Working with Field Sets and Fields
Given that custom field sets and fields are a key MasterPress feature, one of the major concerns of the MasterPress API involves getting the content stored by these fields into your theme templates. Like everything else in the API, we’ve endeavoured to make this as easy as possible.
First though, let’s run through how field sets and fields are represented in the MasterPress user interface, and how that relates directly to the API, by way of a concrete example.
Our car post type
To illustrate how we access custom fields using the MasterPress API, we’ve setup an example post type to create posts about cars, named “car”. Now, let’s assume we’ve used MasterPress to setup a single-item “details” field set to store content about our cars, which looks like this:
Figure 1: The "details" field set for our cars
At this stage, it’s worth noting how the “Front End Name” column in the grid is designed to give you an indication of how to access the fields in theme code. It would suggest that once you’ve got a post object, you might access the “make” field via the property details->make – and this is indeed correct.
One other thing to note about our post type – we’ve only switched on the “title” feature in our “Supports” panel, since we intend to replace the standard content field entirely:
Figure 2: Our supports setup in the Edit Post Type screen
Now let’s look at an example post for the Type 1 beetle, with content supplied by this entry from Wikipedia. Note how the details field set in MasterPress maps directly to a metabox panel in WordPress containing all of the fields within.
Figure 3: An example car
Accessing the car fields
So we’ve established an example field set with some sample content. Now let’s take a look at how we access these fields in our template.
Here is the code we could use in a single-car.php template for our car post type:
Example 1: Accessing our custom fields
Note that there is quite a bit happening behind the scenes to allow this code to be so concise. This is covered in detail in the article Dynamic properties and string conversion which contains a very similar example to the one above, so please read through that first if you’re curious about how this works.
It’s also worth noting that the code in Example 1 could be wrapped in a standard construct for “The Loop”, but this is not actually required in this case.
Checking for the presence of field values with the has method
Example 1 makes the assumption that all of the fields have actually been provided with a value. If they haven’t been however, we will see a few holes when viewing the post at the front-end, which is undesirable.
All of the API objects that can contain custom field sets or fields have a has method to help us deal with this in a very intuitive way. Let’s take a look at another example which refines Example 1 to check for certain fields before outputting the surrounding HTML tags:
Example 2: Checking for the presence of specific fields
As you can see, we’ve now placed conditions around the “years_in_production” and “detailed_description” fields, so that they won’t output the surrounding HTML if field values haven’t been provided. In this case, the method we’re using to do this is MEOW_FieldSetCollection::has.
One thing you may notice about Example 2 though is that the checks for field values are a little clumsy in that you need to repeat the field name within each if statement. We can improve on this code slightly by noting that the MEOW_FieldSetCollection::has method will return false if the field doesn’t exist or have a value, but the field itself if it does. Using this fact, we can actually use our if statements to assign a quick variable as well, so we don’t have to repeat ourselves.
Example 3: Using quick assignment with "has"
Note that this technique is the same as the quick-assignment technique for the exists method.
Field Type APIs
The MasterPress API uses the concept of class delegates to allow certain objects within the API to make use of the methods of another class, just as if the methods were part of the original object. Please refer to the Class Delegates article for detailed information on how this mechanism works.
This is important when you’re looking up information on the methods available for specific field types. Suppose that you’re trying to lookup the methods supported by the image field type. The Class Reference contains a “Field Types” package with a list of classes prefixed with “MPFT_” that represent the core field types in MasterPress, and our image field is represented by MPFT_Image, so this class entry is the first step.
If you visit the MPFT_Image entry you’ll note that there aren’t too many methods listed there, and we’ve already used a resize method, which isn’t listed. This is because the image type delegates to the WOOF_Image class, meaning that all of the methods available in WOOF_Image are available to the image field type:
Figure 4: The Image field type delegate
This is a powerful concept that allows our API to be very intuitive and concise. It’s worth keeping this in mind when you use the class reference, since the more complex field types will obtain most of their very specific functionality from delegates rather than the extended class.
Multiple-Item Field Sets
Building upon our car example, we’ve now decided that we want a way to store even more photos of our car. We can setup a multiple-item field set called “photos” in MasterPress to achieve this. Note how the icon for a multi-item field set has a little “plus” and “minus” badge to indicate that you can add and remove items from this set.
Figure 5: Our multiple item field set to store "photos"
Now we can enter our photos on the Edit Car screen, to end up with something like this:
Figure 6: More photos of the beetle
A big thanks to Flickr user thorstenhaustein for the photos used in this example!
Now let’s take a look at the code to get these photos into our template:
Example 4: Looping over our photos
There are a number of things to note about this example:
- For multi-item field sets, we can simply iterate over them directly using a foreach loop. This is made possible by the fact that MEOW_FieldSetCollection implements PHP’s Iterator interface.
- On line 1, we’ve made use of the has technique to first check if any photos have been entered for our car before we output the header and unordered list tag.
- The photo object makes use of the url property which is part of the WOOF_File class. This method is available to us since the image field type delegates to the WOOF_Image class, which extends WOOF_File.
Accessing specific items in multi-item field sets
Suppose we wanted to embed photos from our field set into the “detailed_description” field. Let’s take a look at a shortcode handler to allow this, which is a practical example of the need to access specific items within our photos collection. For more information on shortcode handlers, please refer to Shortcode API in the codex.
Here is the code for our shortcode handler below:
Example 5: A photo shortcode handler for our functions.php file
This method first extracts the “id” attribute of our shortcode, which we assume to be the number displayed in the content entry interface for each item in the photos field set:
Figure 7: Photo item ID
Line 10 is the key part of this code, where we use the id attribute to access the specific indexed item from our photos field set collection. We can use the standard array access syntax, since MEOW_FieldSetCollection extends WOOF_Collection which implements PHP’s ArrayAccess interface. Furthermore, field set collections actually assume a 1-based index, to match the number displayed in the UI.
Note that if we try to access an item index that doesn’t exist, a WOOF_Silent object will be returned for silent failure. This is the reason we can check if the shortcode points to a valid photo by using the exists method on line 12.
Shortcut to the first item in a collection
There’s one more thing worth mentioning about multiple-item field set collections – if we access them as if they were single-item sets, we’ll simply be retrieving the first item in the collection.
Example 6: Accessing the first item
This is a useful shortcut that can actually be quite handy in a lot of situations, especially if the first item in the set is regarded as the “primary” item.
Some field types support the separate storage of properties of our field values – kind of like metadata for our metadata. We can access the values of these properties easily, using the same chaining concepts we’ve explored already. We’ll highlight two field types in particular: the image field type, and the video field type.
While the image field type stores the URL of the image as it’s primary value, It also uses two properties to store the “alt” and “title” attributes. Here’s how we might build an img tag manually, from an image field:
Example 7: The alt and title properties of an image field
The video field type uses the YouTube or Vimeo APIs to retrieve information about the video URl you’ve specified. MasterPress uses field properties to store this information, so that it can be easily accessed via our API, sparing you the need to learn how to use theirs.
Example 8: Video Field Properties
This is a really powerful feature of MasterPress field types, especially in the case of the Video field type where all of the meta information that you’d normally have to lookup yourself is available via simple properties.
Note: field type classes which offer field properties will list them under the screenshot in the Class Reference
Field database storage
Behind the scenes, MasterPress stores all of your field values inside the following tables (assuming the default table prefix):
- wp_postmeta for field data attached to posts
- wp_mp_termmeta for field data attached to taxonomy terms (this is a custom table)
- wp_usermeta for field data attached to users
- wp_mp_sitemeta for Site Content field data (this is a custom table)
It’s useful to discuss the format of this data, in cases where you may need to run queries on it directly for your WordPress themes or custom plug-ins.
All of these tables have both a meta_key and meta_value column. The values stored in the meta_value database column are usually either:
- the text content of the field,
- a JSON representation of an array of values
- OR some type of canonical representation of the field, which can allow us to infer other info about the field. The URL of an image, for example.
The keys stored in the meta_key column have the following structure:
That is, they use a dot notation to separate the field set name and field name, with an optional property name suffix at the end, beginning with a colon. This makes it quite intuitive to run broad queries over the data in the post meta table, and the dot notation should generally mean that the data won’t conflict with other plug-ins using postmeta.
Let’s look a representation of the data stored for the sample car in Figure 3, where each line is a “meta_key” = “meta_value” key/value pair:
Example 9: Database values
There are a few interesting points to note:
- All field values store an internal “field_id” property value, so that MasterPress knows which defined custom field they originated from.
- Blank values and properties are present in the table, and they actually need to be so that multiple-item sets can determine where one field set item beings and ends
Also note that for multiple item field sets, the values are stored just like the are above, but in row blocks for each field set item, one after the other.
If you want to inspect the data in a MySQL tool, the following queries will order the data in the way that MasterPress sees it: