Take the 2-minute tour ×
Craft CMS Stack Exchange is a question and answer site for administrators, end users, developers and designers for Craft CMS. It's 100% free, no registration required.

I have done a "Is featured" switch on articles which works great. I can list the latest 4 featured articles but after that I would like to list the others (Of course they may be featured too). What is the best way to exclude an array of elements when getting elements? Or is there a better solution?

Update 1

{% set allArticles = craft.entries.section('articles').find() %}
{% set featuredArticles = craft.entries.section('articles').featured(1).limit(4).find() %}
{% set notFeaturedArticles = allArticles|without(featuredArticles) %}

This is the code and the notFeaturedArticles returns with the same entries as the allArticles.

Update 2

{% set featuredArticleIds = craft.entries.section('articles').featured(1).limit(4).ids() %}
{% set featuredArticlIdsString = featuredArticleIds | join(', ') %}
{% set notFeaturedArticles = craft.entries.section('articles').id('not '~featuredArticlIdsString) %}

In this case only the first entry is excluded from the not featured articles.

share|improve this question
    
Why do you add answers to your questions text, Hun? This is confusing. –  carlcs Aug 11 at 11:08
    
I am sorry, I thought if I would like to add code formatting to an answer, this is the right way. –  Hun Bubu Aug 11 at 11:32
    
Hmm.. after reading through the answers, I see why you did this. I think it would help if you write some introduction to the code blocks, if you really want to repost the answers here. –  carlcs Aug 11 at 11:39

3 Answers 3

up vote 3 down vote accepted

Craft documentation describes how to exclude entries with a given value. In this case, we want a string that looks like: 'and, not id1, not id2, not id3, not id4'

So we need a string that is all of the featured article ids separated by , not. First, get them as an array using ids():

{% set featuredArticleIds = craft.entries.section('articles').featured(1).limit(4).ids() %}

Then convert that array to a string, using twig's join filter:

{% set featuredArticleIdsString = featuredArticleIds | join(', not ') %}

Then, fetch all the articles, but not the featured ones:

{% set notFeaturedArticles = craft.entries.section('articles').id('and, not '~featuredArticleIdsString) %}

[thanks to carlcs for crucial fix]

share|improve this answer
    
Thanks for the tip. I have already tried this solution too, but the "notFeaturedArticles" filters only the first featured entry. That time I thought it can get only one entry when "not" is there. I have tried again, but with the same results: only the first entry is excluded. –  Hun Bubu Aug 11 at 7:53
1  
@Hun there's a little mistake in Marion's answer. Use this code to compose your IDs string: 'and, not ' ~ featuredArticleIds|join(', not '). –  carlcs Aug 11 at 11:34
    
Thanks for the help. Marion's solution with carlcs's correction works fine. –  Hun Bubu Aug 11 at 12:12

The without filter seems to be a bit picky with parameters. This is what did work in the end:

{# Get the Entry Models of the most recent feature acticles #}
{% set featuredArticles = craft.entries.section('articles').featured(1).limit(4) %}

{# Get the Entry Models of all articles without the most recent feature acticles #}
{% set notFeaturedArticles = craft.entries.section('articles').limit(null)
    |without(featuredArticles[0].title)
    |without(featuredArticles[1].title)
    |without(featuredArticles[2].title)
    |without(featuredArticles[3].title)
%}

Or you get the Entry Models over their IDs:

{# Get IDs of all the articles #}
{% set allArticlesIds = craft.entries.section('articles').ids() %}

{# Get IDs of the most recent feature acticles #}
{% set featuredArticlesIds = craft.entries.section('articles').featured(1).limit(4).ids() %}

{# Get IDs of all articles without the most recent feature acticles #}
{% set notFeaturedArticlesIds = allArticlesIds|without(featuredArticlesIds) %}

{# Get the Entry Models #}
{% set featuredArticles = craft.entries.section('articles').id(featuredArticlesIds) %}
{% set notFeaturedArticles = craft.entries.section('articles').id(notFeaturedArticlesIds) %}
share|improve this answer

I can think of two ways to accomplish this:

The without filter:

Fetch all entries and all featured entries. Then remove the latter from the first:

{% set all          = craft.entries.section('news').find() %}
{% set featured     = craft.entries.section('news').featured(1).find() %}
{% set not_featured = all|without(featured) %}

Pro: You can set the limit for each type individually.
Cons: You need two queries (performance).

UPDATE:
I talked with Brad from P&T and he explained that my example is not working, because after fetching, all and featured become objects not arrays. However it might become possible at some point in the future.

For now you would have to do it like this:

{% set allIds = craft.entries.section('news').ids() %}
{% set featuredIds = craft.entries.section('news').light('1').ids() %}
{% set notFeaturedIds = allIds|without(featuredIds) %}

{% set entries = craft.entries.id(notFeaturedIds) %}

Sorting:

By default all entries are sorted by date. But you could just as well order by "featured" first and then by date.

{% set all = craft.entries.section('news').order('featured desc, postDate desc').find() %}

Pros: One query.
Cons: You can only set one limit.

share|improve this answer
    
I have already tried a similar solution (1st one) which didn't worked for me. I don't know why, but the query with the without() filter simply returns with all the entries. –  Hun Bubu Aug 10 at 20:31
    
You probably have a small mistake in your query, can you show it? –  Victor In Aug 10 at 20:38
    
Victor your without solution doesn't work (see my answer), but that second solution is really nice! @HunBubu have you considered using this? –  carlcs Aug 11 at 13:50
    
@carlcs Yes noticed this too, send a support ticket to make sure it's not a bug and will update the answer when I get an answer. –  Victor In Aug 11 at 14:42
    
@carlcs Updated it with a working example and explanation. –  Victor In Aug 11 at 22:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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