Taxonomy module provides the function taxonomy_get_term_by_name(), which lets you retrieve an array of term objects matching a given term name.

However, I've found several instances where I'm using either only one free-tagging vocabulary, a collection of hand-crafted vocabularies, where I know terms don't have repeats. And I'm only interested in grabbing the term ID of the first result so that I can monkey with it elsewhere in my script.

So here's a new function, taxonomy_get_tid_by_name()...

var_dump(taxonomy_get_tid_by_name('Drupal project')); // Found, one result... returns that term's ID.
var_dump(taxonomy_get_tid_by_name('adsasdasd'));  // Not found... returns FALSE.
var_dump(taxonomy_get_tid_by_name('Modules')); // Found, two results... returns the *first* term's ID.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

RobRoy’s picture

Status: Needs review » Needs work

A look and me thinks there is a parse error, single quote at beg.

db_rewrite_sql('SELECT t.tid FROM {term_data} t WHERE LOWER('%s') LIKE LOWER(t.name)", 't', 'tid')
webchick’s picture

Status: Needs work » Needs review
FileSize
1.11 KB

D'oh!! wrong patch. :( Thanks.

catch’s picture

Version: 6.x-dev » 7.x-dev

Thsi still applies with offset. Does it count as a performance improvement? Bumping to drupal 7 since it's marke as a feature anyway.

aaron’s picture

This patch still applies. If it seems worthwhile, I could write up a test or two for this.

drawk’s picture

I often need to do the same, and I like this. However, there are times where I only want the tids, but from any matching term. Weighing that with the possibly confusing function naming where both are singular (get_term and get_tid) and have complementary functions, yet the first returns multiple results and the latter returns only a single result, what about ..

taxonomy_get_terms_by_name($name, $limit = NULL)
and
taxonomy_get_tids_by_name($name, $limit = NULL)

Where if limit is NULL all results are returned, but if limit is specified that limit is applied to the query.

$term = taxonomy_get_terms_by_name('Drupal', 1) results in one term object
$tid = taxonomy_get_tids_by_name('Drupal', 1) results in one tid

catch’s picture

Status: Needs review » Needs work

Needs a re-roll for dbtng.

catch’s picture

Version: 7.x-dev » 8.x-dev
Summit’s picture

Hi, Will this function be possible in Drupal 6?
Otherwise, how can I get from termname to TID?
Thanks a lot for your reply in advance!
greetings, Martijn

marvil07’s picture

Status: Needs work » Needs review
FileSize
1.41 KB

Not sure if this is still desired, but re-rolled for dbtng anyway.

For the case mentioned in comment 5 I would say using taxonomy_term_load_multiple(), an EntityFieldQuery or a manual query would be OK.

xjm’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests, +API addition

Oh man, when I think of all the overhead of all the term objects I load unnecessarily... +1 for this addition or something like it. I think there are also some related issues open about other taxonomy API functions.

Do we want to statically cache inside this function since we're not using the entity caching anymore?

+++ b/modules/taxonomy/taxonomy.moduleundefined
@@ -1072,6 +1072,28 @@ function taxonomy_get_term_by_name($name) {
+ * @return
+ *   The term ID of the given term, or FALSE if none was found.

Minor point, but we need a blank line above @return.

+++ b/modules/taxonomy/taxonomy.moduleundefined
@@ -1072,6 +1072,28 @@ function taxonomy_get_term_by_name($name) {
+
+
+/**

I think there's an extra linebreak here, too. :)

And, of course, the patch needs to be rerolled now.

marvil07’s picture

Status: Needs work » Needs review
FileSize
1.43 KB

Not sure about a static cache there.

Formatting errors fixed here(it rebased cleanly noticing the renaming, git++).

xjm’s picture

Cross-referencing #336697: Optional vid argument for taxonomy_get_term_by_name(). That arg would be desirable for this helper as well.

I think static caching so the query isn't run repeatedly would be a good idea. That's one reason to have this helper in core rather than just leaving it to taxonomy-dependent contrib to add their own helpers.

marvil07’s picture

Thanks for the suggestions.

I was not sure about which optional parameter to provide: vid or a vocabulary_machine_name, so I provided both.

This patch also adds static cache to the function results.

ro-no-lo’s picture

I would like to raise a problem here. May look minor to you.

Guessing if a parameter is either one thing or another thing is a bad practise. The initial task webchick described was of that kind. In the latest added patch, you try to guess if the parameter $vocabulary is an ID (= int) or a vocabulary name (= string).

A quick test in D7 showed me that you actually are not prevented from giving vocabularies INT looking internal names a "4444" went right through it and now the link looks like this admin/structure/taxonomy/4444/add. I cannot tell if that is an vid or a vocabulary_name.

You have either to make sure (accross drupal) that internal unique names follow the same rules as variables in PHP or someone will break your system, because he can.

I can tell you that this is a big problem. In Magento for example there is a CORE helper function which loads a product by either SKU (= alphanumerical) or ProductID (= int).

Small excurse:

    /**
     * Return loaded product instance
     *
     * @param  int|string $productId (SKU or ID)
     * @param  int $store
     * @param  string $identifierType
     * @return Mage_Catalog_Model_Product
     */
    public function getProduct($productId, $store, $identifierType = null)
    {
        /** @var $product Mage_Catalog_Model_Product */
        $product = Mage::getModel('catalog/product')->setStoreId(Mage::app()->getStore($store)->getId());

        $expectedIdType = false;
        if ($identifierType === null) {
            if (is_string($productId) && !preg_match("/^[+-]?[1-9][0-9]*$|^0$/", $productId)) {
                $expectedIdType = 'sku';
            }
        }

        if ($identifierType == 'sku' || $expectedIdType == 'sku') {
            $idBySku = $product->getIdBySku($productId);
            if ($idBySku) {
                $productId = $idBySku;
            } else if ($identifierType == 'sku') {
                // Return empty product because it was not found by originally specified SKU identifier
                return $product;
            }
        }

        if ($productId && is_numeric($productId)) {
            $product->load((int) $productId);
        }

        return $product;
    }

They are trying to guess what is used by RegEx. Well our company uses numeric SKUs for like 15 years and we cannot use the SOAP API because for loading prodcucts the core uses this function.

Back to Drupal. I could "break" your code by taxonomy_get_tid_by_name('something', intval('4444')); (Try to imaging I'm someone who has only numeric internal uniquenames just because another external data system has the same IDs for tagging and it makes it easier for me to have them matched)

Btw. why using a "LIKE" when a ->condition('t.name', trim(strtolower($name))) could be better. LIKE indicated also guessing. I mean the whole function was initial like guessing, but that is not something I expect from core.

ro-no-lo’s picture

Oh, I see this is from 2007. I have no idea why this caught my attention. I guess that is outdated anyway.

marvil07’s picture

Issue summary: View changes
Status: Needs review » Closed (won't fix)

I guess we could just won't fix this.

If needed the asked function can be a manual select, or a attachLoad() override on the storage controller.