Reputation: 4834
The Setup
This is to do specifically with Twitter Cards, but I'm looking for a more general (i.e. not Twitter Cards specific) solution, as many meta tags are namespaced.
Twitter cards are stored in the head of a web page, inside meta
tags. Something like...
<meta name="twitter:site" content="... tag content ...">
When you run get_meta_tags()
on a website that uses the cards, you'll get a return that looks something like...
[
... bunch of other meta tags ...
"twitter:card" : "... tag content ...",
"twitter:description" : "... tag content ...",
"twitter:title" : "... tag content ...",
"twitter:site" : "... tag content ...",
"twitter:image" : "... tag content ...",
"twitter:creator" : "... tag content ...",
... maybe some more tags ...
]
All the keys that have to do with the Twitter Card are namespaced - what I mean is that each of them is prefaced with twitter:
.
Even if a page has Twitter Card tags present, not all the tags listed above will necessarily be there. Some times it's all of them, some times it's just a couple.
The Problem
Let's get us some meta tags...
$tagsList = @get_meta_tags($url);
Because you don't know for sure which tags will be present, it doesn't make sense to test for them all...
if(isset($tagsList['twitter:card'])) {
// Do something
}
if(isset($tagsList['twitter:description'])) {
// Do something
}
... and so on ...
This approach is also particularly ineffective if you do not know every possible tag name that could be present, or Twitter decides to change the current standard.
So instead, you loop through every tag...
$twitterList = array();
foreach($tagsList as $tagName => $tagCont) {
if(strpos(strtolower($tagName), 'twitter:') === 0) {
// root = 'twitter', sub = 'card' or 'description' or ...
list($root, $sub) = explode(':', $tagName);
$twitterList[] = array(
'root' => $root, // Don't really need this
'sub' => $sub,
'content' => $tagCont
);
}
}
And this works a treat. It's accurate, and returns your Twitter Card tags in a nice list. But, if I only need the tags pertaining to the Twitter Card, why the heck should I have to busy myself with looping through ALL of them!?
The Question
Is there a quick way to access these namespaced keys, without looping through every meta tag that was returned from the page? I'm only interested in the twitter:
ones, so I don't want to waste resources and time looping through every tag.
Something like...
$twitterTags = $tagsList['twitter:'];
where the output would be along the lines of...
$twitterTags : [
'card' : 'card content',
'description' : 'desc content',
... and so on ...
]
I reckon you might be able to use array_map()
, which might shorten the number of lines of code used, but you still end up looping through every key.
Ok, I know it isn't necessarily necessary, but...
Unless a page has an unreasonable number of meta tags (bazillions of them), the time/resources difference between the brute-force loop and a more elegant solution will be negligible. But it's still an interesting exercise.
Edit #1
Thanks to Daniel Klein, I found this beauty...
function preg_grep_keys($pattern, $input, $flags = 0) {
return array_intersect_key($input, array_flip(preg_grep($pattern, array_keys($input), $flags)));
}
Which is used in the following way...
$pattern = '/(twitter\:)([\w\d\-\_]+)/';
$twitterList = preg_grep_keys($pattern, $tagsList, $flags = 0);
And returns...
"twitterList": {
"twitter:card": "... tag content ...",
"twitter:description": "... tag content ...",
"twitter:title": "... tag content ...",
"twitter:site": "... tag content ...",
"twitter:image": "... tag content ...",
"twitter:creator": "... tag content ..."
}
What a gem! But, I'm unsure how array_intersect_key()
and array_flip()
go about their business. I'm probably still looping over the array. And surely array_keys()
has to loop over the array?
It looks prettier than the foreach()
above, anyway.
Upvotes: 0
Views: 56
Reputation: 6013
No there is no such functionality, as get_meta_tags() is not designed for this (and certainly was designed prior to Twitter introducing their own set of meta tags).
You will have to either iterate over the list as you are doing (or use array_map() as you also mention yourself) or load the html using a DomDocument and traverse/search (with xpath) the DOM Structure to find the meta tags you are looking for.
In fact, the twitter:description
naming scheme is just a naming scheme chosen by Twitter. It is not an actual namespace, nor is the tags part of any standard. If you want php to support this functionality of get_meta_tags you can try to propose it as a feature to add
Upvotes: 2