Twig filter with callback

Greetings.

I have a template intended to generate API responses from Tailor content types. My CMS is based in posts that could have several authors. So it is something like this:

title = "Posts"
layout = "api"
url = "/api-v1/posts/filter/:status?/:language?/:author?/:dates?any/:orderby?id/:order?asc/:ipp?100"

[collection]
handle = "Content\Post"
==
{% set posts = collection %}
{# Check status parameter #}
{% if this.param.status and this.param.status != 'any' %}
    {% set posts = posts.where('status', this.param.status) %}
{% endif %}

{# ******* Here some other Twig checks that are working fine ********* #}

{# Check if author parameter is integer #}
{% if this.param.author matches '/^\\d+$/' %}
    {# Next line doesn't work. This is my attempt to filter the posts that include the author passed in the URL parameter #}
    {% set posts = posts|filter(v => v.authors and v.authors.id == this.param.author) %}  
{% endif %}

{% set posts = posts.orderBy(this.param.orderby, this.param.order).paginate(this.param.ipp) %}

{% set pager = pager(posts) %}

{% do response({
    data: posts,
    links: pager.links,
    meta: pager.meta
}) %}

I got an error:

Call to a member function toArray() on null
~/modules/system/classes/PagerElement.php line 49

I know that there’s a way to filter collections with PHP/Laravel, using the filter method and a callback function, but I can’t figure out how to implement that inside Twig.

Your comments and suggestions will be greatly appreciated.

Best regards.

You can filter it by using a where clause.

Something like:

{% posts.where('author', 'id', v) %}

More documenation here

1 Like

I assume that “v” is the URL parameter in your proposed syntax. That doesn’t work.

Please note that in this case I defined a field “authors” of type “entries” in the “post” blueprint. Every post could potentially have several authors. There is a relationship involved, so as far as I know, a simple “where” clause will not do the trick.

Thanks anyway for your suggestion.

Well, it should work. This where clause gets all posts where the author’s id is the variable at the end, and you can combine them to include the slug.

If you have the Tailor entry setup with a relation, it’ll pull all posts with that author.

Another note too, the twig where clause should be 1:1 except it’s in the twig syntax. You can try other where clauses or even queries from Laravel to see if it’ll work.

1 Like

Oh also, if it doesn’t return the posts, add a .get() method at the end. That will return the list of the posts instead of the object.

2 Likes

The suggestion of Devin pointed me to the documentation, where I found the solution:

{% set posts = posts.whereRelation('authors', 'id', this.param.author) %}

2 Likes