October CMS resources and help articles

Simple and to the point. Optimized by the community.

Exclude blog posts without featured images in OctoberCMS

1
by sam_rat, last modified on October 20th, 2024

When creating hero sliders or similar components, it’s often helpful to exclude blog posts that don’t have a featured image attached. Fortunately, Laravel makes this easy. Here's a simple query that works in Laravel 6 (the version used in 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 the Query in Your Template

The result stored in $posts can be passed to your template layout or CMS page, either in the onInit or onStart function. However, you may notice that the post URLs are missing. This happens because we need to set them manually. Here’s a solution to ensure each post has a URL:

##
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: Extending the Query with BlogHub

For our upcoming Falcon template, we extended this query to allow the user to set either a featured_image or a custom slider_image meta field. This is achieved using our BlogHub extension for OctoberCMS. To ensure that either a featured_image or a slider_image is available, the query is adjusted 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')
                        ->whereNotNull('ratmd_bloghub_meta.value');
            });
        });
    });

To include the slider_image field in your blog posts, install the BlogHub extension and add the following code at the bottom of your 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

Now, you can output the slider_image 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?