Answers.Body: <p>You can use arrow functions pretty much everywhere, overcoming Twig's current limitations, via the Closure Plugin by NYStudio107 <a href="https://github.com/nystudio107/craft-closure" rel="nofollow noreferrer">https://github.com/nystudio107/craft-closure</a></p>
  <blockquote>
  <p>Craft Closure allows you to use arrow function closures anywhere,
  which is especially useful with Laravel Collection methods, many of
  which take a closure as a parameter.</p>
  </blockquote>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-09-19T15:25:10.497Z
Answers.LastActivityDate: 2023-09-19T15:25:10.497Z
Answers.UserDisplayName: pecus
Answers.Body: <blockquote>
  <ol>
  <li>Syntax for Laravel methods using arrow functions in twig ?</li>
  </ol>
  </blockquote>
  <p>You're not doing anything wrong, this approach is simply not supported by Twig. Arrow functions in Twig can only be used with built-in filters and functions that expect them – they can't be used as callables, so they can't be passed as parameters into functions. This comes down the implementation details, but because it's not supported, the parser straight up throw the <em>unexpected token</em> error.</p>
  <p>I don't think this caveat is documented anywhere, but it's mentioned <a href="https://github.com/twigphp/Twig/issues/3402#issuecomment-704052291" rel="nofollow noreferrer">in this issue</a>:</p>
  <blockquote>
  <p>It's not supported. Arrow functions are limited in scope.</p>
  </blockquote>
  <p>So using the appropriate Twig filters like <code>map</code> and <code>unique</code> is the correct approach here.</p>
  <hr />
  <blockquote>
  <ol start="2">
  <li>Is a single query possible ?</li>
  </ol>
  </blockquote>
  <p>It's possible, but a bit involved. You need to use two joins to join the <code>content</code> table through the <code>relations</code> junction table to connect join the programs with the associated episodes. Then you can order by the joined the <code>postDate</code> column directly.</p>
  <p>Something like this:</p>
  <pre class="lang-twig prettyprint-override"><code>{% set episodes = craft.entries().section('programs')
      .innerJoin('{{%relations}} programs_relation', '[[programs_relation.targetId]] = [[elements.id]]')
      .innerJoin('{{%entries}} episodes_entries', '[[episodes_entries.id]] = [[programs_relation.sourceId]]')
      .orderBy('episodes_entries.postDate DESC')
      .limit(5)
  %}
  </code></pre>
  <p>The problem with this is that it creates a lot of duplicate results. Probably because the limit is only applied to the sub-query and the inner join creates multiple rows since multiple episodes can be related to a single program. Maybe someone smarter than me can explain how to limit the query to only return unique program entries …</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-05-11T18:25:01.163Z
Answers.Text: Right. Makes sense. Will keep it as is and probably limit the episodes query to 100 episodes or so. That should give me a large enough sample to get 6 programs for the homepage. Thanks for shiming in
Answers.UserDisplayName: Jérôme Coupé
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-05-11T14:25:20.147Z
Answers.LastActivityDate: 2022-05-11T14:25:20.147Z
Answers.UserDisplayName: MoritzLost
Body: <p>I am working on a website for a radio that publishes its programs as podcasts with episodes. Each of the 30 or so programs potentially has a lot of episodes.</p>
  <ul>
  <li>Each entry in the <code>episodes</code> channel has a one to one relation with a program entry through an <code>episodeProgram</code> entry field (episodes are sources and programs are targets)</li>
  <li>I want to display the 6 programs with the most recently published episodes on the homepage</li>
  </ul>
  <p>What I did:</p>
  <ul>
  <li>get all episodes (most recent first)</li>
  <li>get the ids of related programs</li>
  <li>query the <code>programs</code> channel using those ids and <code>fixedOrder</code> to get programs with the most recently published episodes</li>
  </ul>
  <pre><code>{% set allEpisodes = craft.entries()
    .section(&quot;episodes&quot;)
    .with([&quot;episodeProgram&quot;])
    .orderBy(&quot;postDate DESC&quot;)
    .limit(null)
    .collect() %}
  
  {% set recentProgramsIds = allEpisodes|map(item =&gt; item.episodeProgram.collect().first().id)|unique %}     
  
  {% set recentPrograms = craft.entries()
    .section(&quot;programs&quot;)
    .with([&quot;programImage&quot;])
    .id(recentProgramsIds)
    .fixedOrder(true)
    .limit(6)
    .collect() %}
  
  {% for item in recentPrograms %}
    {% if loop.first %}&lt;ul class=&quot;l-grid  l-grid--gap  l-grid--2cols@small  l-grid--3cols@large  u-margin-bottom-xl&quot;&gt;{% endif %}
      &lt;li&gt;
  
        {% include &quot;_components/program.twig&quot; with {
          title: item.commonMediumTitle,
          url: item.url,
          image: item.programImage.collect().first(),
          id: item.id
        } only %}
  
      &lt;/li&gt;
    {% if loop.last %}&lt;/ul&gt;{% endif %}
  {% else %}
    &lt;p&gt;No program found&lt;/p&gt;
  {% endfor %}
  </code></pre>
  <p>Everything seems to work fine but I have two issues/questions:</p>
  <p><strong>1. Syntax for Laravel methods using arrow functions in twig ?</strong></p>
  <p>My code works with the twig <code>|map</code> and <code>|unique</code> filters and I cannot for the life of me figure out how to make it work with the Laravel collections methods (probably my noobness)</p>
  <p>I would like to understand why / how to correct it.</p>
  <p>Here are the two things I tried:</p>
  <pre><code>{% set recentProgramsIds = allEpisodes.map(item =&gt; item.episodeProgram.collect().first().id).unique() %}
  </code></pre>
  <p>Error: <code>Twig\Error\SyntaxError: Arguments must be separated by a comma. Unexpected token &quot;arrow function&quot; of value &quot;=&gt;&quot; (&quot;punctuation&quot; expected with value &quot;,&quot;). in ... index.twig:62</code></p>
  <pre><code>{% set recentProgramsIds = allEpisodes.map((item, key) =&gt; item.episodeProgram.collect().first().id).unique() %}     
  </code></pre>
  <p>Error: <code>Twig\Error\SyntaxError: An opened parenthesis is not properly closed. Unexpected token &quot;punctuation&quot; of value &quot;,&quot; (&quot;punctuation&quot; expected with value &quot;)&quot;). in ... index.twig:62</code></p>
  <p><strong>2. Is a single query possible ?</strong></p>
  <p>Second question, is there a more performant way to query the <code>programs</code> channel for entries with the most recently posted related entries of the <code>episodes</code> channel (perhaps using Yii query builders).</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-05-11T07:15:46.293Z
Comments.Text: Can you provide the error message?
Comments.UserDisplayName: Ben Croker
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-05-11T11:44:50.643Z
Comments.Text: Added it as an edit above
Comments.UserDisplayName: Jérôme Coupé
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-12-13T11:15:19.577Z
Comments.Text: Now it is possible to use laravel collections with arrow functions inside twig with https://github.com/nystudio107/craft-closure
Comments.UserDisplayName: tenshi
Tags: <relations><craft4><collections>
Title: Craft 4: using the new laravel collections and related methods (in a performant way)
ThreadText: # Craft 4: using the new laravel collections and related methods (in a performant way)
  
  (Asked by: username_0 on 2022-05-11)
  
  I am working on a website for a radio that publishes its programs as podcasts with episodes. Each of the 30 or so programs potentially has a lot of episodes.
  
  * Each entry in the `episodes` channel has a one to one relation with a program entry through an `episodeProgram` entry field (episodes are sources and programs are targets)
  * I want to display the 6 programs with the most recently published episodes on the homepage
  
  What I did:
  
  * get all episodes (most recent first)
  * get the ids of related programs
  * query the `programs` channel using those ids and `fixedOrder` to get programs with the most recently published episodes
  
  ```
  {% set allEpisodes = craft.entries()
    .section("episodes")
    .with(["episodeProgram"])
    .orderBy("postDate DESC")
    .limit(null)
    .collect() %}
  
  {% set recentProgramsIds = allEpisodes|map(item => item.episodeProgram.collect().first().id)|unique %}     
  
  {% set recentPrograms = craft.entries()
    .section("programs")
    .with(["programImage"])
    .id(recentProgramsIds)
    .fixedOrder(true)
    .limit(6)
    .collect() %}
  
  {% for item in recentPrograms %}
    {% if loop.first %}<ul class="l-grid  l-grid--gap  l-grid--2cols@small  l-grid--3cols@large  u-margin-bottom-xl">{% endif %}
      <li>
  
        {% include "_components/program.twig" with {
          title: item.commonMediumTitle,
          url: item.url,
          image: item.programImage.collect().first(),
          id: item.id
        } only %}
  
      </li>
    {% if loop.last %}</ul>{% endif %}
  {% else %}
    <p>No program found</p>
  {% endfor %}
  
  ```
  
  Everything seems to work fine but I have two issues/questions:
  
  **1. Syntax for Laravel methods using arrow functions in twig ?**
  
  My code works with the twig `|map` and `|unique` filters and I cannot for the life of me figure out how to make it work with the Laravel collections methods (probably my noobness)
  
  I would like to understand why / how to correct it.
  
  Here are the two things I tried:
  
  ```
  {% set recentProgramsIds = allEpisodes.map(item => item.episodeProgram.collect().first().id).unique() %}
  
  ```
  
  Error: `Twig\Error\SyntaxError: Arguments must be separated by a comma. Unexpected token "arrow function" of value "=>" ("punctuation" expected with value ","). in ... index.twig:62`
  
  ```
  {% set recentProgramsIds = allEpisodes.map((item, key) => item.episodeProgram.collect().first().id).unique() %}     
  
  ```
  
  Error: `Twig\Error\SyntaxError: An opened parenthesis is not properly closed. Unexpected token "punctuation" of value "," ("punctuation" expected with value ")"). in ... index.twig:62`
  
  **2. Is a single query possible ?**
  
  Second question, is there a more performant way to query the `programs` channel for entries with the most recently posted related entries of the `episodes` channel (perhaps using Yii query builders).
  
  **Tags:** relations, craft4, collections
  
  > **Comments:**
  > **username_1**: Can you provide the error message?  
  > **username_0**: Added it as an edit above  
  > **username_2**: Now it is possible to use laravel collections with arrow functions inside twig with https://github.com/nystudio107/craft-closure  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_4 on 2022-05-11. Score: 4 | Accepted answer
  
  > 1. Syntax for Laravel methods using arrow functions in twig ?
  
  You're not doing anything wrong, this approach is simply not supported by Twig. Arrow functions in Twig can only be used with built-in filters and functions that expect them – they can't be used as callables, so they can't be passed as parameters into functions. This comes down the implementation details, but because it's not supported, the parser straight up throw the *unexpected token* error.
  
  I don't think this caveat is documented anywhere, but it's mentioned [in this issue](https://github.com/twigphp/Twig/issues/3402#issuecomment-704052291):
  
  > It's not supported. Arrow functions are limited in scope.
  
  So using the appropriate Twig filters like `map` and `unique` is the correct approach here.
  
  ---
  
  > 2. Is a single query possible ?
  
  It's possible, but a bit involved. You need to use two joins to join the `content` table through the `relations` junction table to connect join the programs with the associated episodes. Then you can order by the joined the `postDate` column directly.
  
  Something like this:
  
  ```twig
  {% set episodes = craft.entries().section('programs')
      .innerJoin('{{%relations}} programs_relation', '[[programs_relation.targetId]] = [[elements.id]]')
      .innerJoin('{{%entries}} episodes_entries', '[[episodes_entries.id]] = [[programs_relation.sourceId]]')
      .orderBy('episodes_entries.postDate DESC')
      .limit(5)
  %}
  
  ```
  
  The problem with this is that it creates a lot of duplicate results. Probably because the limit is only applied to the sub-query and the inner join creates multiple rows since multiple episodes can be related to a single program. Maybe someone smarter than me can explain how to limit the query to only return unique program entries …
  
  > **Comments:**
  > **username_0**: Right. Makes sense. Will keep it as is and probably limit the episodes query to 100 episodes or so. That should give me a large enough sample to get 6 programs for the homepage. Thanks for shiming in  
  
  ---
  
  ### Answer by username_3 on 2023-09-19. Score: 1
  
  You can use arrow functions pretty much everywhere, overcoming Twig's current limitations, via the Closure Plugin by NYStudio107 <https://github.com/nystudio107/craft-closure>
  
  > Craft Closure allows you to use arrow function closures anywhere,
  > which is especially useful with Laravel Collection methods, many of
  > which take a closure as a parameter.
  
  
  ---
  
  