Skip to content

Post Collections

Miguel Muscat edited this page Nov 30, 2022 · 1 revision

Post collections are an abstraction for WP_Query. They allow you to create a post query without submitting it to the database, and derive new variations of that query through a fluent interface.

This is useful for creating a query that you want to use in multiple places, or for creating a "base" query for a set of posts that you want to modify in different ways later on.

Usage

Post collections are created using a query arguments array, just like WP_Query.

use RebelCode\WpSdk\Wp\PostCollection;

$collection = new PostCollection([
    'post_type' => 'books',
    'post_status' => 'publish',
    'posts_per_page' => 10,
    'meta_query' => [
        [
            'key' => 'author',
            'value' => 'J.K. Rowling',
        ],
    ]
]);

$posts = $collection->get();

The query is not executed until you call a method that requires the results, such as:

Iterate over collection

foreach ($collection as $post) {
    // ...
}

Get array of posts

$posts = $collection->get();

Get Iterator for posts

$iterator = $collection->getIterator();

Get the number of posts

$count = $collection->count();

Get a post with a specific ID

$post = $collection->getById(123);

if ($post === null) {
    // Post not found
}

Note: this will only retrieve posts that have the given ID and also satisfy the collection's query.

Get the first post

$first = $collection->first();

Map the posts

$titles = $collection->map(function ($post) {
    return $post->post_title;
});

Filter the posts

$filtered = $collection->filter(function ($post) {
    return strpos($post->post_title, 'News:') === 0;
});

Reduce the posts

$comments = $collection->reduce(0, function ($total, $post) {
    return $total + $post->comment_count;
}, []);

The following methods do not execute the query, but instead return a new collection with modified query arguments:

Add query arguments

$collection = new PostCollection([
    'post_type' => 'books',
    'post_status' => 'publish',
]);

$collection2 = $collection->with([
    'meta_query' => [
        [
            'key' => 'author',
            'value' => 'J.K. Rowling',
        ],
    ]
]);

Set a post limit

// Limit to 10 posts
$collection2 = $collection->limit(10);

// Remove the limit
$collection3 = $collection2->limit(null);

Set a post offset

// Offset by 10 posts
$collection2 = $collection->offset(10);

Set the page

// Get the second page of posts
$collection2 = $collection->page(2);

Fluent Interface

The fluent interface allows you to chain methods together to create a new collection with modified query arguments, and get its result immediately.

Example 1:

$collection = new PostCollection(['post_type' => 'books']);

$publishedBooks = $collection
    ->with(['post_status' => 'publish'])
    ->limit(10)
    ->page(2)
    ->get();

Example 2: Pagination

Pagination is a common task with post queries. With post collections, pagination can be easily achieved by using the limit() method to create a new collection with a fixed page size, and then calling page()->get() on that collection to get each individual page.

$paginated = $collection->limit(20);

$page1 = $paginated->page(1)->get(); // First page
$page2 = $paginated->page(2)->get(); // Second page
$page3 = $paginated->page(3)->get(); // Third page

Services

You can easily create a post collection factory service using the PostCollection::factory() static method. It accepts the query arguments array as its only argument, like the constructor.

use RebelCode\WpSdk\Module;
use RebelCode\WpSdk\Wp\PostCollection;

class MyModule extends Module
{
    public function getFactories() : array
    {
        return [
            'books' => PostCollection::factory([
                'post_type' => 'books',
                'post_status' => 'publish',
            ]),
        ];
    }
} 

Clone this wiki locally