timber icon indicating copy to clipboard operation
timber copied to clipboard

[BUG] Empty post collection is true inside twig if statement

Open rubas opened this issue 1 year ago • 1 comments

Expected Behavior

{% set posts = get_posts({'post_type': 'not_existing'}) %}

{% if posts %}
  This is false
{% endif %}

{% if posts is not empty %}
  This is false
{% endif %}

Actual behavior

{% set posts = get_posts({'post_type': 'not_existing'}) %}

{% if posts %}
  This is true
{% endif %}

{% if posts is not empty %}
  This is false
{% endif %}

Notes

An empty array is falsy in PHP, which allow's Twig's if to tests if an array is empty Doc. This doesn't work, if you have a lazy Post Collection (get_posts) and not an array.

You need to use length or empty to check the Post Collection in Twig.

Solution

I don't see a way to improve this currently as the RFC for falsifable is not implemented - except to return an empty array if the post collection is empty (found_posts == 0).

I suggest updating the docs in the meantime with an example as this is not obvious and can lead to bugs.


What version of Timber are you using?

2.0

What version of WordPress are you using?

6.2

What version of PHP are you using?

8.1

How did you install Timber?

Installed or updated Timber through Composer

rubas avatar Feb 07 '24 18:02 rubas

We fixed the issue with a simple wrapper function.

public static function get_posts(array|false $query = false, array $options = []): null|PostCollectionInterface
  {
    $posts = Timber::get_posts($query, $options);

    if ($posts instanceof \Countable && 0 === \count($posts)) {
      return null;
    }

    return $posts;
  }

rubas avatar Feb 08 '24 09:02 rubas