简体   繁体   中英

Joomla 3.1.4: how to insert tags programmatically?

In Joomla 3.1.1, here's the simplified code that I use to batch insert articles (and tags):

$table = JTable::getInstance('Content', 'JTable', array());
$data = array(
    'title' => $my_title,
    'introtext' => $my_introtext,
    ....
    'metadata' => array(
          ...,
         'tags' => $list_of_tag[id],
          ...,
       ),
  );
$table->bind($data);
$table->check();
$table->store();

The $list_of_tag[ids] then goes into #_content metadata field in the form {"tags":[ids],"robots":"","author":"","rights":"","xreference":""} . Joomla also would take care of other related tables such as #_contentitem_tag_map , etc.

This method does not work in Joomla 3.1.4, as the tag no longer goes into metadata field, the new format is {"robots":"","author":"","rights":"","xreference":""} , ie, no more tags key.

Does anyone know how do I insert tags into Joomla programmatically in 3.1.4? Thanks,

Update for full code:

The full code that worked in 3.1.1, where $row['tags'] is an array of integers, corresponding to exising tag ids in #_tags, and all other fields in $row are well defined.

<?php
define( '_JEXEC', 1 );
define('JPATH_BASE', dirname(dirname(__FILE__)));
define( 'DS', DIRECTORY_SEPARATOR );

require_once (JPATH_BASE . DS . 'includes' . DS . 'defines.php');
require_once (JPATH_BASE . DS . 'includes' . DS . 'framework.php');
require_once (JPATH_BASE . DS . 'libraries' . DS . 'joomla' . DS . 'factory.php' );

define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_BASE . DS . 'administrator' . DS . 'components' . DS . 'com_content');

$mainframe = JFactory::getApplication('site');

require_once (JPATH_ADMINISTRATOR.'/components/com_content/models/article.php');

$string = file_get_contents("items.json");
$json_str = json_decode($string, true);
$title_default = 'No Title';
$i = 0;
foreach($json_str as $row){
    $table = JTable::getInstance('Content', 'JTable', array());
    $data = array(
        'title' => $row['title'][0],
        'alias' => $row['alias'][0],
        'introtext' => $row['content'],
        'state' => 1,
        'catid' => $row['catid'][0],
        'created' => $row['pdate'],
        'created_by' => 635,
        'created_by_alias' => $row['poster'][0],
        'publish_up' => $row['pdate'],
        'urls' => json_encode($row['urls']),
        'access' => 1,
        'metadata' => array(
            'tags' => $row['tags'],
            'robots' => "",
            'author' => implode(" ", $row['poster']),
            'rights' => "",
            'xreference' => "",
        ),
    );
    ++$i;
// Bind data
    if (!$table->bind($data))
        {
            $this->setError($table->getError());
            return false;
        }

// Check the data.
    if (!$table->check())
        {
            $this->setError($table->getError());
            return false;
        }

// Store the data.
    if (!$table->store())
        {
            var_dump($this);
            $this->setError($table->getError());
            return false;
        }
    echo 'Record ' . $i . ' for post ' . $data['alias'] . ' processed';
    echo "\r\n";
}
?>

Upon on reading the docs, I have tried different ways to re-write the code:

  1. Move the line that says 'tags' => $row['tags'], under metadata to its parent array, that is:

      ... 'access' => 1, 'tags' => $row['tags'], 'metadata' => array( 'robots' => "", 'author' => implode(" ", $row['poster']), 'rights' => "", 'xreference' => "", ), ... 

So now we have $data['tags'] populated with an array of integers mapping existing tag ids, presumabaly ready for the JTable store() method;

  1. In addition to method 1, jsonify $row['tags']. for this I've tried two method:

2.a)

...
$registry = new JRegistry();
$registry->loadArray($row['tags']);
$data['tags'] = (string) $registry;
...

2.b)

data['tags'] = json_encode(json_encode($row['tags']));

With these changes I still can't add tags for the inserted articles.

Elin: Thanks for your patience!

http://docs.joomla.org/J3.1:Using_Tags_in_an_Extension is the basic documentation for using tags in an extension.

ALthough there are changes in 3.1.4+ if you follow these instructions it will work. 3.1.4+ makes it somewhat easier because it handles tags via an observer pattern instead. I'll try to get the docs updated but you can look in any core component and see that the code as been simplified and moved somewhat out of JTable.

Update:

I updated the documentation for 3.1.4 including how to modify your old code to make it work.

It turns out that if you instantiate JTable, then the new com_tags won't take $data['tags'] , instead, you need to bind your tags directly to $table as table->newTags = $data['tags']; , this way your newly inserted articles will be tagged properly given that you have populated your $data['tags'] with existing tag ids.

Late answer, but hopefully will save the next OP from the frustration I had trying to find a way to call the Tag methods directly.

I wound up simply updating the article to be tagged with the content model:

$basePath = JPATH_ADMINISTRATOR.'/components/com_content';
require_once $basePath.'/models/article.php';
$articlemodel = new ContentModelArticle(array('table_path' => $basePath . '/tables'));

$params = array(
    'id' => 123,                // Article being tagged
    'tags' => array(7,8,9,14)   // Tag IDs from #__tags to tag article with
);
if($articlemodel->save($params)){
    echo 'Success!';
}

Worked like a charm! It seems that it could be easily adapted to any taggable items. I think I had a similar situation as the original question, and actually used the above code with a SQL statement that compiled the correct Tag IDs for me. It would be meaningless to the answer, but it saved me having to manually tag 1,900 articles from a selection of 200+ tags!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM