Limit number of tags returned

Hello again everyone!

I’m trying to limit the number of tags returned to a list using this slightly modified version of the tag-cloud example:

<?php $tags = $site->children()->children()->visible()->pluck('tags', ',', true);   ?>
<div id="tags-returns" class="returns">
<?php foreach($tags as $tag): ?>
   <h3>
      <a href="<?php echo url('/' . url::paramsToString(['tag' => $tag])) ?>"><?php echo html($tag) ?></a>
   </h3>
<?php endforeach ?>

This works perfectly well to return all of the tags I want but I can’t seem to find a way of limiting the number of tags it returns (like you might with a number of pages returned). I’ve poked around similar questions but nothing seems to have a straightforward answer – I’m not looking to rank them by popularity or anything like that, simply to return a limited number.

I’ve tried both:

$tags = $site->children()->children()->visible()->pluck('tags', ',', true)->limit(10);

&

<?php foreach($tags->limit(10) as $tag): ?>

In both instances I get an ‘Call to a member function limit() on array’ error :frowning:

I realise from reading other questions this is the wrong way to go about it but I really can’t get to the right way – hopefully somebody can help x

1 Like

You can use PHP array functions, in this case array_slice(), for example:

array_slice($tags, 0, 5)

will give you the first five elements of the array.

limit() only works with Collection objects or classes that inherit from the Collection class, not with arrays.

1 Like

Bastian’s tagcloud plugin does have a limit option, to automatically limit the number of tags returned. According to the plugin docs, this is how you’d use it:

<?php $tagcloud = tagcloud(page('blog'), array('limit' => 20)) ?>

	<ul>
	<?php foreach($tagcloud as $tag): ?>
	    <li><a href="<?php echo $tag->url() ?>"><?php echo $tag->name() ?></a></li>
	<?php endforeach ?>
	</ul>

@luxlogica Unfortunately, the tagcloud plugin only takes a single parent page as first argument, and then fetches the tags of all children of that page. To use the plugin for the above use case, you’d have to modify it.

@jackclarke On a side note, instead of $site->children()->children() you can use $site->grandChildren().

@texnixe ah, I see!

But looking at the plugin code, the $parent parameter (that holds the page object that we pass), is only used either with the url() method (line 16) or children() lines 27, 30 and 33.

How about if instead of passing a page, we just pass the $site object? Wouldn’t it work in this case? After all, $site has the same methods, returning the same types of objects…?

@luxlogica Even if you pass the $site object (which should actually be possible), you would only get the children, not the grandchildren.

What the plugin does, is fetch all the tags, loop through them to create another array with some additional information and then create a collection from that array. We could do the same here, i.e. create a collection to be able to use limit(), but it’s a lit easier to just use the pluck() method with some array methods.

@texnixe you’re totally right!

I suppose, if we did want to have all the extra info on each tag that the plugin is compiling for us, we could perhaps write a (recursive) function that would collect the $tagcloud of each child page, and then combine them into a big collection?..

I guess the only caveat here would be that all the tag fields would have to have the same name.

Or we could just fork the tagcloud plugin and replace children with grandchildren or whatever is needed, or even extend the plugin to be more flexible, for example add a third parameter for subpages (children, grandchildren, index).

The pluck() method only works with fields with the same name anyway.

But: The tagcloud plugin just makes your life easier, at the cost of some overhead that is probably not needed for a certain use case.