0

I'm creating a masonry post grid of animals. I plan to filter the the visible posts by toggling classes. The classes would in turn would be the post's.

I'm using an MVC theme and would like to get all my data within the Controller, and not have to do multiple queries within the theme loop.

I'm thinking something this:

<?php

namespace App\Controllers;

use Sober\Controller\Controller;

class PageOurAnimals extends Controller
{
    protected $acf = true;

    public function animals() {
        $args = [
            'posts_per_page' => -1,
            'post_type' => 'portfolio',
            'post_status' => 'publish',
            'order_by' => 'date',
            'order' => 'DESC',
        ];

        return array_map(function($post) {
            $post->terms = [];

           // Maps terms to posts (doesn't work)
            array_map(function($term) {
                if (isset($term)) {
                    array_push($post->terms, $term->slug);
                }
            }, wp_get_post_terms($post->ID, 'category'));

        }, get_posts($args));
    }
}

.

 {-- Blade Template --}
    @foreach($animals as $i => $animal)
            <div class="cell {{ implode(' ', $animal->terms }}">
                <div class="animal animated rollin">
                    <figure class="zoom zoom__container animal__figure">
                        {!!
                            get_the_post_thumbnail($animal->ID, 'medium', [
                                'title' => $animal->post_title,
                                'class' => 'zoom__image'
                            ])
                        !!}
                        <div class="animal__overlay"></div>
                    </figure>
                    <div class="animal__caption">
                        <span class="animal__name">
                            {{ $animal->post_title }}
                        </span>
                    </div>
                </div>
            </div>
        @endforeach

Edit: I looked up the documentation and found array_map doesn't modify the original array, and what I actually want is array_walk().

I've updated the the code to what is below, but it is still returning an empty array.

    $posts = get_posts($args);
    array_walk($posts, function(&$post, $index) {
        $terms = wp_get_post_terms($post->ID, 'category');

        if (isset($terms)) {
            $post->terms = [];

            array_walk($terms, function(&$term, $term_index) {
                // die(print_r($term));
                if (isset($term->slug)) {
                    array_push($post->terms, $term->slug);
                }
            });
        }
    });

    return $posts;
1

I guess you have a problem with variable scopes in here.

        array_walk($terms, function(&$term, $term_index) {
            // die(print_r($term));
            if (isset($term->slug)) {
                array_push($post->terms, $term->slug);
            }
        });

In this part of your code, you use anonymous function and inside of it you use $post variable. But it is a different variable than the one from few lines back - you're in different function now.

But you can simplify that code a lot:

$posts = get_posts($args);
array_walk($posts, function(&$post, $index) {
    $terms = wp_get_post_terms($post->ID, 'category');

    if ( ! empty($terms) && ! is_wp_error($terms) ) {
        $post->terms = [];

        foreach ($terms as $term) {
            $post->terms[] = $term->slug;
        }
    }
});

return $posts;

And even easier, if you know some "magic" WP functions like wp_list_pluck

$posts = get_posts($args);
array_walk($posts, function(&$post, $index) {
    $terms = wp_get_post_terms($post->ID, 'category');
    $post->terms = []; // Prevents error on blade template's implode()

    if ( ! empty($terms) && ! is_wp_error($terms) ) {
        $post->terms = wp_list_pluck( $terms, 'slug' );
    }
});

return $posts;

PS. You have some errors in your $args too.

    $args = [
        'posts_per_page' => -1,
        'post_type' => 'portfolio',
        'post_status' => 'publish',
        'order_by' => 'date',
        'order' => 'DESC',
    ];

It should be orderby instead of oder_by.

  • Ah, I've never actually used a callback in PHP, my brain just processed it as a regular condition :p. I appreciate the wp_list_pluck(), definitely gotta remember that. Thanks for the typo catch, though I think you made one yourself with 'oder_by' haha. – Daniel Foust Jan 11 at 19:38
  • Hahaha. Yeah, I definitely did :p But you’ve got the point - that’s the important part :) – Krzysiek Dróżdż Jan 11 at 19:40

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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