<p>Twig is a templating language, and in my opinion this is pushing what it's comfortably meant to do. You might want to consider handling the heavy lifting w/ PHP by writing a small <a href="https://github.com/lindseydiloreto/craft-businesslogic" rel="nofollow">business logic plugin</a>, or take a look at third party plugins like Micheal Rog's <a href="http://michaelrog.com/craft/lagniappe/supersort" rel="nofollow">SuperSort</a> to help out.</p>

<p>That being said, if you want to go plugin-less the following should work (<em>note that you'll need to change "myProjectCategoryHandle" to the actual handle of the category group used for the <code>projectCategory</code> field</em>):</p>

<pre><code>{# Pull entries, group by category field "projectCategory" #}
{% set entries = craft.entries.section( 'projects' ) | group( 'projectCategory.first().title' ) %}

{# Get all category titles for the category group "yourProjectCategoryHandle" #}
{% set categories = craft.categories.group( 'yourProjectCategoryHandle' ).titles %}

{# Loop through the category title array #}
{% for category in categories %}

    {# Get the entries grouped under the current category title (if any) #}
    {% set catEntries = entries[ '' ~ category ] | default( [] ) %}

    {# Print the category title and entries #}
    {% if catEntries | length %}
    &lt;h4 class="sc"&gt;{{ category }}&lt;/h4&gt;
    &lt;ul class="no-bullet"&gt;
        {% for entry in catEntries %}
            &lt;li&gt;&lt;a href="{{ entry.url }}"&gt;{{ entry.title }}&lt;/a&gt;&lt;/li&gt;
        {% endfor %} {# -- // for entry -- #}
    &lt;/ul&gt;
    {% endif %}

{% endfor %}
</code></pre>

CC BY-SA 3.0
2015-04-14T19:57:53.653Z
That is insane! Shouldn't the default order be the order that the categories are set in the Admin CP? Seems like I should have to force the order just to make the category order not how they are arranged.

I did look at SuperSort but there doesn't seem to be an option to sort by the fixer order.
smartpill
CC BY-SA 3.0
2015-04-14T20:08:26.233Z
That said, I just tried it and your solution does work. So thank you.
smartpill
CC BY-SA 3.0
2015-04-14T20:18:55.313Z
The problem is that the ```group``` filter has no idea about order – it just takes an array of objects (the entries) and an array of strings (the category titles) and sorts the former on whatever matches. The entries are really what determines the order in this case.
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2015-04-14T19:19:16.987Z
2015-04-14T19:19:16.987Z
Mats Mikkel Rummelhoff
<p>Depending on your needs, you may be able to ditch the group() filter and sort your list however you need.</p>

<p>Get all your entries and categories. Then use the relatedTo functions to filter those lists.</p>

<pre><code>{% set categories = craft.categories.group('projectCategories') %}
{% set projects = craft.entries.section('projects').order('title').limit(null) %}

{% for category in categories.relatedTo(projects) %}
  &lt;h3&gt;{{ category.title }}&lt;/h3&gt;

  &lt;ul class="no-bullet"&gt;
    {% for entry in projects.relatedTo(category) %}
      &lt;li&gt;&lt;a href="{{ entry.url }}"&gt;{{ entry.title }}&lt;/a&gt;&lt;/li&gt;
    {% endfor %}
  &lt;/ul&gt;
{% endfor %}
</code></pre>

<p>One caveat might be that this solution pulls all your entries and categories. This worked for my situation where I had around 50 categories and under 200 entries. I also knew these numbers wouldn't get bigger in the future.</p>

<p>This also makes a few other assumptions too...</p>

<ul>
<li>You DON'T need to show entries with NO related categories like this:</li>
</ul>

<p><strong>Category A</strong></p>

<ul>
<li>entry</li>
<li>entry</li>
</ul>

<p><strong>Category B</strong></p>

<ul>
<li>entry</li>
</ul>

<p><strong>(No Categories)</strong></p>

<ul>
<li>entry</li>
</ul>

<p>Also, your entries can show up under EACH category they're related to, instead of just the FIRST category like your original code. For example, if Entry 1 has Category A and Category B selected, you'll get this:</p>

<p><strong>Category A</strong></p>

<ul>
<li>entry 1</li>
</ul>

<p><strong>Category B</strong></p>

<ul>
<li>entry 1</li>
</ul>

CC BY-SA 3.0
2015-04-16T10:21:43.243Z
Aside from the possible performance issue with pulling all entries & categories, this solution will print – unless I misread your code above – entries multiple times, i.e. once for each category its related to; whereas the original code will only print an entry once, even its related to multiple categories. I'm assuming the latter is wanted behaviour in this case (although if the category field has a hard 1 category limit it probably won't be an issue either way).
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2015-04-16T20:27:03.417Z
You are correct. That's another difference with this solution. The original code will also show entries related to NO categories whereas this won't. I'll do a little editing on my answer.
Alex Roper
CC BY-SA 3.0
2015-04-16T22:05:08.733Z
Thanks Mats. You put me on the track to completely refactor my code and simplify the answer. :)
Alex Roper
CC BY-SA 3.0
2015-04-16T07:56:51.923Z
2015-04-16T22:03:59.103Z
2015-04-16T22:03:59.103Z
Alex Roper
<p>I found a solution to <a href="https://craftcms.stackexchange.com/questions/2749/how-do-i-output-entries-by-their-category">grouping entries by category here</a> which is working perfectly but I need the categories in the order they were arranged in the categories tab in the Admin panel.</p>

<p>Currently, the categories are outputting in the order they were entered but they've been re-ordered since then.</p>

<p>I tried using <code>.fixedOrder(true)</code> in a few places but nothing good happened. This is the current code: </p>

<pre><code>{% set entries = craft.entries({
  section: 'projects'
}).find() %}

{% for category, catEntries in entries|group('projectCategory.first().title') %}
    &lt;h4 class="sc"&gt;{{ category }}&lt;/h4&gt;

    &lt;ul class="no-bullet"&gt;
        {% for entry in catEntries %}
            &lt;li&gt;&lt;a href="{{ entry.url }}"&gt;{{ entry.title }}&lt;/a&gt;&lt;/li&gt;
        {% endfor %} {# -- // for entry -- #}
    &lt;/ul&gt;
{% endfor %}{# -- // for category -- #}
</code></pre>

CC BY-SA 3.0
2015-04-16T21:26:47.000Z
Do all projects have a category? Or do you need to show entries that are category-less? Also, should projects show up under EACH category they are related to or only be limited to the FIRST category like the code you have above does?
Alex Roper
<ordering><group>
How Do I group entries by Category and retain fixed Category Order?
# How Do I group entries by Category and retain fixed Category Order?

(Asked by: username_0 on 2015-04-14)

I found a solution to grouping entries by category here which is working perfectly but I need the categories in the order they were arranged in the categories tab in the Admin panel.
Currently, the categories are outputting in the order they were entered but they've been re-ordered since then.
I tried using .fixedOrder(true) in a few places but nothing good happened. This is the current code: 
{% set entries = craft.entries({
  section: 'projects'
}).find() %}

{% for category, catEntries in entries|group('projectCategory.first().title') %}
    {{ category }}

    
        {% for entry in catEntries %}
            {{ entry.title }}
        {% endfor %} {# -- // for entry -- #}
    
{% endfor %}{# -- // for category -- #}

**Tags:** ordering, group
> **Comments:**
> **username_1**: Do all projects have a category? Or do you need to show entries that are category-less? Also, should projects show up under EACH category they are related to or only be limited to the FIRST category like the code you have above does?  

---

## 2 answers

### Answer by username_2 on 2015-04-14. Score: 3 | Accepted answer

Twig is a templating language, and in my opinion this is pushing what it's comfortably meant to do. You might want to consider handling the heavy lifting w/ PHP by writing a small business logic plugin, or take a look at third party plugins like Micheal Rog's SuperSort to help out.
That being said, if you want to go plugin-less the following should work (note that you'll need to change "myProjectCategoryHandle" to the actual handle of the category group used for the projectCategory field):
{# Pull entries, group by category field "projectCategory" #}
{% set entries = craft.entries.section( 'projects' ) | group( 'projectCategory.first().title' ) %}

{# Get all category titles for the category group "yourProjectCategoryHandle" #}
{% set categories = craft.categories.group( 'yourProjectCategoryHandle' ).titles %}

{# Loop through the category title array #}
{% for category in categories %}

    {# Get the entries grouped under the current category title (if any) #}
    {% set catEntries = entries[ '' ~ category ] | default( [] ) %}

    {# Print the category title and entries #}
    {% if catEntries | length %}
    {{ category }}
    
        {% for entry in catEntries %}
            {{ entry.title }}
        {% endfor %} {# -- // for entry -- #}
    
    {% endif %}

{% endfor %}

> **Comments:**
> **username_0**: That is insane! Shouldn't the default order be the order that the categories are set in the Admin CP? Seems like I should have to force the order just to make the category order not how they are arranged.  I did look at SuperSort but there doesn't seem to be an option to sort by the fixer order.  
> **username_0**: That said, I just tried it and your solution does work. So thank you.  
> **username_2**: The problem is that the ```group``` filter has no idea about order – it just takes an array of objects (the entries) and an array of strings (the category titles) and sorts the former on whatever matches. The entries are really what determines the order in this case.  

---

### Answer by username_1 on 2015-04-16. Score: 4

Depending on your needs, you may be able to ditch the group() filter and sort your list however you need.
Get all your entries and categories. Then use the relatedTo functions to filter those lists.
{% set categories = craft.categories.group('projectCategories') %}
{% set projects = craft.entries.section('projects').order('title').limit(null) %}

{% for category in categories.relatedTo(projects) %}
  {{ category.title }}

  
    {% for entry in projects.relatedTo(category) %}
      {{ entry.title }}
    {% endfor %}
  
{% endfor %}

One caveat might be that this solution pulls all your entries and categories. This worked for my situation where I had around 50 categories and under 200 entries. I also knew these numbers wouldn't get bigger in the future.
This also makes a few other assumptions too...

You DON'T need to show entries with NO related categories like this:

Category A

entry
entry

Category B

entry

(No Categories)

entry

Also, your entries can show up under EACH category they're related to, instead of just the FIRST category like your original code. For example, if Entry 1 has Category A and Category B selected, you'll get this:
Category A

entry 1

Category B

entry 1

> **Comments:**
> **username_2**: Aside from the possible performance issue with pulling all entries & categories, this solution will print – unless I misread your code above – entries multiple times, i.e. once for each category its related to; whereas the original code will only print an entry once, even its related to multiple categories. I'm assuming the latter is wanted behaviour in this case (although if the category field has a hard 1 category limit it probably won't be an issue either way).  
> **username_1**: You are correct. That's another difference with this solution. The original code will also show entries related to NO categories whereas this won't. I'll do a little editing on my answer.  
> **username_1**: Thanks Mats. You put me on the track to completely refactor my code and simplify the answer. :)  

---

