Knows someone a good guide on how to implement the TAGS feature into a Custom J4/5 Component? I have this information from Astrid's Book on how to develop J4 Components but it looks not fully correct to me (uses old syntax at least for the table).

What I've tried (multiple times)


private function saveContentTypes()
//      $app = Factory::getApplication();
//      $table = $app->bootComponent('com_tags')
//          ->getMVCFactory()
//          ->createTable('Contenttype');

        $table = Table::getInstance('Contenttype', 'JTable'); // << Old way should be replaced by above or not?

        $table->load(['type_alias' => 'com_component.question']); // will fail on new way (commented above)

        $tableStringContentObj                   = new stdClass();
        $tableStringContentObj->special          = new stdClass();
        $tableStringContentObj->special->dbtable = '#__com_component_questions';
        $tableStringContentObj->special->key     = 'id';
        $tableStringContentObj->special->type    = '[COMPONENTNAME]QuestionTable';
        $tableStringContentObj->special->prefix  = 'NXD\\Component\\[COMPONENTNAME]\\Administrator\\Table\\';
        $tableStringContentObj->special->config  = 'array()';
        $tableStringContentObj->common           = new stdClass();
        $tableStringContentObj->common->dbtable  = '#__ucm_content';
        $tableStringContentObj->common->key      = 'ucm_id';
        $tableStringContentObj->common->type     = 'Corecontent';
        $tableStringContentObj->common->prefix   = 'Joomla\\CMS\\Table'; // was JTable
        $tableStringContentObj->common->config   = 'array()';
        $tableString                             = json_encode($tableStringContentObj);

        $fieldMappingObj                               = new stdClass();
        $fieldMappingObj->common                       = new stdClass();
        $fieldMappingObj->common->core_content_item_id = 'id';
        $fieldMappingObj->common->core_title           = 'title';
        $fieldMappingObj->common->core_state           = 'published';
        $fieldMappingObj->common->core_alias           = 'alias';
        $fieldMappingObj->common->core_publish_up      = 'publish_up';
        $fieldMappingObj->common->core_publish_down    = 'publish_down';
        $fieldMappingObj->common->core_access          = 'access';
        $fieldMappingObj->common->core_params          = 'params';
        $fieldMappingObj->common->core_featured        = 'featured';
        $fieldMappingObj->common->core_language        = 'language';
        $fieldMappingObj->common->core_ordering        = 'ordering';
        $fieldMappingObj->common->core_catid           = 'catid';
        $fieldMappingObj->common->asset_id             = 'null';
        $fieldMappingObj->special                      = new stdClass();
        $fieldMapping                                  = json_encode($fieldMappingObj);

        $contentType                            = [];
        $contentType['type_id']                 = ($table->type_id) ?: 0;
        $contentType['type_title']              = 'Questions';
        $contentType['type_alias']              = 'com_component.question';
        $contentType['table']                   = $tableString;
        $contentType['rules']                   = '';
        $contentType['router']                  = 'RouteHelper::getQuestionRoute'; // not yet defined but shouldn't be an issue?
        $contentType['field_mappings']          = $fieldMapping;
        $contentType['content_history_options'] = '';



The row gets added on install and looks good to me (a lot more information then the others but type_alias looks fine) - Note: I'm adding the information by using an object (xyObj) because when typing it as string it writes the format (newlines) also into the table.

In the XML Form for Edit Question

<field name="tag" type="tag" custom="true" ... />

The field gets rendered and shows me all Tags of COM_CONTENT.Article that has been setted up already (that shouldn't be the case right?). When trying to add a new tag (type and enter) it does not store the new tag and the field is empty after save.

For me it feels like i'm trying to use outdated information on how to implement the Tags functionality...

1 Answer 1


The changes necessary for getting the joomla mvc component tutorial working are listed in https://docs.joomla.org/J3.x:Developing_an_MVC_Component/Upgrading_to_Joomla4#Miscellaneous_Changes.

The tags functionality still uses content types, so you'll need to add those as you've done above. As these are used by Version History and by Tags, this is described in the Version History section in that tutorial webpage, so have a look at that section too.

You can also download the zip file of the tutorial code from https://github.com/robbiejackson/Joomla-4-MVC-Tutorial to see how it's been done.

Section from that tutorial page copied to below:

Like version history, tags functionality has been changed to use a plugin – in plugins/behaviour/taggable – rather than the JTableObserver approach.

To enable tags the component table must implement TaggableTableInterface (in libraries/src/Tag), and provide the getTypeAlias() which is common to the Versioning functionality.

Whenever com_tags outputs helloworld messages or categories relating to a tag it displays them as links, and looks in the site/helpers/route.php file to find the route functions (as described above in com_tags). The class and method in this file must match the 'router' field within the data entered into the #__content_types table.

The language constant JTAG_DESC (used in the XML form file for tags fields) is no longer available.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.