Skip to content

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

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?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions