ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

Why isn’t my multiple channel entry query in expression engine not working?

January 16, 2012 11:17pm

Subscribe [2]
  • #1 / Jan 16, 2012 11:17pm

    dgink

    60 posts

    I am trying to output tab panels for two channels (blog and news) within the same template. I need two entry titles each from the blog and news channel. Unfortunately what I am only getting output from the news channel and not the blog channel. Why is that? Here is my code:

    {exp:channel:entries channel="blog|news" limit="4" disable="category_field|trackbacks|comments"}
     
     {if channel_short_name=='blog'}
      blog: {title}
     {if:elseif channel_short_name=='news'}
      news: {title}
     {/if}
     
    {/exp:channel:entries}

    What gets output is only 4 entries from the news channel.

    I have tried turning dynamic on and off. I have also tried outputting all entries without a limit. I get around 10 news entries and then 4 blog entries at the end of the list.

    The url looks like this: http://www.sitename.com/site_sandbox

    I am following advice mentioned in this thread: http://ellislab.com/forums/viewthread/174525/#828980

    What am I doing wrong? What should I try doing next?

     

  • #2 / Jan 17, 2012 12:04am

    Cheif

    626 posts

    Using Stash that I mentioned via Twtiter, try the following

    //This is your index page
    //Header stuff here
    
    {embed="_includes/latest_entries"} //This gets rendered AFTER the following :blush:
    
    {exp:stash:set name="entries_blog" scope="site" save="yes" output="yes" refresh="30"} //Cached for ALL users for 30 minutes
    {exp:channel:entries channel="blog" limit="2" disable="category_field|trackbacks|comments"}
      blog: {title} 
    {exp:channel:entries}
    {/exp:stash:set} 
    
    {exp:stash:set name="entries_news" scope="site" save="yes" output="yes" refresh="5"} //Cached for ALL users for 5 minutes
    {exp:channel:entries channel="news" limit="2" disable="category_field|trackbacks|comments"}
      news: {title}
    {exp:channel:entries}
    {/exp:stash:set} 
    
    //Footer
    //This is your embed code
    <div class= "latest_wrapper">
        <div class="tab blog">
        {exp:stash:get name="entries_blog"}
        </div>
        <div class="tab news">
        {exp:stash:get name="entries_news"}
        </div>
    </div>

    I’m doing my first site applying the Dry principle and this technique is what makes it awesome, so the code above might or might not work but should head you in the right direction 😊

  • #3 / Jan 17, 2012 12:45am

    dgink

    60 posts

    Hey Stuart,

    I did try out this solution. But the query tripled in rendering time due to the embed being used. Also setting output to yes doubles the output. So I took that out.

    I am still looking for a dynamic way to output multiple channels without using multiple exp:channel:entries tags.

  • #4 / Jan 17, 2012 12:56am

    Cheif

    626 posts

    It’s all relative, once the entries are cached your overhead should be significantly reduced for the remainder of the cache period resulting in a net saving of overhead yes ? Or are you saying that every time that page is hit it renders it all again ?

  • #5 / Jan 17, 2012 12:58am

    dgink

    60 posts

    Meanwhile…thank you Stuart and @mediagirl for helping me understand why this is happening. EE outputs the most recent entries from the database and since these latter are from the news channel, only the news channel entries are coming back.

    To quote stuart: “Expression engine sorts by date, not channel”

  • #6 / Jan 17, 2012 1:02am

    dgink

    60 posts

    It’s all relative, once the entries are cached your overhead should be significantly reduced for the remainder of the cache period resulting in a net saving of overhead yes ? Or are you saying that every time that page is hit it renders it all again ?

    If I use three exp:channel:entries tags, the loading time it 700 milliseconds. If I use the caching approach above, the first time load take 1.9 secs and consequent loads take around 1.3 secs. I don’t know how exactly the page is being rendered all over again. I can’t tell.

    If I need only caching I guess, I could just turn caching on at the template level. What I am looking for is a dynamic way to pass in the channel name so only one loop happens on the template.

  • #7 / Jan 17, 2012 3:02am

    Mark Croxton

    319 posts

    Cheif’s approach is a good one, however he/she has omitted two crucial parameters in the Stash tags: parse_tags=“yes” and replace=“no”.  This will make Stash parse the nested channel entries tag *before* saving the rendered html for reuse. Adding this param will reduce your query count to 2 for the code above and reduce render time to a fraction of the typical time required for 2 channel entries tags.

  • #8 / Jan 17, 2012 3:18am

    dgink

    60 posts

    Hey Mark, thanks for coming in. You’re right. Adding parse_tags=“yes” does reduce my queries down two counts. However, isn’t there a clever way to avoid making multiple channel entry queries in the first place? I am racking my brains for a way to conditionally pass in the channel names and use a common snippet with conditional logic.

    Alternatively, do you think using stash in a files based approach as mentioned here will help optimize my page speed?
    https://github.com/croxton/Stash/blob/dev/docs/working_with_files.md

    The reason why I am so adamant is because this is my home page. I need it loaded within 3 seconds and with me querying 4-5 channels for data on this template, I don’t see that happening. Any ways to meet this target?

  • #9 / Jan 17, 2012 5:49am

    Mark Croxton

    319 posts

    Hi Amit

    you’d need a custom query to get the two latest items in news and blog channels in a single query. You could go down that route if you liked but personally I prefer to keep things simple and readable (for my future self), so I’d stick with the two channel entries tags. Remember that those tags are only going to get run when your Stash cache regenerates.

    To keep overhead to a minimum I would cache the entire output of the homepage using Stash. You can still do this if you are using the viewModel/view approach:

    {!-- viewModel --}
    
    {embed="_includes/latest_entries"}
    
    {!-- set the context to namespace your stash variables. Usually this should be the page uri --}
    {exp:stash:context name="homepage"}
    
    {!-- run the channel entries tags and set stash vars only if the page is NOT cached --}
    {exp:switchee variable="'{exp:stash:not_empty name='page_cache' scope='site' context='@'}'" parse="inward"}
     {case value="'0'"}
      {exp:stash:set name="entries_blog" context="@" parse_tags="yes"}
       {exp:channel:entries channel="blog" limit="2" disable="category_field|trackbacks|comments"}
          blog: {title} 
        {/exp:channel:entries}
      {/exp:stash:set} 
      {exp:stash:set name="entries_news" context="@" parse_tags="yes"} 
       {exp:channel:entries channel="news" limit="2" disable="category_field|trackbacks|comments"}
        news: {title}
       {/exp:channel:entries}
      {/exp:stash:set}
     {/case}
    {/exp:switchee}
    {!-- view --}
    
    {!-- set/retrieve page_cache for 60 minutes --}
    {exp:stash:set name="page_cache" save="yes" refresh="60" parse_tags="yes" replace="no" scope="site" context='@' output="yes"}
    <div class= "latest_wrapper">
        <div class="tab blog">
        {exp:stash:get name="entries_blog" context='@'}
        </div>
        <div class="tab news">
        {exp:stash:get name="entries_news" context='@'}
        </div>
    </div> 
    {/exp:stash:set}
  • #10 / Jan 17, 2012 6:02am

    dgink

    60 posts

    Wow! There’s a lot to do here. Lemme try this and get back to you Mark. Thank you so much for helping out.

  • #11 / Jan 17, 2012 6:05am

    Mark Croxton

    319 posts

    Alternatively, if you wanted to use Stash files and eliminate that embed then you could do the following:

    {!-- viewModel --}
    
    {!-- load, parse and cache the Stash template file for 60 minutes --}
    {exp:stash:get 
        name="homepage"
        scope="site" 
        file="yes" 
        save="yes"
        refresh="60"  
        replace="no"               
        parse_tags="yes"             
    }
    {!-- Stash template file: homepage.html --}
    
    {!-- output html --}
    <div class= "latest_wrapper">
        <div class="tab blog">
        {exp:channel:entries channel="blog" limit="2" disable="category_field|trackbacks|comments"}
            blog: {title} 
        {/exp:channel:entries}
        </div>
        <div class="tab news">
        {exp:channel:entries channel="news" limit="2" disable="category_field|trackbacks|comments"}
            news: {title}
        {/exp:channel:entries}
        </div>
    </div>

     

  • #12 / Jan 17, 2012 9:27am

    dgink

    60 posts

    To keep overhead to a minimum I would cache the entire output of the homepage using Stash. You can still do this if you are using the viewModel/view approach:

    As it happens, I am using the viewModel/view approach. And the code you posted did work (save for a minor typo where the channel entries tag pair wasn’t closed). I would like to understand how it worked. Some things are not clear to me.

    1. Why use exp:stash:set in the view?
    So far in my viewmodel/view approach I have been setting stash variables in the viewmodel and getting them in the view template. In your approach you use set in both in the view as well as view model:

    In the View:

    {exp:stash:set name="entries_blog" context='@'}

    In the viewmodel:

    {!-- set/retrieve page_cache for 60 minutes --}
    {exp:stash:set name="page_cache" save="yes" refresh="60" parse_tags="yes" replace="no" scope="site" context='@' output="yes"}

    Of course, you then go ahead and get the values in the view too:

    {exp:stash:get name="entries_blog" context='@'}

    Why do you do that? How come it works? Would like to understand what’s happening.

    2. What does the replace=“no” parameter do in the snippet above?

    I couldn’t find documentation for this.

    3. What is stash parsing? What is it exactly retrieving?

    You mention that stash parses my channel entries only once. Does that mean a first time visitor on the site will also get a cached serving of my entries. Or does cache only work when the page reloads? Also to clear cache I have to use the flush tags repeatedly. I wish there was a better way to flush cache from the backend. Cached values that don’t respond to code changes are potentially confusing to the developers I work with. Can you suggest a work around?

     


  • #13 / Jan 17, 2012 11:13am

    Mark Croxton

    319 posts

    Why use exp:stash:set in the view?

    The set and get tags both have a parameter output=“yes|no”. This tells Stash to either output the variable or not. By default when using get, output=“yes”. When using set, output=“no” by default. In this case I’ve used set with output=“yes” because I want Stash to both set a variable if it does NOT exist and get a variable if it does. This is basically a ‘trick’ you can use for caching arbitrary bits of template code.

    Replace parameter

    This tells Stash whether it should replace a variable that already exists. By default replace=“yes” for both the get and set tags, meaning every time the template containg the tag is viewed, the Stash tag overwrites the variable value with it’s tagdata. If you set it to “no” then Stash will return the existing variable without replacing the variable’s value, or if the variable doesn’t exist, it will set it as normal. That means we can use it in combination with save=“yes” for persistent caching.


    What is stash parsing? What is it exactly retrieving?

    {!-- set/retrieve page_cache for 60 minutes --}
    {exp:stash:set name="page_cache" save="yes" refresh="60" parse_tags="yes" replace="no" scope="site" context='@' output="yes"}
    <div class= "latest_wrapper">
        <div class="tab blog">
        {exp:stash:get name="entries_blog" context='@'}
        </div>
        <div class="tab news">
        {exp:stash:get name="entries_news" context='@'}
        </div>
    </div> 
    {/exp:stash:set}

    When parse_tags=“yes” Stash will parse it’s tagdata (the text the tag pair encloses) using the EE template engine. It creates a new instance of the Template object and runs the tagdata through a single pass of it’s parser methods. You can choose to run multiple passes of the parser (for nested tags) by setting the parameter parse_depth=“X” where X is the number of passes desired (more passes = more processing/overhead). The rendered tagdata is then saved to the database using the variable name as it’s key. If you look in the Stash table in your database for the key you will see that the value stored looks something like:

    <div class="tab blog">
        blog: title 1 
        blog: title 2 
    </div>
    <div class="tab news">
        news: title 1 
        news: title 2 
    </div>


    Clearing the cache

    I AM planning on a control panel interface for managing the Stash cache in the future. This will likely be a paid add-on (the Stash core will always be free).

    One thing I do is add this to the top of my viewModels (put it in a snippet):

    {exp:switchee variable="get:flush" parse="inward"}
    {case value="1"}
    {exp:stash:flush_cache}
    {/case}
    {/exp:switchee}

    Then when you visit the site in your browser append ?flush=1 to the url to clear the cache.

  • #14 / Jan 17, 2012 12:17pm

    dgink

    60 posts

    Going through these answers in certainly clearing up things for me. This is great stuff. Mark you should absolutely go ahead and release a paid add-on. For the kind of support you deliver, I would be first in line with my credit card in hand.

    The other thing is I feel that the documentation for the switchee stash template-partials/viewmodel approach should now be consolidated given that the forum topics seem to have reached a critical mass. Right now hardly 10 percent of the EE community is aware about the power of this methodology. Easy to understand screen-casts and tutorials would be great for everyone. Cause right now, its really hard for newbies like me to get it.

    I would be happy to serve as technical editor/writer for your documentation efforts.

  • #15 / Jan 17, 2012 9:50pm

    Dan Decker

    7338 posts

    Hi dgink,

    Quite the discussion you started here! I’m glad to see the community has stepped up and offered you several solid options and advice. To keep this discussion going I’ll be moving this thread over to Community Help.

    Thanks everyone!

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases