3

We have some components that are used to build pages, like normal, and some where we hydrate them with other data, so we are passing in arrays instead of entries.

If something is essentially an element, we need to do a .all() to not have deprecation warnings, but if you do that on an array, you get errors. I've read through A similar question with element queries vs arrays but since I'm not explicitly running a query on the page, this isn't quite applicable.

Both arrays and objects are iterable so that can't distinguish it. Ideally I'd like to do something like this:

{% if props.cards is array %}
    {% set cardArray = props.cards %}
{% else %}
    {% set cardArray = props.cards.all() %}
{% endif %}
{% for card in cardArray %}
...

Obviously, I'd be fine swapping the if/else conditions for the right test case

2 Answers 2

4

you can use the instance of twig test here.

You want to flip your logic, so test for Query object first else array stuff but this should work I think.

To get the specific class just {% dd props.cards %} in the template for ease.

1
  • 1
    This worked like a charm for me. I did have to double escape the back slashes when single quoting the string, and I found two different classes that were possible on one component, because of good code reuse, but problem solved!
    – Greg Bowne
    Commented Jun 10, 2020 at 14:25
1

If you have a custom module/plugin, you can register a Twig extension, and then your class would look something like this:

<?php

namespace my\plugin\twigextensions;

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;


class MyTwigExtension extends AbstractExtension
{
    /**
     * @inheritdoc
     */
    public function getFilters(): array
    {
        return [
            new TwigFilter('isArray', [$this, 'isArray']),
        ];
    }

    /**
     * @inheritdoc
     */
    public function getFunctions(): array
    {
        return [
            new TwigFunction('isArray', [$this, 'isArray']),
        ];
    }

    /**
     * Twig function to test if something is an array or not.
     *
     * This is useful for checking if something has been eager loaded or just a db query
     * class that needs to be executed.
     *
     * @param mixed $variable
     * @return bool
     */
    public function isArray($variable): bool
    {
        return is_array($variable);
    }
}

Now you can do this in your templates:

{% if isArray(props.cards) %}
...

or

{% if props.cards|isArray %}
...

The benefit of doing it this way is you don't need to know the db query class of your field. I find this to be more flexible for checking if something's been eager loaded or not, although it does require you to have a custom module set up for it to work, which in almost any site I work on that's the case anyway. Just another option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.