@@ -17,12 +17,13 @@ Use this file as a comprehensive reference when creating the `multi-block-plugin
17177 . Shared React components (Slider, Repeater, etc.)
18188 . Post Collection block (similar to WooCommerce Product Collection)
19199 . Complete uninstall cleanup and test suite
20+ 10 . ** WordPress Plugin Dependencies** (` Requires Plugins ` header) for SCF dependency
2021
2122---
2223
2324## Repository Structure
2425
25- ```
26+ ``` text
2627multi-block-plugin-scaffold/
2728├── {{slug}}.php # Main plugin file
2829├── uninstall.php # Uninstall cleanup
@@ -185,6 +186,10 @@ multi-block-plugin-scaffold/
185186
186187### Main Plugin File (` {{slug}}.php ` )
187188
189+ ** Important:** WordPress 6.5+ introduced Plugin Dependencies. The ` Requires Plugins ` header declares that this plugin requires Secure Custom Fields. WordPress will prevent activation until SCF is installed and active.
190+
191+ See: [ WordPress Plugin Dependencies] ( https://make.wordpress.org/core/2024/03/05/introducing-plugin-dependencies-in-wordpress-6-5/ )
192+
188193``` php
189194<?php
190195/**
@@ -194,6 +199,7 @@ multi-block-plugin-scaffold/
194199 * Version: {{version}}
195200 * Requires at least: {{requires_wp}}
196201 * Requires PHP: {{requires_php}}
202+ * Requires Plugins: secure-custom-fields
197203 * Author: {{author}}
198204 * Author URI: {{author_uri}}
199205 * License: {{license}}
@@ -214,6 +220,26 @@ define( '{{namespace|upper}}_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
214220define( '{{namespace|upper}}_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
215221define( '{{namespace|upper}}_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
216222
223+ /**
224+ * Defensive coding: Check for SCF/ACF functions before using them.
225+ *
226+ * While Plugin Dependencies ensures SCF is active, defensive coding is still
227+ * recommended for:
228+ * - Edge cases (FTP deletion, deployment issues)
229+ * - Loading order variations
230+ * - Future compatibility
231+ *
232+ * @see https://make.wordpress.org/core/2024/03/05/introducing-plugin-dependencies-in-wordpress-6-5/
233+ */
234+ if ( ! function_exists( 'acf_add_local_field_group' ) ) {
235+ add_action( 'admin_notices', function() {
236+ echo '<div class =" error" ><p >' .
237+ esc_html__( '{{name}} requires Secure Custom Fields to be active.', '{{textdomain}}' ) .
238+ '</p ></div >';
239+ } );
240+ return;
241+ }
242+
217243// Autoloader.
218244require_once {{namespace|upper}}_PLUGIN_DIR . 'vendor/autoload.php';
219245
@@ -1938,12 +1964,174 @@ module.exports = {
19381964## Dependencies
19391965
19401966### Required
1941- - WordPress 6.5+ (for Block Bindings API)
1967+
1968+ - WordPress 6.5+ (for Block Bindings API and Plugin Dependencies)
19421969- PHP 8.0+
19431970- Node.js 18+
1971+ - ** Secure Custom Fields** (declared via ` Requires Plugins ` header)
1972+
1973+ ### WordPress Plugin Dependencies (WP 6.5+)
1974+
1975+ The ` Requires Plugins ` header in the main plugin file declares SCF as a required dependency:
1976+
1977+ ``` php
1978+ Requires Plugins: secure-custom-fields
1979+ ```
1980+
1981+ ** Behaviour:**
1982+
1983+ - Plugin cannot be installed until SCF is installed
1984+ - Plugin cannot be activated until SCF is activated
1985+ - SCF cannot be deactivated while this plugin is active
1986+ - SCF cannot be deleted while this plugin is installed
1987+
1988+ ** Reference:** [ WordPress Plugin Dependencies] ( https://make.wordpress.org/core/2024/03/05/introducing-plugin-dependencies-in-wordpress-6-5/ )
1989+
1990+ ### Defensive Coding
1991+
1992+ While Plugin Dependencies ensures SCF is active, defensive coding is still recommended:
1993+
1994+ ``` php
1995+ // Check for SCF/ACF functions before using them.
1996+ if ( function_exists( 'acf_add_local_field_group' ) ) {
1997+ // Register fields.
1998+ }
1999+
2000+ if ( function_exists( 'get_field' ) ) {
2001+ $value = get_field( 'my_field', $post_id );
2002+ }
2003+
2004+ if ( function_exists( 'have_rows' ) && have_rows( 'my_repeater', $post_id ) ) {
2005+ while ( have_rows( 'my_repeater', $post_id ) ) {
2006+ the_row();
2007+ // Process row.
2008+ }
2009+ }
2010+ ```
2011+
2012+ ---
2013+
2014+ ## Secure Custom Fields Documentation
2015+
2016+ ### Key SCF Resources
2017+
2018+ - ** Plugin:** < https://wordpress.org/plugins/secure-custom-fields/ >
2019+ - ** GitHub:** < https://github.com/WordPress/secure-custom-fields >
2020+ - ** Documentation:** < https://github.com/WordPress/secure-custom-fields/tree/trunk/docs >
2021+
2022+ ### Field Types Used in This Scaffold
2023+
2024+ | Field Type | Description | Documentation |
2025+ | ------------| -------------| ---------------|
2026+ | Text | Single line text | ` docs/features/field/text/ ` |
2027+ | Textarea | Multi-line text | ` docs/features/field/textarea/ ` |
2028+ | Image | Image upload | ` docs/features/field/image/ ` |
2029+ | Gallery | Multiple images | ` docs/features/field/gallery/ ` |
2030+ | Repeater | Repeating subfields | ` docs/features/field/repeater/ ` |
2031+ | Flexible Content | Layout-based editor | ` docs/features/field/flexible-content/ ` |
2032+ | Post Object | Post relationships | ` docs/features/field/post-object/ ` |
2033+ | Link | URL with title | ` docs/features/field/link/ ` |
2034+ | Select | Dropdown selection | ` docs/features/field/select/ ` |
2035+ | True/False | Boolean toggle | ` docs/features/field/true-false/ ` |
2036+
2037+ ### SCF API Functions
2038+
2039+ ** Getting Field Values:**
2040+
2041+ ``` php
2042+ // Get single field value.
2043+ $value = get_field( 'field_name', $post_id );
2044+
2045+ // Get all fields for a post.
2046+ $fields = get_fields( $post_id );
2047+
2048+ // Get field object (with settings).
2049+ $field = get_field_object( 'field_name', $post_id );
2050+ ```
2051+
2052+ ** Repeater Fields:**
2053+
2054+ ``` php
2055+ // Loop through repeater.
2056+ if ( have_rows( 'repeater_name', $post_id ) ) {
2057+ while ( have_rows( 'repeater_name', $post_id ) ) {
2058+ the_row();
2059+
2060+ // Get sub field values.
2061+ $title = get_sub_field( 'title' );
2062+ $image = get_sub_field( 'image' );
2063+ }
2064+ }
2065+
2066+ // Reset repeater (if nested).
2067+ reset_rows();
2068+ ```
2069+
2070+ ** Flexible Content:**
2071+
2072+ ``` php
2073+ // Loop through flexible content.
2074+ if ( have_rows( 'sections', $post_id ) ) {
2075+ while ( have_rows( 'sections', $post_id ) ) {
2076+ the_row();
2077+
2078+ // Get current layout name.
2079+ $layout = get_row_layout();
2080+
2081+ if ( 'text_section' === $layout ) {
2082+ $heading = get_sub_field( 'heading' );
2083+ $content = get_sub_field( 'content' );
2084+ } elseif ( 'gallery_section' === $layout ) {
2085+ $images = get_sub_field( 'gallery' );
2086+ }
2087+ }
2088+ }
2089+ ```
2090+
2091+ ** Registering Fields Programmatically:**
2092+
2093+ ``` php
2094+ // Register field group.
2095+ acf_add_local_field_group( array(
2096+ 'key' => 'group_my_fields',
2097+ 'title' => 'My Fields',
2098+ 'fields' => array(
2099+ array(
2100+ 'key' => 'field_my_text',
2101+ 'label' => 'My Text',
2102+ 'name' => 'my_text',
2103+ 'type' => 'text',
2104+ ),
2105+ ),
2106+ 'location' => array(
2107+ array(
2108+ array(
2109+ 'param' => 'post_type',
2110+ 'operator' => '==',
2111+ 'value' => 'my_post_type',
2112+ ),
2113+ ),
2114+ ),
2115+ ) );
2116+ ```
2117+
2118+ ### SCF REST API
2119+
2120+ SCF fields are exposed via the WordPress REST API when enabled:
2121+
2122+ ``` php
2123+ // In field group settings, set 'show_in_rest' => true.
2124+ acf_add_local_field_group( array(
2125+ 'key' => 'group_my_fields',
2126+ 'show_in_rest' => true,
2127+ // ... other settings
2128+ ) );
2129+ ```
2130+
2131+ ** REST API Endpoints:**
19442132
1945- ### Recommended
1946- - [ Secure Custom Fields ] ( https://wordpress.org/plugins/secure-custom-fields/ ) for custom fields
2133+ - ` GET /wp-json/wp/v2/{post_type}?_fields=acf ` – Get posts with ACF fields
2134+ - Fields appear in the ` acf ` object on post responses
19472135
19482136---
19492137
0 commit comments