WAIT: PHP query loop with multiple orderings not working with filters only on page load

Browser: Chrome 148
OS: Windows
URL: https://staging21.divanbleu.com/en/therapists/?_service=408&_lang=english
Video: Jam

It seems that when custom query loops load on the page and filter using url parameters as opposed to through the filter elements after page load, ignores the orderby clause of my custom query loop.

Query Loop:

return [
    'post_type'      => 'therapist',
    'posts_per_page' => 10,
    'meta_query'     => [
        'relation'      => 'AND',
        'status_clause' => [
            'key'     => 'new_clients_status',
            'value'   => '4',
            'compare' => '!=',
            'type'    => 'NUMERIC',
        ],
        'boost_clause'  => [
            'key'  => 'boost_date',
            'type' => 'NUMERIC',
        ],
    ],
    'orderby' => [
        'status_clause' => 'ASC',
        'boost_clause'  => 'DESC',
    ],
];

A little help from Claude and I now have the following query:

return [
    'post_type'      => 'therapist',
    'posts_per_page' => 10,
    '_therapist_ordered' => true,  
    'meta_query'     => [
        'relation'      => 'AND',
        'status_clause' => [
            'key'     => 'new_clients_status',
            'value'   => '4',
            'compare' => '!=',
            'type'    => 'NUMERIC',
        ],
        'boost_clause'  => [
            'key'  => 'boost_date',
            'type' => 'NUMERIC',
        ],
    ],
    'orderby' => [
        'status_clause' => 'ASC',
        'boost_clause'  => 'DESC',
    ],
];

along with this snippet in my child theme’s functions.php in order to overwrite whatever it is that Bricks is doing to build the query from the url parameters. I do have two versions of the query loop so there’s a mild complexity added in to make that happen.


add_filter('bricks/posts/query_vars', function($query_vars, $settings, $element_id) {

    $is_ordered      = !empty($query_vars['_therapist_ordered']);
    $is_menu_ordered = !empty($query_vars['_therapist_ordered_menu']);

    if (!$is_ordered && !$is_menu_ordered) {
        return $query_vars;
    }

    $existing = $query_vars['meta_query'] ?? [];
    unset($existing['relation'], $existing['status_clause'], $existing['boost_clause']);

    $query_vars['meta_query'] = array_merge(
        ['relation' => 'AND'],
        $existing,
        [
            'status_clause' => [
                'key'     => 'new_clients_status',
                'value'   => '4',
                'compare' => '!=',
                'type'    => 'NUMERIC',
            ],
            'boost_clause' => [
                'key'  => 'boost_date',
                'type' => 'NUMERIC',
            ],
        ]
    );

    $query_vars['orderby'] = $is_menu_ordered
        ? [
            'status_clause' => 'ASC',
            'menu_order'    => 'ASC',
            'boost_clause'  => 'DESC',
          ]
        : [
            'status_clause' => 'ASC',
            'boost_clause'  => 'DESC',
          ];

    unset($query_vars['order']);

    return $query_vars;
}, 999, 3);

add_action('pre_get_posts', function($query) {
    if (empty($query->get('_therapist_ordered')) && empty($query->get('_therapist_ordered_menu'))) {
        return;
    }

    $meta_query = $query->get('meta_query');
    if (empty($meta_query)) return;

    // Define which meta_keys map to which named clause
    $key_map = [
        'new_clients_status' => 'status_clause',
        'boost_date'         => 'boost_clause',
    ];

    $named = [];
    foreach ($meta_query as $key => $clause) {
        if (is_int($key) && is_array($clause)) {
            $meta_key = $clause['key'] ?? null;
            // Use the defined clause name if it's one of ours, otherwise auto-generate
            $clause_name = $key_map[$meta_key] ?? 'filter_' . preg_replace('/[^a-z0-9_]/', '_', $meta_key ?? $key);
            $named[$clause_name] = $clause;
        } else {
            $named[$key] = $clause;
        }
    }

    $query->set('meta_query', $named);
}, 999);

Hard to say if it’s a bug or I’m just trying to do something just a touch more complex than is reasonable to expect from Bricks builder.

Hi @Dawson ,

I tried to replicate this locally, but all good here. You shouldn’t need the extra code to achieve that.

Is this a query on the archive template? Did you set the query as the main query?

Try:

return [
    'is_archive_main_query'      => true,
    'post_type'      => 'therapist',
    'posts_per_page' => 10,
    'meta_query'     => [
        'relation'      => 'AND',
        'status_clause' => [
            'key'     => 'new_clients_status',
            'value'   => '4',
            'compare' => '!=',
            'type'    => 'NUMERIC',
        ],
        'boost_clause'  => [
            'key'  => 'boost_date',
            'type' => 'NUMERIC',
        ],
    ],
    'orderby' => [
        'status_clause' => 'ASC',
        'boost_clause'  => 'DESC',
    ],
   
];

By the way, you should be able to get the same result by using the GUI.

Regards,
Jenn