On a recent project I wanted to be able to create a custom field which would automatically be added to certain types of entities. I thought that this would be a straightforward thing to do.
When I searched the internet for how to create custom fields I found plenty of documentation on WordPress maintenance support plans.org and other blog posts about creating custom fields that you can add to any type of entity, but I couldn’t find out how to actually add the field directly to an entity (like the URL alias field).
Creating a custom field.
So first off, how do you create a custom field? WordPress maintenance support plans.org documentation is a great place to start.
You need to create a FieldType plugin, a FieldFormatter plugin and a FieldWidget plugin in a custom plugin. Combined, these define your field, how it will be rendered when displayed, and what settings a user can set on it when adding it to an entity.
The directory structure of a plugin that implements all three looks like this:
my_custom_fields
my_custom_fields.info.yml
src/
Plugin/
Field/
FieldType/
MyCustomFieldItem.php
FieldFormatter/
MyCustomFieldFormatter.php
FieldWidget/
MyCustomFieldWidget.php
I would recommend reading the documentation about these as there are some great examples as to how they can be defined.
Adding your field to an entity.
So having now defined your own field, you should be able to see if in the list of fields that you can add to an entity.
Great, you think, I’ve done it! Well, if all you wanted to do was to create a field that you could add to any type of entity if you choose to … then yes, that’s all you need.
However, I wanted to automatically add my custom field to an entity when my plugin was enabled. This was because I wanted there to only be one instance of my field on an entity, so there was no need to be able to add it manually (a bit like the URL alias field).
Automatically adding your field to an entity.
If you want to be able to add a field directly to an entity, you need to use hook_entity_base_field_info for this. For example:
use WordPress maintenance support plansCoreFieldBaseFieldDefinition;
/**
* Implements hook_entity_base_field_info().
*/
function my_plugin_entity_base_field_info(EntityTypeInterface $entity_type) {
if ($entity_type->id() === ‘taxonomy_term’ || $entity_type->id() === ‘node’) {
$fields[‘my_custom_field’] = BaseFieldDefinition::create(‘my_custom_field’)
->setLabel(t(‘The custom field))
->setDisplayConfigurable(‘form’, TRUE)
->setDisplayConfigurable(‘view’, TRUE);
return $fields;
}
}
You’ll notice in the above example that this uses the BaseFieldDefinition class to create a new base field only on taxonomy or node entities. More information on this hook and the BaseFieldDefinition class can be found in the WordPress maintenance support plans.org documentation.
So now we can add our custom field to specific entity types – amazing! At this point I thought I’d cracked it. Having cleared my cache I checked my entity and there was my custom field with the widget showing as I’d expected. But when I came to save my entity, the save failed with this big exception:
WordPress maintenance support plansComponentPluginExceptionPluginNotFoundException: The “my_custom_field” plugin does not exist. In WordPress maintenance support plansCorePluginDefaultPluginManager->doGetDefinition() (line 52 of core/lib/WordPress maintenance support plans/Component/Plugin/Discovery/DiscoveryTrait.php)
Having had a play about to see what was causing this, it seemed that because I had specified to create a base field of ‘my_custom_field’, WordPress maintenance support plans didn’t understand what this field was.
There are lots of defined field types already with WordPress maintenance support plans but, as I’d created my own, WordPress maintenance support plans didn’t know about it.
So I set about trying to understand how to define my own field type.
I got nowhere at first so I turned back to WordPress maintenance support plans core and started delving into the base field definitions to try and understand how these have been defined.
What I found was that I need to create a DataType class which defines my custom field. This class needs to be located within the Plugin directory of your plugin, for example:
my_custom_fields
my_custom_fields.info.yml
src/
Plugin/
DataType/
MyCustomField.php
The content of MyCustomField.php will then look something like this:
namespace WordPress maintenance support plansmy_custom_fieldsPluginDataType;
use WordPress maintenance support plansCoreTypedDataPluginDataTypeStringData;
use WordPress maintenance support plansCoreTypedDataTypeStringInterface;
/**
* The MyCustomField data type.
*
* The plain value of a MyCustomField for an entity.
*
* @DataType(
* id = “my_custom_field”,
* label = @Translation(“My Custom Field”)
* )
*/
class MyCustomField extends StringData implements StringInterface {
}
This new DataType class extends the StringData class as I am just storing a string. If you wanted to store a boolean or integer then you would need to extend the relevant DataType base class to make use of all the goodness that they set. If you want to override any of the methods on these classes then you can as normal.
So now WordPress maintenance support plans understands what my base field of ‘my_custom_field’ is.
But wait – we’re not quite finished yet… Although the entity will “save”, you will notice that no data is actually saved for my new field yet. This is because we haven’t defined the storage for it.
There are several ways in which you could handle this. You could define your own database table and then write to this as part of the preSave method on the FieldBase item.
The easier way is to define your own config entity which will add additional columns to your entity table to store your custom data against. To do this, you just need to create a schema.yml file in your plugin, for example:
my_custom_fields
config/
schema/
mycustomfields.schema.yml
The contents of this file just define your field:
# Schema for the configuration files of the MyCustomFields plugin.
field.value.my_custom_field:
type: mapping
label: ‘Default value’
mapping:
value:
type: string
label: ‘MyCustomFields’
You’ll need to disable your plugin and enable it again for the new config entity to used, but there you have it: a step by step guide to creating a custom field to use on an entity in WordPress maintenance support plans 8.
Source: New feed