October CMS resources and help articles

Simple and to the point. Optimized by the community.

Select blog posts which contains at least one featured image

1
by sam_rat, last modified on November 14th, 2022

Sometimes, when creating hero sliders or similar components, it would be pretty handy to exclude blog posts which do not have any featured image attached to it. Well, thanks to Laravel this is quite simple with the following query, which is also supported in Laravel 6 (used on OctoberCMS v2):

$query = \RainLab\Blog\Models\Post::with(['categories', 'featured_images'])
    ->withCount('featured_images')
    ->where('featured_images_count', '>', 0);

$posts = $query->listFrontEnd([
    'page'             => 1,
    'sort'             => 'published_at desc',
    'perPage'          => 10,
    'published'        => true,
});

Using on your template

The result stored in $posts can be added to your template layout or CMS page (either on the onInit or on the onStart function). However, you may will notice, that the post links / URLs do not exist, because we need to set them on our own. We're using the following solution for this:

##
url = "/test"
description = "Example Template"
==
<?php 
function onStart()
{
    $query = \RainLab\Blog\Models\Post::with(['categories', 'featured_images'])
        ->withCount('featured_images')
        ->where('featured_images_count', '>', 0));

    // Select posts
    $posts = $query->listFrontEnd([
        'page'             => 1,
        'sort'             => 'published_at desc',
        'perPage'          => 10,
        'search'           => null,
        'category'         => null,
        'published'        => true,
    ]);

    // Get component details
    if (!empty($component = $this->layout->getComponent('blogPosts'))) {
        $postPage = $component->property('postPage');
        $categoryPage = $component->property('categoryPage');
    }
    $ctrl = $this->controller;
    $postPage = empty($postPage) ? 'blog/post' : $postPage;
    $categoryPage = empty($categoryPage) ? 'category/post' : $categoryPage;

    // Set on each post and category
    $posts->each(function($post) use ($ctrl, $postPage, $categoryPage) {
        $post->setUrl($postPage, $ctrl);
        $post->categories->each(fn ($item) => $item->setUrl($categoryPage, $ctrl)); 
    });

    // Pass to template
    $this['featuredPosts'] = $posts;
}
?>
==
<!-- Output -->

Bonus: Extend with BlogHub

We extended this query for our upcoming Falcon template, on which the user is able to set either a featured_image or alternatively a custom slider_image meta value, implemented using our BlogHub OctoberCMS extension. To ensure, that either at least the featured_image or the slider_image value is set, we extended the query as follows:

$query = \RainLab\Blog\Models\Post::with(['categories', 'featured_images', 'ratmd_bloghub_meta'])
    ->withCount('featured_images')
    ->where(function ($builder) {
        $builder->where('featured_images_count', '>', 0);
        $builder->orWhere(function ($builder) {
            $builder->whereHas('ratmd_bloghub_meta', function ($builder) {
                $builder->where('ratmd_bloghub_meta.name', '=', 'slider_image');
                $builder->where('ratmd_bloghub_meta.value', '!=', null);
            });
        });
    });

To include the slider_image field to your blog posts, just install our BlogHub extension and add the following code on the bottom of your current theme.yaml file:

ratmd.bloghub:
    post:
        slider_image:
            tab: Custom Meta
            type: mediafinder
            mode: image
            label: A special image used for sliders only.
            maxItems: 1

The featured image, stored in the slider_image meta field, can then be output as follows:

<img src="{{ post.bloghub.meta.slider_image | media }}" alt="..." /> 

Discussion

0 comments

We use cookies to measure the performance of this website. Do you want to accept these cookies?