Extended ACF

repository·master·Indexed 19 days ago

https://github.com/vinkla/extended-acf

An object-oriented PHP API for registering Advanced Custom Fields (ACF) groups and fields in WordPress. It simplifies the registration process using a fluent, class-based syntax, automatic unique field key management, and helper classes for location rules and conditional logic. It supports a wide range of ACF field types including basic, content, choice, relational, advanced, and layout fields, and provides additional features like bidirectional relationships and Markdown-supported helper text.

Tokens
11.8K
Snippets
53
Records
54
Agent score
67%

What's inside extended-acf

  1. Configure Extended ACF Fields

    master

    All fields in Extended ACF (except the Clone field) are instantiated via a specific class.

    Naming Convention:

    • Every field requires a label.
    • If a name is not explicitly provided, the label is converted to snake_case and used as the field name.
    • The name must only contain alphanumeric characters and underscores.

    Common Methods: Most fields support:

    • default($value): Sets a default value.
    • required(): Makes the field mandatory.
    • wrapper($options): Configures the field wrapper.

    Basic Field Methods: Basic fields also support:

    • prepend($text)
    • append($text)
    • placeholder($text)
    • readOnly()
    • disabled()
    use Extended\ACF\Fields\Text;
    
    Text::make('Title', 'heading')
        ->helperText('Add the text value')
        ->required();
  2. Add custom functionality using Macros

    master

    Macros allow you to add reusable methods to all field classes at runtime without creating new classes.

    Best Practices:

    1. Register macros on the Extended\ACF\Fields\Field class.
    2. Use the acf/init hook to ensure macros are registered before field groups are defined.
    3. For type-specific macros, check the instance type using instanceof and throw a BadMethodCallException if the method is called on an incompatible field type.

    Example: Global Macro

    use Extended\ACF\Fields\Field;
    
    add_action('acf/init', function () {
        Field::macro('translatable', function (Field $field): static {
            return $field->withSettings(['translatable' => true]);
        });
    });

    Example: Type-Specific Macro

    Field::macro('maxLength', function (Field $field, int $length): static {
        if (!$field instanceof Text) {
            throw new BadMethodCallException('maxLength only works on Text fields');
        }
        return $field->withSettings(['maxlength' => $length]);
    });
    use Extended\ACF\Fields\Field;
    use Extended\ACF\Fields\Location;
    
    add_action('acf/init', function () {
        Field::macro('translatable', function (Field $field): static {
            return $field->withSettings(['translatable' => true]);
        });
    });
    
    add_action('acf/include_fields', function () {
        register_extended_field_group([
            'title' => 'About',
            'fields' => [
                Text::make('Title')->translatable(),
                Textarea::make('Description')->translatable(),
            ],
            'location' => [
                Location::where('post_type', 'page'),
            ],
        ]);
    });
  3. Implement conditional logic for fields

    master

    The ConditionalLogic class enables you to show or hide fields based on the values of other fields without needing to know their specific ACF field keys.

    Available Operators

    ==, !=, >, <, ==pattern, ==contains, ==empty, !=empty.

    Logic Patterns

    • AND condition: Chain .and() methods.
    • OR condition: Pass multiple ConditionalLogic::where() calls within the conditionalLogic() array.
    • Cross-group logic: Use the group parameter in where() to reference a field from a different field group.

    Example

    Select::make('Type')
        ->choices(['document' => 'Document', 'link' => 'Link', 'embed' => 'Embed']),
    
    File::make('Document', 'file')
        ->conditionalLogic([
            ConditionalLogic::where('type', '==', 'document')
        ]),
    
    // OR condition using multiple entries in the array
    Text::make('Title')
        ->conditionalLogic([
            ConditionalLogic::where('type', '!=', 'document'),
            ConditionalLogic::where('type', '!=', 'link')
        ]),
    
    // Cross-group condition
    Text::make('Sub Title')
        ->conditionalLogic([
          ConditionalLogic::where(
            group: 'other-group',
            name: 'enable_highlight', 
            operator: '==', 
            value: 'on', 
          )
        ]),
    use Extended\ACF\ConditionalLogic;
    use Extended\ACF\Fields\File;
    use Extended\ACF\Fields\Select;
    use Extended\ACF\Fields\URL;
    use Extended\ACF\Fields\Textarea;
    use Extended\ACF\Fields\Text;
    
    Select::make('Type')
        ->choices([
            'document' => 'Document',
            'link' => 'Link to resource',
            'embed' => 'Embed',
        ]),
    File::make('Document', 'file')
        ->conditionalLogic([
            ConditionalLogic::where('type', '==', 'document')
        ]),
    URL::make('Link', 'url')
        ->conditionalLogic([
            ConditionalLogic::where('type', '==', 'link')
        ]),
    
    Textarea::make('Embed Code')
        ->conditionalLogic([
            ConditionalLogic::where('type', '!=', 'document')->and('type', '!=', 'link')
        ]),
    
    Text::make('Title')
        ->conditionalLogic([
            ConditionalLogic::where('type', '!=', 'document'),
            ConditionalLogic::where('type', '!=', 'link')
        ]),
    
    Text::make('Sub Title')
        ->conditionalLogic([
          ConditionalLogic::where(
            group: 'other-group',
            name: 'enable_highlight', 
            operator: '==', 
            value: 'on', 
          )
        ]);
  4. Migrate from wordplate/acf to vinkla/extended-acf

    master

    If you are upgrading from version 12 or lower, the package has been renamed. You must update your composer.json to use the new package name.

    -"wordplate/acf": "^12.0",
    +"vinkla/extended-acf": "^12.0"
  5. Create custom field classes

    master

    To create a custom field, extend the Extended\ACF\Fields\Field base class. You can also use setting traits (like HelperText or Required) to quickly add standard ACF functionality to your custom class.

    Implementation Steps

    1. Extend Field.
    2. Define the $type property (the ACF field type string).
    3. Use traits for common settings.
    4. Add custom methods that return static to allow chaining.

    Example

    namespace App\Fields;
    
    use Extended\ACF\Fields\Field;
    use Extended\ACF\Fields\Settings\HelperText;
    use Extended\ACF\Fields\Settings\Required;
    
    class OpenStreetMap extends Field
    {
        use HelperText;
        use Required;
    
        protected $type = 'open_street_map';
    
        public function latitude(float $latitude): static
        {
            $this->settings['latitude'] = $latitude;
            return $this;
        }
        
        // ... other methods
    }
    
    // Usage
    OpenStreetMap::make('Map')
        ->latitude(56.474)
        ->longitude(11.863)
        ->zoom(10);
    namespace App\Fields;
    
    use Extended\ACF\Fields\Field;
    use Extended\ACF\Fields\Settings\HelperText;
    use Extended\ACF\Fields\Settings\Required;
    
    class OpenStreetMap extends Field
    {
        use HelperText;
        use Required;
    
        protected $type = 'open_street_map';
    
        public function latitude(float $latitude): static
        {
            $this->settings['latitude'] = $latitude;
            return $this;
        }
        
        public function longitude(float $longitude): static
        {
            $this->settings['longitude'] = $longitude;
            return $this;
        }
        
        public function zoom(float $zoom): static
        {
            $this->settings['zoom'] = $zoom;
            return $this;
        }
    }
    
    // Usage
    use App\Fields\OpenStreetMap;
    
    OpenStreetMap::make('Map')
        ->latitude(56.474)
        ->longitude(11.863)
        ->zoom(10);
  6. Upgrade to v13 (Namespace Change)

    master

    In version 13, the namespace was changed from WordPlate\Acf to Extended\ACF. You must update all imports in your codebase.

    -// Old Namespace
    -use WordPlate\Acf\Fields\Text;
    -
    -// New Namespace
    +use Extended\ACF\Fields\Text;
  7. Install Extended ACF via Composer

    master

    Install the package using Composer in your project's root directory.

    Note: This package requires the Advanced Custom Fields plugin to be installed and activated in WordPress. If you are using ACF Pro, you can install it via Composer by placing it in your plugins or mu-plugins directory.

    composer require vinkla/extended-acf
  8. Register a field group with register_extended_field_group()

    master

    To register a new field group using an object-oriented approach, use the register_extended_field_group() function. This function extends the standard ACF register_field_group() function by automatically handling unique field keys.

    You should wrap your registration inside the acf/include_fields action hook to ensure ACF is loaded.

    Key components:

    • title: The name of the field group.
    • fields: An array of field objects created using the ::make() method.
    • location: An array of location rules, typically constructed using the Location::where() helper.
    use Extended\ACF\Fields\Image;
    use Extended\ACF\Fields\Text;
    use Extended\ACF\Location;
    
    add_action('acf/include_fields', function() {
        register_extended_field_group([
            'title' => 'About',
            'fields' => [
                Image::make('Image'),
                Text::make('Title'),
            ],
            'location' => [
                Location::where('post_type', 'page')
            ],
        ]);
    });
  9. Upgrade to v12 (Method and Namespace Changes)

    master

    Version 12 introduced several breaking changes:

    • The Attributes namespace was renamed to Settings.
    • The toArray() method on Field, Location, and ConditionalLogic was renamed to get().
    • The if() method on Location and ConditionalLogic was renamed to where().
    • Removed: field() and option() helper functions, setParentKey() methods, conditional logic comparison methods, and the configuration and field group classes.
    -// Attributes -> Settings
    -use Extended\ACF\Fields\Attributes\Required;
    +use Extended\ACF\Fields\Settings\Required;
    
    -// toArray -> get
    -$field->toArray();
    +$field->get();
    
    -// if -> where
    -Location::if('post_type', 'post');
    +Location::where('post_type', 'post');
  10. Upgrade to v11 (Naming Conventions)

    master

    Version 11 updated naming conventions:

    • Field names are now automatically formatted as snake_case instead of kebab-case.
    • Radio field was renamed to RadioButton.
    • Wysiwyg field was renamed to WysiwygEditor.
    -// Field name formatting
    -Text::make('Organization Number'); // organization-number
    +Text::make('Organization Number'); // organization_number
    
    -// Class Renames
    -Radio::make('Color');
    +RadioButton::make('Color');
  11. Upgrade to v14 (PHP 8.2)

    master

    Upgrading to version 14 requires PHP 8.2 or higher. This version introduced significant renaming of classes, methods, and traits to improve consistency.

    Class Renames

    • Url $\rightarrow$ URL
    • WysiwygEditor $\rightarrow$ WYSIWYGEditor

    Method Renames

    • defaultValue() $\rightarrow$ default()
    • instructions() $\rightarrow$ helperText()
    • allowMultiple() $\rightarrow$ multiple()
    • allowNull() $\rightarrow$ nullable()
    • characterLimit() $\rightarrow$ maxLength()
    • pagination() $\rightarrow$ paginated()
    • buttonLabel() $\rightarrow$ button()
    • weekStartsOn() $\rightarrow$ firstDayOfWeek()
    • prepend() $\rightarrow$ prefix()
    • append() $\rightarrow$ suffix()
    • mimeTypes() $\rightarrow$ acceptedFileTypes()
    • enableOpacity() $\rightarrow$ opacity()
    • delay() $\rightarrow$ lazyLoad()
    • message() $\rightarrow$ body()
    • insert() $\rightarrow$ prependFiles()
    • returnFormat() $\rightarrow$ format() (on all fields)

    Method Behavior Changes

    • TrueFalse::stylisedUi() is now stylized() (with on: argument) or lazyLoad() for Select fields.
    • WysiwygEditor::mediaUpload(false) is now disableMediaUpload().
    • PageLink::allowArchives(false) is now disableArchives().
    • Taxonomy methods addTerm(), loadTerms(), and saveTerms() are now create(), load(), and save().

    Split Methods

    • Image::fileSize() $\rightarrow$ minSize() and maxSize()
    • Gallery::height() $\rightarrow$ minHeight() and maxHeight()
    • Image::width() $\rightarrow$ minWidth() and maxWidth()

    Context-Specific Min/Max Renames

    FieldOldNew
    Gallerymin / maxminFiles / maxFiles
    Relationshipmin / maxminPosts / maxPosts
    Repeatermin / maxminRows / maxRows
    FlexibleContentmin / maxminLayouts / maxLayouts
    Layoutmin / maxminInstances / maxInstances

    Trait Renames (for Custom Fields)

    OldNew
    InstructionsHelperText
    MimeTypesFileTypes
    CharacterLimitMaxLength
    PendingAffixable
    WritableImmutable
    SubFieldsFields
    -// Class Renames
    -use Extended\\ACF\\Fields\\Url;
    +use Extended\\ACF\\Fields\\URL;
    
    -// Method Renames
    -Text::make('Name')->defaultValue('Jeffrey Way');
    +Text::make('Name')->default('Jeffrey Way');
    
    -// Split Methods
    -Image::make('Product Image')->width(100, 1000);
    +Image::make('Product Image')->minWidth(100)->maxWidth(1000);
  12. Debug fields with dd() and dump()

    master

    The dd() and dump() methods are available for debugging field definitions. These are non-standard and require the symfony/var-dumper package to be installed via Composer.

    composer require symfony/var-dumper --dev
    Text::make('Name')
        ->dd()
        ->dump();