Skip to content

Map filter doesn't work as documented by Twig #623

@dave-kennedy

Description

@dave-kennedy

According to the Twig documentation, this example should display "Bob Smith, Alice Dupond":

{% set people = [
    {first: "Bob", last: "Smith"},
    {first: "Alice", last: "Dupond"},
] %}

{{ people|map(p => "#{p.first} #{p.last}")|join(', ') }}

However, it throws the following error:

[Sun Mar 20 23:32:27.248660 2022] [php:error] [pid 12] [client 172.17.0.1:64928] PHP Fatal error:  Uncaught TypeError: Illegal offset type in isset or empty in /var/www/localhost/htdocs/pico/vendor/picocms/pico/lib/PicoTwigExtension.php:285
Stack trace:
#0 /var/www/localhost/htdocs/pico/vendor/picocms/pico/lib/PicoTwigExtension.php(152): PicoTwigExtension::getKeyOfVar()
#1 /var/www/localhost/htdocs/pico/vendor/twig/twig/src/Environment.php(497) : eval()'d code(40): PicoTwigExtension->mapFilter()
#2 /var/www/localhost/htdocs/pico/vendor/twig/twig/src/Template.php(453): __TwigTemplate_5751ea7c50eca1750bc3952b6ce22d8d4c2142ae3b68d7ee69add82bb55ba61d->doDisplay()
#3 /var/www/localhost/htdocs/pico/vendor/twig/twig/src/Template.php(420): Twig\\Template->displayWithErrorHandling()
#4 /var/www/localhost/htdocs/pico/vendor/twig/twig/src/Template.php(432): Twig\\Template->display()
#5 /var/www/localhost/htdocs/pico/vendor/twig/twig/src/TemplateWrapper.php(47): Twig\\Template->render()
#6 /var/www/localhost/htdocs/pico/vendor/twig/twig/src/Environment.php(384): Twig\\TemplateWrapper->render()
#7 /var/www/localhost/htdocs/pico/vendor/picocms/pico/lib/Pico.php(514): Twig\\Environment->render()
#8 /var/www/localhost/htdocs/pico/index.php(33): Pico->run()
#9 {main}
  thrown in /var/www/localhost/htdocs/pico/vendor/picocms/pico/lib/PicoTwigExtension.php on line 285

The second example doesn't throw an error:

{% set people = {
    "Bob": "Smith",
    "Alice": "Dupond",
} %}

{{ people|map((last, first) => "#{first} #{last}")|join(', ') }}

However, instead of displaying "Bob Smith, Alice Dupond" it displays "Smith, Dupond".

What I'd really like to do is map a list of tags to lowercase, e.g.:

{% set tags = ['Foo', 'Bar', 'Blah'] %}

{{ tags | map(t => "#{t}" | lower) | join(', ') }}

I've tried several variations, including:

  • {{ tags | map(t => t | lower) | join(', ') }}
  • {{ tags | map(t => t | lower()) | join(', ') }}
  • {{ tags | map(t => t.lower) | join(', ') }}
  • {{ tags | map(t => t.lower()) | join(', ') }}
  • {{ tags | map(t => t | lower(t)) | join(', ') }}
  • {{ tags | map(t => t.strtolower) | join(', ') }}
  • {{ tags | map(t => t.strtolower()) | join(', ') }}

None of these work -- the output is always "Foo, Bar, Blah" -- yet none throw an error. It seems that anything I pass to the map filter it simply ignored. I wonder if the filter is being replaced by Pico's own map filter, which works as described here:

You can return all values of a given array key using the map filter (e.g. {{ pages|map("title") }} returns all page titles).

Any ideas?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions