Gists

2 months ago
<?php
// Order by a custom field, but prevent posts from disappearing when that field does not exist for those posts.
// It first sorts by the reviews_rating field, then by post title.
// Posts without reviews_rating are sorted by title and added after the ones with the reviews_rating. 

// Important:
// - NOT EXISTS needs to be before EXISTS
// - In 'orderby' it needs to use 'meta_value_num' or 'meta_value' instead of a named meta_query segment.
// - Use 'meta_value' if the custon field is not numerical
// - The order needs to be DESC for the posts without the rating to appear after the ones with it
// See: https://wordpress.stackexchange.com/a/329687 

// Related: 
// https://gist.facetwp.com/gist/gist-bcd7971b433440a5a73b99c73b530a0f/
// https://facetwp.com/how-to-filter-or-sort-a-wp_query-by-one-or-more-custom-fields/#order-a-query-by-a-custom-field
// https://facetwp.com/how-to-filter-or-sort-a-wp_query-by-one-or-more-custom-fields/#order-a-query-by-multiple-custom-fields-that-can-be-empty-for-some-posts
// https://facetwp.com/help-center/developers/hooks/output-hooks/facetwp_facet_sort_options/#add-an-option-to-sort-by-a-custom-field-and-include-posts-without-that-field

add_filter('facetwp_facet_sort_options', function ($options, $params) {

  $options['rating'] = [

    'label' => 'Rating',
    'query_args' => [
      'meta_query' => [
        'relation' => 'OR',
        [
          'key' => 'reviews_rating',
          'compare' => 'NOT EXISTS'
        ],
        [
          'key' => 'reviews_rating',
          'compare' => 'EXISTS'
        ]
      ],
      'orderby' => [
        'meta_value_num' => 'DESC', // Order by rating first. Needs to be 'DESC'. Note: use 'meta_value' if the custom field is not numerical
        'title' => 'ASC' // Order by title second
      ],
      'meta_key' => 'reviews_rating'
    ]
  ];

  return $options;

}, 10, 2 );