-
Notifications
You must be signed in to change notification settings - Fork 10
Supports ACF
- Article is under construction
Advanced Custom Fields is a famous plugin to create custom fields for Pages, Posts, Custom Post Types, Taxonomy terms, Users and Option pages.
This plugin is really cool, however moving it still has few issues to resolve.
- Moving fields configuration between environments
- Fields UI
ACF stores its configuration inside wp_posts
/wp_postmeta
/wp_options
tables in database.
Collecting all these settings together from the database takes time. And you need to export/import your
configuration when you have several environments (like develop/production). ACF has an option to
import settings as a PHP file, however it's too hard to edit and support such code.
We believe that fields configuration have to be stored under VCS, this makes all processes easier. We found a good package which can help you with defining fields inside the code: https://github.com/StoutLogic/acf-builder/wiki
It's easy to use, however still not good enough :) To stay DRY (Don't Repeat Yourself), you need to break duplicated definitions in separate files, then include them, you need to move init hook somewhere as well. That's why we created few classes, which do all dirty job for you.
Inside our framework we have 2 main classes to work with ACF fields:
- ACF_Definition is a base class for repeatable fields definitions like Flexible Content Layouts, generic fields (for example Color or Background settings).
- ACF_Register is a base class for registering all fields together and match them with a content types, user form or custom options page.
Both classes has 2 similar methods has()
and build()
.
has()
method is used to add fields definitions to an internal property (some type of cache).
build()
method is a wrapper for new FieldsBuilder($name, $config)
statement.
To create a re-usable field definition you need to create a child class and write init()
method with
combination of has()
and build()
calls.
For example let's create a module to print a Hero banner fields
{theme}/app/Fields/Modules/Module_Hero.php
<?php
namespace Boilerplate\Theme\Fields\Modules;
use JustCoded\WP\Framework\ACF\ACF_Definition;
class Module_Hero extends ACF_Definition {
/**
* Init fields configuration method
*/
public function init() {
$this->has(
$this->build( 'module_hero' )
->addText( 'hero_title' )
->addImage( 'hero_image' )
->addWysiwyg( 'hero_text' )
);
}
}
And one more example of common fields, which can be used inside different modules:
<?php
namespace Boilerplate\Theme\Fields\Modules;
use JustCoded\WP\Framework\ACF\ACF_Definition;
class Fields_Generic extends ACF_Definition {
/**
* Init fields configuration method
*/
public function init() {
$this->has(
$this->build( 'subtitle' )
->addText( 'subtitle', ['label' => 'Subtitle'] )
->setRequired(true)
->setInstructions('Smaller title, usually printed under primary title or name.'),
$this->build( 'color' )
->addSelect( 'color' )
->addChoice( 'red' )
->addChoice( 'blue' )
->addChoice( 'green' )
->setDefaultValue( 'blue' )
);
}
}
Note: Each build()
call have to use a unique name. Using this name you will be able to get this field group later._
As you can see if we use standard ACF admin UI or manual functions to create configs - we will need to repeat such general configurations and will duplicate them a lot of times.
Now to get a field group object you need to call a static method get()
like this:
-
Module_Hero::get()
will return a full group. -
Fields_Generic::get('subtitle')
will return a single 'subtitle' field definition.
Field groups objects can be used inside other builders to add fields with addFields()
method.
(If you have an ACF PRO version and use Flexible Content, then you can also use them inside addLayout()
method).
With help of another base class we can register them. Actually a base class just has acf/init
hook
registratino and a call of a standard acf_add_local_field_group()
function.
It works absolutely the same as Definition class - you need to write an init()
method.
The only difference - you also need to specify a location property for your fields.
For example let's define extra fields for a Page:
<?php
namespace Boilerplate\Theme\Fields;
use Boilerplate\Theme\Fields\Modules\Fields_Generic;
use Boilerplate\Theme\Fields\Modules\Module_Hero;
use JustCoded\WP\Framework\ACF\ACF_Register;
class Page_Fields extends ACF_Register {
/**
* Init fields configuration method
*/
public function init() {
$this->has(
$this->build()
->addFields( Fields_Generic::get( 'subtitle' ) )
->addFields( Module_Hero::get() )
->setLocation( 'post_type', '==', 'page' )
);
}
}
If you want to define an Options page - you can use add_options_page()
method to define it
(it's actually an ACF wrapper, which will check for ACF installed).
And after that you define your fields in similar way as before.
<?php
namespace Boilerplate\Theme\Fields;
use JustCoded\WP\Framework\ACF\ACF_Register;
class Theme_Fields extends ACF_Register {
/**
* Init fields configuration method
*/
public function init() {
$this->add_options_page( 'Theme options' );
$this->has(
$this->build()
->addTab( 'Socials Links' )
->addFields( $this->socials_tab() )
->addTab( '404 Page' )
->addFields( $this->page_404_tab() )
->setLocation( 'options_page', '==', 'acf-options-theme-options' )
);
}
protected function socials_tab() {
return $this->build( 'socials_options' )
->addText( 'social_fb', [ 'label' => 'Facebook Page' ] )
->setDefaultValue( 'http://facebook.com/my-page' )
->addText( 'social_twitter', [ 'label' => 'Twitter account' ] )
->setDefaultValue( 'http://twitter.com/@some-username' )
->addText( 'social_gplus', [ 'label' => 'Google+' ] )
->setDefaultValue( 'https://plus.google.com/-unique-profile-id-' )
->getRootContext();
}
protected function page_404_tab() {
return $this->build( '404_options' )
->addText( 'page_404_title', [ 'label' => '404 Page Title' ] )
->addWysiwyg( 'page_404_content', [ 'label' => '404 Page Content' ] )
->getRootContext();
}
}