Music: PHP

How to easily access to Custom Fields in Joomla

Published

Over the past few years, I’ve had to get more and more involved in developing Joomla websites. Joomla is such a powerful, flexible and user-friendly CMS to work with, but did find a few harder-than-they-need-to-be moments.

Michael, Mity Digital’s in-house Certified Joomla Administrator with over a decade of Joomla experience, introduced me to Custom Fields for a specific project – and the value it adds to the author is incredible – he’s written a blog post all about the benefits of Custom Fields for Joomla content authors.

The project relied on a rather large number of Custom Fields – and by using the combination of Field Groups and Categories has created an incredibly easy-to-manage editing experience for the site’s authors. By using Field Groups, Fields are more logically placed, and lists of Fields appear shorter (making it easier to read and process entire sections) – and the nerd in me loves it because the content of these Fields remains fully separate from the core Article content – meaning I can do what I need to with the content and not have to rely on accuracy of markup from the author. Massive bonus.

Within each Article, we are able to access our Custom Fields using the jcfields array on our $item, and Joomla provide in their documentation the option of simply iterating, or using the FieldsHelper.

The FieldsHelper method spits out markup in a set (and not-overridable) way – which isn’t good for the control freak in me – and the jcfields index is a numerically indexed array, so accessing a specific field is quite loopy (ha…).

The documentation does also point out how to access the fields by their name – but still relies on placing repeated code at the top of every override. If we have several overrides  and need to make one change to the logic of this processing, we need to update several files.

So the core idea and logic how to access fields (directly using jcfields, not the FieldsHelper) is spot on – but the repeated implementation in every override isn’t the best. The programmer in me says “nope, let’s make it better”. Well, not “better”, but centralised. Let’s write the code to make it easier to access Custom Fields once rather than in every override.

To help out managing Articles at the override level, I wrote a Helper class that we use in all of our Joomla sites now at Mity. This Helper still requires some code in every override, but the code is simply including that Helper, and running it. The smarts inside the helper – i.e. making it easier to access Custom Fields – is then written once, but can be used by any override. Much happier coder now.

The jcfields array is great – it as everything we could ever need. But that’s also an issue – it has everything – and still requires a bit of work to get actual selected values based on different field types. This is actually really great though – it means we have total control and full knowledge over the source Custom Field. But we do just need to make sure we know how to access the different properties of different Custom Field types.

Hello this centralised Helper, once again.

Simply put, this Helper accepts an $item (i.e. $this->item from an Article override, or $item from a Module override), and performs some processing on the items.

Rather than overriding the jcfields array (as the docs suggest), we are creating another named-index array for our processed fields. This processing is:

  • Giving is the name and label
  • Telling us the Field Group ID
  • Processing the Value to be a little more friendly
  • Saving the options, if the Field Type uses them
foreach ($item->jcfields as $field)
{
    $item->jcfieldsnames[ $field->name ] = [
        'name'    => $field->name,
        'value'   => is_array($field->rawvalue) && count($field->rawvalue) == 1 ? $field->rawvalue[0] : $field->rawvalue,
        'label'   => $field->label,
        'group'   => $field->group_id,
        'options' => $field->fieldparams->get('options')
    ];
}

This means that our original untouched jcfields are always there – but we can just access our Custom Fields using a named-index array.

Given different Field Types behave in slightly different ways with their value, we have also had to extend this. Currently I have only done this for Checkboxes and JSON-based data (such as a Repeatable) – again, all with the aim of making it easier to access the Field data at the override level.

if ($field->type == 'checkboxes')
{
    // create an array for our selected items
    $selected = [];

    // loop through all of the options
    foreach ($field->fieldparams->get('options') as $option)
    {
        // check if the selected value(s) has the current option
        // if rawvalue is an array, there is 2 or more options - look inside the rawvalue as an array
        // if rawvalue is a string, there's only one option - comparitor is as a string
        if ((is_array($field->rawvalue) && in_array($option->value, $field->rawvalue)) || $field->rawvalue == $option->value)
        {
            $selected[] = array(
                'name'  => $option->name,
                'value' => $option->value
            );
        }
    }

    // update the value with the selected items
    $item->jcfieldsnames[ $field->name ]['value'] = $selected;
}
else if (ItemHelper::isJSON($item->jcfieldsnames[ $field->name ]['value']))
{
    // the value is a JSON string - so decode it to be an associative array
    $item->jcfieldsnames[ $field->name ]['value'] = json_decode($item->jcfieldsnames[ $field->name ]['value'], true);
}

Note that this helper is currently for Joomla 3 – Joomla 4 will be making some changes to repeatable fields – and the PR for this has not yet been committed as of alpha 9.

If you find this useful, you may want to extend the helper further to process additional Field Types too. This is a great starting point though.

Want the full source code? You can view it all at my Joomla Item Helper repository over at Github.

Now that we have the smarts, how do we use it?

In our override, we need to include the Helper. For these code samples, we’re in an Article override using $this->item to access our item contents.

$app = JFactory::getApplication();
$path = JPATH_THEMES . DIRECTORY_SEPARATOR . $app->getTemplate() . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'ItemHelper.php';
JLoader::register('ItemHelper', $path);

Now that we have registered the class, let’s just call the processing method – I’ve called it processItem as that is what it is doing:

ItemHelper::process($this->item)

The code inside the processItem call is making changes to the input parameter – i.e. $this->item or $item – but because the function definition is accepting this variable by reference, it is simply updating our item – no need to save it back to our calling script.

With the processing complete, fields can easily be used just by calling our array with a named index:

echo $this->item->jcfieldsnames['my-field-name']['value'];

But that wasn’t enough for me… so I went one step further and added a few additional helper functions to make it really easy (and less array-ish) for use in the overrides. There are four helpers that allow easy retrieval of specific properties:

  • getFieldGroupId
  • getFieldLabel
  • getFieldOptions
  • getFieldValue

These accept the item, and the field you are looking for, and will return the property (or false if not found). Just something to make life a little easier. You can now call:

echo ItemHelper::getFieldValue($this->item, 'my-field-name');

This will return the value of the Custom Field named “my-field-name” for the item. Easy!

The total nerd in me does like this approach – i.e. a centralised helper, with handy (and helpful) processing taking place in one central piece of code, which can easily be used where needed – be that a component override or module override – and, better yet, only run if we actually need it. And better still – without touching any core Joomla files, so future 3.x updates should have no impact (if any) to our site’s behaviour.

Custom Fields are really awesome – and the way that Joomla have provided a powerful and flexible approach to structuring, implementing and accessing them is great. And this Helper just takes the repetitive coding out of the way, and puts the processing in one central place. Need to update the processing for a new Custom Field type? Awesome – we can now make one code change any ALL of our overrides can take advantage of the processing. Time saving at its best.

Want the full source code? Get yourself started with my Joomla Item Helper repository over at Github.

Blog

View all
JS

Integrating Tiny with Vue in a real world application

TinyMCE 5 has made the setup process more straightforward - and even easier with the Cloud version. And as there are so many JS frameworks out there, Tiny have...

Continue reading...

PHP

Extending the ItemHelper for Joomla

There are times in Joomla where you want a bit of control over your content at the template override level – such as showing the first X characters of a string. PHP...

Continue reading...

JS

How Tiny helps me deliver the best content authoring experience

At Joomla Day Australia 2019 in Brisbane, I spoke about how TinyMCE helps deliver the best content authoring experience. And for those who couldn’t make it on...

Continue reading...

Photo

How to show real-time highlights and shadows clipping in Photoshop

I’ve used Photoshop for years. Decades even. Yikes, showing age there. But for my photography, I tended to use Photoshop for specific things – such as cleaning...

Continue reading...

I am the Development Director (and co-owner) at Mity Digital, a Melbourne-based digital agency specialising in responsive web design, custom web development and graphic design.
Mity Digital