1

What I am trying to do:

  • I am in an entry detail page.
  • Entries have a playa field to create relationships w/ other entries
  • First, I need the first 4 related entries, in the order specified by the user in the Playa field
  • Then, I need to add the 4 most recent entries to that list
  • Finally, I need to display the first 4 entries of that list (Playa entries + Recent entries) and filter out duplicates

3 possible scenarios

  • I have no Playa entries > display just the 4 most recent entries
  • I have 4 Playa entries > just display those
  • I have a mix of Playa entries and Recent entries. In that case, Playa entries have to be displayed first in the order specified by the user

Here is what I have tried so far

{!-- SET Entry data --}
{exp:channel:entries disable="member_data|pagination|trackbacks" channel="articles" status="not closed" require_entry="yes" limit="1"}

    {!-- Get first 4 related items in Playa field (combined with latest article and interviews if less than 4 --}
    {exp:stash:set_list name="st_complementary_items" parse_tags="yes"}
        {exp:playa:children channel="articles|interviews" limit="4"}
            {stash:st_complementaryitem_title}{title}{/stash:st_complementaryitem_title}
        {/exp:playa:children}
    {/exp:stash:set_list}

{/exp:channel:entries}


{!-- Get last 4 published articles / interviews items (completes the list if less than 4 in the Playa field  --}
{exp:channel:entries disable="member_data|pagination|trackbacks" channel="articles|interviews" status="not closed" orderby="date" sort="desc" dynamic="no" limit="4"}

    {exp:stash:append_list name="st_complementary_items"}
        {stash:st_complementaryitem_title}{title}{/stash:st_complementaryitem_title}
    {/exp:stash:append_list}

{/exp:channel:entries}


{!-- BUILD page content --}
{exp:stash:set name="content"}

    <p>Total items in list: {exp:stash:list_count name="st_complementary_items"}</p>
    <p>Unique items in list: {exp:stash:list_count name="st_complementary_items" unique="yes"}</p>

    {!-- get the list of related items (Playa + latest if less than 4 playa), still have to make rows unique using the unique=yes parameter --}
    {exp:stash:get_list name="st_complementary_items"}
        <p>[{count}/{total_results}] - {st_complementaryitem_title}</p>
    {/exp:stash:get_list}

{/exp:stash:set}

That works decently well, unless I have no playa items. Then Stash acts as if I have 5 items in my list with a first one that's not parsed.

Total items in list: 5 / Unique items in list: 5

  • [1/5] - {st_complementaryitem_title}
  • [2/5] - Recent Entry title
  • [3/5] - Recent Entry title
  • [4/5] - Recent Entry title
  • [5/5] - Recent Entry title

I am at loss as to why this is happening.

If I completely remove the recent entries loop and just leave the Playa loop, things work as expected and I get 0 entries.

Grateful if anyone can help me out with that.

EDIT: Mark "The" Croxton was quick again: Stash 2.4.4 has been updated to ignore empty list items which apparently was the problem here.

1

I think you are overcomplicating things with Stash. I'd use switchee with the variable {exp:playa:total_children}, I'd set up the cases as:

case value ="0" -> display recent entries with exp:channel:entries

case value ="1|2|3" -> display mix of entries I'd use stash here to retrieve the ids of playa:children and the ids of the most recent entries which I'd then put inside a channel:entries with a limit of 4.

case default (for when there are enough playa entries) -> display playa entries only with exp:playa:children

I hope this helps.

| improve this answer | |
  • 1
    Thanks. Tried that route before. In this case, to deal w/ the mixed case the way you describe I think you need more loops, which is less economical in terms of queries. 1 playa children loop and 1 channel entries loop to get the ids + another channel entries loop to display the data you need from the entries. You also need to pass a few things around (ids of playa and recent entries) + need a way to filter out duplicates. With the solution described above, you just need 2 loops (1 playa and 1 channel entries) and no need to pass variables around. – Jérôme Coupé Oct 19 '13 at 13:41
1

Ok, here is how I ended up coding this in the end:

{!-- Extended page template --}
{stash:embed name="layouts:page"}

{!-- SET Entry data --}
{exp:channel:entries disable="member_data|pagination|trackbacks" channel="articles" status="not closed" require_entry="yes" limit="1"}

    {!-- Get first 4 related items in Playa field (combined with latest article and interviews if less than 4 --}
    {exp:stash:set_list name="st_complementary_items" parse_tags="yes"}

        {exp:playa:children channel="articles|interviews" status="not closed" limit="4"}
            {stash:st_complementaryitem_title}{title}{/stash:st_complementaryitem_title}
            {stash:st_complementaryitem_date}{entry_date format="%F %d, %Y"}{/stash:st_complementaryitem_date}
            {stash:st_complementaryitem_date_machine}{entry_date format="%Y-%m-%d"}{/stash:st_complementaryitem_date_machine}
        {/exp:playa:children}

    {/exp:stash:set_list}

{/exp:channel:entries}


{!-- Get last 4 published articles / interviews items (completes the list if less than 4 in the Playa field  --}
{exp:channel:entries disable="member_data|pagination|trackbacks" channel="articles|interviews" status="not closed" orderby="date" sort="desc" dynamic="no" limit="4"}

    {exp:stash:append_list name="st_complementary_items"}
        {stash:st_complementaryitem_title}{title}{/stash:st_complementaryitem_title}
        {stash:st_complementaryitem_date}{entry_date format="%F %d, %Y"}{/stash:st_complementaryitem_date}
        {stash:st_complementaryitem_date_machine}{entry_date format="%Y-%m-%d"}{/stash:st_complementaryitem_date_machine}
    {/exp:stash:append_list}

{/exp:channel:entries}

{!-- BUILD page content --}
{exp:stash:set name="content"}

        {!-- get the list of related items and make it unique on the titles --}
        {exp:stash:get_list name="st_complementary_items" unique="st_complementaryitem_title"}
            {if count == 1}<ul>{/if}
                <li>[{count}/{total_results}] - {st_complementaryitem_title} - {st_complementaryitem_date} - {st_complementaryitem_type}</li>
            {if count == total_results}</ul>{/if}
        {/exp:stash:get_list}

{/exp:stash:set}

This ends up meeting all my requirements

  • Because the set_list and append list happen in the same "oignon layer" and because the set_list comes first in the code, the playa items are always before the recent items in the stash list
  • Playa items are in the order they were entered by the user and recent items are ordered by date
  • We get rid of duplicates by using the unique parameter (set on titles) on the get_list tag pair

I first tried to use append_lists in both cases and create a type of "playa" or a type of "recent" that I could use to sort the list when I get it to make sure playa items are always before the recent items.

But then, even using nested lists, I couldn't figure out a way of making the titles unique across the playa and recent entries.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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