7

I want to list a channel's entries by category. It's a kind of hybrid of using EE's category_archive tag but inside of exp:channel:entries. I have an ugly solution (shown here); it violates every DRY principle out there, but I don't know how to do it better.

The channel is a glorified list of links with explanation text and image.


The results I'd like to have:

Resource Page Title heading H1

Category A H2
Resource Link 1
Another Resource Link
And another

A different Category H2
Resource Link
Yet Another one
One more here

etc.


How the channel fields are set up:

{title} (obviously)

Channel fields
{resource_url_link} — Link to destination website
{resource_src_logo} — Destination website logo
{resource_rte_blurb} — Brief description of destination site

Note: {title_url} has no business in this channel. At all.


Option I considered but rejected:

Category Archive (link to EE Docs): Limited to only entry title and a path or entity akin to title_url, which will not work.


Ugly workable code/tags I'm using at the moment

(It is ugly, it violates DRY/Don't Repeat Yourself, but the total number of categories are limited so it's doable.)

For each category (see H2 tags), I hand-code category ID in the low_title item, and match that ID in the subsequent exp:channel:entries.

<h2>{exp:low_title:category category_id="7"}</h2>
    {exp:channel:entries channel="resources" disable="pagination|member_data|category_fields" category="7"}
    <div>
        <div><img alt="{title}" src="{resource_src_logo:medium}"></div>
        <div><h3><a href="{resource_url_link}">{title}</a></h3>{resource_rte_blurb}</div>
    </div>
    {/exp:channel:entries}

<h2>{exp:low_title:category category_id="10"}</h2>
    {exp:channel:entries channel="resources" disable="pagination|member_data|category_fields" category="10"}
    <div>
        <div><img alt="{title}" src="{resource_src_logo:medium}"></div>
        <div><h3><a href="{resource_url_link}">{title}</a></h3>{resource_rte_blurb}</div>
    </div>
    {/exp:channel:entries}

Do you know how I can do this better?

5 Answers 5

9

I had the same problem and found that the Stash solution was the best approach for this.

{exp:channel:entries channel="resources" dynamic="no" disable="pagination|member_data|category_fields"}
{exp:stash:append name="resources_{categories limit='1'}{category_id}{/categories}" parse="inward"}
 <div>
    <div><img alt="{title}" src="{resource_src_logo:medium}"></div>
    <div><h3><a href="{resource_url_link}">{title}</a></h3>{resource_rte_blurb}</div>
</div>
{/exp:stash:append}
{/exp:channel:entries}

{exp:channel:categories channel="resources" style="linear" disable="category_fields" show_empty="no"}
    <h2>{category_name}</h2>
    {exp:stash:get name="resources_{category_id}"}
{/exp:channel:categories}
4
  • That does it. I gotta learn more about stash.
    – auntialias
    Nov 26, 2012 at 23:41
  • Note that this piece of code is when there is only one category assigned to the entry. For multiple you will have to use the second piece of code in Mark's comment. Don't forget to mark this the answer if it answered the question.
    – since1976
    Nov 27, 2012 at 0:55
  • Only have 1 category per entry. I needed to go and do some basic reading on Stash before I tried it out. It works. Now I gotta study a bit more to understand how. I think that Stash will help with another unrelated item.
    – auntialias
    Nov 27, 2012 at 4:44
  • Stash is awesome, good luck with the other problem. Remember to post it here if you run into trouble. I believe mark Croxton (creater of stash) follows anything tagged with stash.
    – since1976
    Nov 27, 2012 at 7:15
3

If you're not opposed to using an add-on ee-garage's http://ee-garage.com/nsm-categories does exactly what you describe.

2
2

I'm not too sure on how to make the underlying code better - but the first way you could make this DRY would come with a bit of a performance hit

You could take the below and set this as a new template

<h2>{exp:low_title:category category_id="{embed:id}"}</h2>
{exp:channel:entries channel="resources" disable="pagination|member_data|category_fields" category="{embed:id}"}
<div>
    <div><img alt="{title}" src="{resource_src_logo:medium}"></div>
    <div><h3><a href="{resource_url_link}">{title}</a></h3>{resource_rte_blurb}</div>
</div>
{/exp:channel:entries}

And then in your existing template call it in such a fashion...

{embed="_embeds/.category-info" id="7"}
{embed="_embeds/.category-info" id="10"}

That would work pretty nicely, but as mentioned would have a performance hit with the embeds being used to this degree. That said, this is a nice example where embeds' ability to parse parameters is a nice thing.


My next method is completely made up, I'm not sure if any plugins exist to allow this but if they do you could achieve the same with less of a performance hit.

Firstly, we could set a Preload Replace variable of a comma separated values of the IDs you wish to use...

{preload_replace:pre_categories="7,10"}

Now, we would have a new snippet, for examples sake I'm calling this {sn_category-info}

{exp:counter:increment} {!-- this made up plugin would +1 each time the snippet is called --}
<h2>{exp:low_title:category category_id="{exp:comma_seperated:grab x="{exp:counter:return}" values="{pre_categories}"}"}</h2> {!-- This made up plugin would take the current count position, the comma separated list and find the x'th value, so on the first run 7, on the second 10 --}
{exp:channel:entries channel="resources" disable="pagination|member_data|category_fields" category="{exp:comma_seperated:grab x="{exp:counter:return}" values="{pre_categories}"}"}
<div>
    <div><img alt="{title}" src="{resource_src_logo:medium}"></div>
    <div><h3><a href="{resource_url_link}">{title}</a></h3>{resource_rte_blurb}</div>
</div>
{/exp:channel:entries}

A bit hypothetical, I understand, but those plugins should be relatively simple to write and I think it'd be pretty damn DRY and fast!

2
  • Thanks for this, Andie. Your first example is nice from a "hey this is another way to do embeds w/ parameters, and is good from that standpoint. 2nd, well, who's gonna write those plugins?
    – auntialias
    Nov 26, 2012 at 22:02
  • ...working on some prototypes now. Will share within an hour or so hopefully. --- EDIT: or not, my code editor is playing up. Perhaps tomorrow.
    – Mutual
    Nov 26, 2012 at 22:04
2

This is exactly what I wrote Category Entries for - you tell it what categories you want to list entries for, and it sorts them by the order that you specify. Omitting the list of categories simply ends up sorting by whatever categories are on the entries. The tag is otherwise identical to the {channel:entries} tag.

You end up extracting category information from the entries' {categories} loop, or through other mechanisms such as Category Info.

Example code to sort entries by three specified categories:

<ul>
  {exp:category_entries category="2|3|1" orderby="date"}
    <li>{title} {categories}{category_name}{/categories} - {entry_date}</li>
  {/exp:category_entries}
</ul>

If you need anything added to the tag, you can post a request in the support forum for it and I will add it.

5
  • 1
    I'll try it out. Does your add-on do away with exp:channel:entries then, or does it live inside exp:channel:entries?
    – auntialias
    Nov 26, 2012 at 21:58
  • 1
    Yes, you would use this plugin instead of the {exp:channel:entries} tag. It actually calls the entries for you internally - so you can provide any other parameters you would normally need on here as well. Nov 26, 2012 at 22:10
  • but then how do you tell it which channel to use when it is called? In using your plugin, where do I put in channel="resources"? Do you have an example somewhere that shows this plugin in action? By the way, on line 7 of your plugin file, it says it's Version 0.2, but when I navigate to the plugin's info in the control panel, it states the version # is 0.1.
    – auntialias
    Nov 27, 2012 at 0:16
  • Last sentence in above comment should read: By the way, on line 7 of your plugin file, it says it's Version 0.2, but when I navigate to the plugin's info in the control panel, it states the version # is 0.1. (um, line 18 of your plugin file?)
    – auntialias
    Nov 27, 2012 at 0:23
  • I tried this (and ommitted the channel="resources" altogether): {exp:category_entries category="7|8|9|10|11|12|13|14|15"} <h2>{categories}{category_name}{/categories}</h2> <div> <div><img alt="{title}" src="{resource_src_logo:medium}"></div> <div><h3><a href="{resource_url_link}">{title}</a></h3>{resource_rte_blurb}</div> </div> {/exp:category_entries} Result: When multiple entires in same categeory, the H2 item was listed each time: Category 7 Item listing Category 7 Next item listed Different Category 8 An item here
    – auntialias
    Nov 27, 2012 at 0:36
1

This is the use case for which I wrote Category Sorted Entries Lite (free) and, later, Category Sorted Entries (commercial).

Check them out, as I think they'll accomplish what you need.

n.b. NSM Categories is another great add-on with very similar functionality. It handles advanced custom fields (Matrix/Playa) a bit better, but doesn't include as many options for sorting and filtering by different category groups.

2
  • So the commercial plugin is the one that includes items available from the standard exp:channel:entries? Good to know for future reference. Also, looked at your docs, and things look clear. That's good. I went with stash, but it's always good to know what other tools there are to do the job. Thanks for responding.
    – auntialias
    Nov 27, 2012 at 20:16
  • Yes, that's correct: The commercial version parses custom fields. Dec 1, 2012 at 5:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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