6

How to realize tags function on my custom extension? I have try follow https://docs.joomla.org/J3.2:Using_Tags_in_an_Extension this guide step by step but still I can't save tags into database. System alerts "Save failed with the following error:(blank)". I don't know what's the error....

Does Anyone have such experiense on tags development who can help me out? Thank you !!!!

4

You can use the tags functionality in your custom extension as follows:

  1. models/forms/formfile.xml -

    <field name="tagfieldname" type="tag" mode="ajax" label="Tag Field Name" description="" multiple="true" custom="allow" required="true" />

  2. tables/filename.php - add the following code in the bind() method :

    public function bind($array, $ignore = '')
    {    
      if (!empty($array['tagfieldname']) ) {
      // Load the tags helper.
      require_once JPATH_ADMINISTRATOR . '/components/com_tags/helpers/tags.php';
    
    // Get the allowed actions for the user
    $canDo = TagsHelper::getActions('com_tags'); // The helper get the user and the component name itself
    
    // Load the tags model.
    require_once JPATH_ADMINISTRATOR . '/components/com_tags/models/tag.php';
    JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_tags/tables');
    
    // Get an instance of the table for insertion the new tags
    $tagsModel = TagsModelTag::getInstance('Tag','TagsModel');
    
    $tags = array(); // Initialization of the tag container must be processed
    
    // If tags is an array, store-mode
    if ( is_array($array['tagfieldname']) ) {
        // "Allow user creation" mode must be activated (default) in the component creation field
        // Save the tags does not exist into the table tags and get its id for save the entire Item with the proper data
        foreach ($array['tagfieldname'] as $singleTag) {
            // If there is any new tag... create it to get the id and save into the table #__COMPONENT_NAME_TABLE_NAME
            if ( strpos($singleTag, "#new#") !== FALSE ) {
                $user           = JFactory::getUser();
                $userId         = $user->id; // For writing permissions 
                $tagName        = str_replace("#new#", "", $singleTag);
                $tagAlias       = $tagPath = preg_replace('/\W+/', '-', $tagName); // Tags alias filter
                $tagMetadata    = array(
                        "author"=>""
                        , "robots"=>""
                        , "tags"=>null
                );
    
                // The data tag field row
                $data = array(
                        "parent_id" => 0
                        , "path" => $tagPath
                        , "title" => $tagName
                        , "alias" => $tagAlias
                        , "created_by_alias" => $user
                        , "created_user_id" => $userId
                        , "published" => 1
                        , "checked_out" => 0
                        , "metadata" => json_encode($tagMetadata)
                );
    
                // Finally, store the tag if the user is granted for that
                if ( $canDo->get('core.create') ) {
                    $table = $tagsModel->getTable();
                    $table->bind($data) ? $table->store($data) : exit;
                    $tags[] = $table->id; // And store the insert_id
                }
            }
    
        // NOT new Tag (already exists)
        // $singleTag is the tag id
        else
            $tags[] = intval($singleTag);
        }
    
        // Override the tags array, because we should need to change the id before field saving
        // The field in database will look like "299,345,567,567"
        $array['tagfieldname'] = implode(',', $tags);
    }
    }
    else {
        $array['tagfieldname'] = '';
    }
    return parent::bind($array, $ignore);
    }// bind() ends
    
  • Thank you!But it still don't work... – Jacky Kwan Jun 18 '16 at 10:27
  • can you tell me what error is it displaying now? Because I have used the same method and it works for me perfectly – Liz. Jun 20 '16 at 4:53
1

For Joomla 3.7.x and every custom component, I took the answer from @liz and put the code in a separate function which you can call from everywhere and use it everywhere you want.

Also I moved the User-factory above the foreach, because we just need to call it once, not for every loop. And I removed the $canDo, because it is not working, as TagsHelper is not available like this. Perhaps this can be done with any other access-control-check?

function saveJoomlaTags($tags, $created_by_alias="", $note="") {

        // Load the tags model.
            require_once JPATH_ADMINISTRATOR . '/components/com_tags/models/tag.php';
            JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_tags/tables');

        // Get an instance of the table for insertion the new tags
            $tagsModel = TagsModelTag::getInstance('Tag','TagsModel');

        // If tags is not an array, return nothing.
            if ( !is_array($tags) ) {
                return "";
            } 

        $user = JFactory::getUser();
        $return = array();

        // "Allow user creation" mode must be activated (default) in the component creation field
        // Save the tags does not exist into the table tags and get its id for save the entire Item with the proper data
            foreach ($tags as $singleTag) {
                // every custom-entered tag starts with "#new#", every exsting tag is the ID.
                    if ( !strBeginsWith($singleTag, "#new#")) { // see pm_helper.
                        $return[] = intval($singleTag);
                        continue;
                    }

                // A new Tag must be saved to the DB first.
                    $tagName        = str_replace("#new#", "", $singleTag);
                    $tagAlias       = $tagPath = preg_replace('/\W+/', '-', $tagName); // Tags alias filter
                    $tagMetadata    = array();
                    $tagMetadata["author"]  = "";
                    $tagMetadata["robots"]  = "";
                    $tagMetadata["tags"]    = "";


                // The data tag field row
                    $data = array(
                            "parent_id" => 0
                            , "path" => $tagPath
                            , "title" => $tagName
                            , "alias" => $tagAlias
                            , "created_by_alias" => $created_by_alias
                            , "created_user_id" => $user->id
                            , "published" => 1
                            , "language" => "*"
                            , "checked_out"=> 0
                            , "metadata" => json_encode($tagMetadata)
                            , "note" => $note
                    );

                // Finally, store the tag if the user is granted for that
                    $table = $tagsModel->getTable();
                    $table->bind($data) ? $table->store($data) : print "Fehler beim Speichern der Tags. Siehe ".__FILE__.__LINE__;
                    $return[] = $table->id; // And store the insert_id                       

            } // foreach 

        // Override the tags array, because we should need to change the id before field saving
        // The field in database will look like "299,345,567,567"
            $return = implode(',',$return);

        return $return; // a list of IDs.

    } // saveItemTags()

You will also need this helper function "strBeginsWith":

    function strBeginsWith($str, $beginsWith) {
       if (strpos($str, $beginsWith) === 0) {
           return true;
       }
       return false;
   }
0

Most likely there is something wrong with your #__content_types entries.

First of all, you need to register your content_types for your views, as described here:

Then you need to be careful with the values of the fields of your content_types.

More specifically for saving tags into the #__contentitem_tag_map table for your extension, the required fields for your content_type are:

type_id, type_title, type_alias, table, field_mappings

From these fields make sure that the type_alias and the field_mappings contain valid data. For example a simple syntax error in field_mappings would lead to errors, like the one you got.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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