Let’s try out some of those very useful, but rarer breed of field types.
There are 3 date and time fields included in Gateway core. Extensions or your own custom code could register additional data handling field types. For now we’ll focus on what is available in core. Each core Gateway field type for date/time handling uses the same underlying React libraries.
We have a field type for each specific requirement, situations where you need:
Memorize the following type keys so you can use these field types easily without having to refer back to docs for basic implementation:
Sorry if the keys seem a little verbose, our aim is typically to match the full human friendly name thus we include “picker” because technically these are picker fields, as opposed to some other date handling or entry field types.
Unless you need a label, these field types for date handling can be initiated with as little as 2 properties name and type:
{
"name": "event_datetime",
"type": "datetime-picker"
}In PHP the equivalent definition would look like:
$fields = [
// Other field definitions.
[
"name" => "event_datetime",
"type" => "datetime-picker"
]
]To recap, in Gateway JSON is the primary language for communicating field definitions. PHP arrays can be used (as they are in $field property in each collection) to create the definition, in which case we just mentally need to shift our thought to the PHP array syntax. The underlying goal remains the same, a flat list (array of fields) where each item is a defined field with at minimum name/type properties and name must be unique and type must be a valid registered field type key.
It’s worth mentioning that some of this work can be skipped in favor of using the Raptor Editor baked into Gateway. This is the admin interface provided which includes a Field Editor that is very similar to the ACF or Metabox list of fields that you might be familiar with. If you are working on a project with a lot of fields, it may save you time to use the editor although it’s hard to compete with copy/paste. Either way it is rare you will define a field by writing every line of code, given there are thousands of example of field definitions in PHP which you can drop into your project to save time.
This is a very advanced field type because under normal usage it will do nothing. A hidden field is exactly that, an HTML5 field of type equals hidden. Only use this field if you are a developer that knows what they want to use the field for. This field type was frequently requested for ACF during its 20+ years as WP’s top field system but was never implemented in core. Developers will often use a hidden field to pass a value along to processing, without wanting the user to be able to edit it. It’s also possible the hidden field is defined without a value, and the value is set by targeting it using JS after the DOM is loaded.
While we won’t cover specific use cases here, it’s worth being aware that the hidden field type does exist and when/if you need it you can reach out to Gateway support for specific handling of your use case on a project. We like projects including hearing about your projects that you plan to build with Gateway!
The Markdown field enables input to a Markdown editor (React Simple MD) and this robust MD editor includes preview and switching between markdown view and render views. There is some configuration available. The field can be defined like most Gateway fields with as little as 2 properties name/type. Use the type=markdown to create this field type.
We highly recommend using this field for situations where you might want markdown content instead of HTML content that you would typically get from a WYSIWYG editor. With the markdown field you will always get valid markdown (although you should still test and filter before trying to parse and render the input). Gateway team uses this field type in Waypoint our documentation engine which runs here at arcwp.ca. We use it as a great way to enable AI to contribute to docs by providing us with draft MD format docs, we then cherry pick through these and enter the content into the doc MD field. Then when we’re closer to publishing the doc we give it another editing round and finally hit publish. For us this provides a pretty good balance between AI-usage, human oversight and fast editing. We’re always just a click away from editing our docs, which we can do by visiting a doc and clicking on the edit doc which takes us straight into the Gateway Studio instance for Waypoint and loads up that specific doc. These are all fairly standard features you might expect in any CMS, but normally this kind of functionality might be limited to Gutenberg block content, or classic WYSIWYG content. The markdown field gives us a whole new way of storing content and that opens the door also to grabbing the MD content from the DB (stored in a normalized table of course) and then parsing the content and using it for example in a static Astro or headless NextJS solution.
We have an oEmbed field which works with a fairly broad range of possible oEmbed services. Because it layers on top of the native WP oEmbed, generally speaking if the oEmbed is available in WP it’s available also using this field. Some exceptions or quirks might apply. Providing an oEmbed field is often a good way to facilitate sharing resources in situations where sharing those resources directly isn’t feasible or secure. For instance instead of allowing video upload directly, we might instead provide an oEmbed field and the user can share YouTube video links instead.
Like all Gateway fields configuration can be as simple as name/type with the type usage defined as “oembed”.
This field is very important because it sits at the core of what makes Gateway a powerful building tool in the WordPress ecosystem. Gateway supports model relationships, namely collections (Eloquent models under the hood) that relate to each other in a managed way using the Eloquent ORM. The relation field turns those underlying relationships into a UI that lets users rapidly create content that is related to other content.
A class example is cars, makes and models. We know that makes have lots of models so this is a one-to-many relationship. We know that models can have many cars so this is another one-to-many relationship. How will this be configured in reverse? Well a car can only have one model, so that’s a many-to-one relationship because we know we’ll have many cars with the same model. We find the pair relation is the same for model to makes because again we know we have many models that each have only one make, so this is a many-to-one relationship.
Although we might often find one-to-many has a many-to-one reverse relationship, it’s good practice to think it through and be clear your choosing the right type.
We won’t cover how to set the relationships here because this topic is fleshed out in depth in several other lessons in this course. What you need to focus on now is that presuming the collection has its relationships establish, the relation field type can do the rest. We just need to configure it, such as the configuration shown below for PHP using the collection $fields property:
// Cars relating to Models using many-to-one relationship. We can presume the relationship is defined using Eloquent standard method relationship handling on this collection by adding protected function model() {}.
protected $fields = [
'model_id' => [
'name' => 'model',
'type' => 'relation',
'label' => 'Make',
'required' => true,
'relation' => [
'endpoint' => 'gateway/v1/models',
'labelField' => 'title',
'valueField' => 'id',
'placeholder' => 'Select a model...',
],
],
// ...Other fields for this collection
]What’s going on in the field configuration above? First notice we’re using the same protected $fields that we have for every other field configuration. Nothing new there, relation fields are special but they are defined in the same place using the same format as any other field. The type, label, required are self-explanatory. Let’s hone in on the unique property “relation”. The first option is the endpoint, which refers to the endpoint where we can fetch the related records. In this case the relationship is to a “Models Collection” and with it’s routing configuration being default, the route segment after wp-json/ is “gateway/v1/models”. This refers to the “fetch all” or [GET] protocol that is open to the public.
The label field, value field each serve their role in the configuration. The label field is not the label string, instead it’s telling the relation field look for the “title” field on each model record, and use that to be the label for that row. This helps the user identify the record when picking from a list. Remember that unlike WP core where title field almost always exists, in Gateway a collection may have no discernable title field or equivalent like label, name etc. You should provide something that allows the user to distinguish records from one another, perhaps in your use case this is specific to your collection.
The valueField is by default “id” so we only need to specify this if we need to alter it. In most cases if you are establishing collections in a standard way you’ll have a unique auto-incrementing “id” field and will want this to be the reference for the relationship. Also note that this must match what you already used when establishing the underlying Eloquent model relationship for instance in this case what the configuration is in model() method on the car collection class.