cómo filtrar por apellido para una publicación personalizada

3

Tengo un tipo de mensaje personalizado (orador) y me gustaría cargar la lista de oradores ordenada por apellido. Parece que no puedo entenderlo. Probé el código de esta publicación: enlace

pero no parece funcionar.

add_action( 'init', 'create_post_type' );
function create_post_type() {
  register_post_type( 'event',
    array(
      'labels' => array(
        'name' => __( 'Conferences' ),
        'singular_name' => __( 'Conference' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
  register_post_type( 'speaker',
    array(
      'labels' => array(
        'name' => __( 'Speakers' ),
        'singular_name' => __( 'Speaker' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
  register_post_type( 'sponsor',
    array(
      'labels' => array(
        'name' => __( 'Sponsors' ),
        'singular_name' => __( 'Sponsor' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
  register_post_type( 'venue',
    array(
      'labels' => array(
        'name' => __( 'Venues' ),
        'singular_name' => __( 'Venue' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
  register_post_type( 'session',
    array(
      'labels' => array(
        'name' => __( 'Sessions' ),
        'singular_name' => __( 'Session' )
      ),
      'public' => true,
      'has_archive' => true,
    'supports' => array('title','editor','thumbnail'),
    )
  );
}

El código al que llamo el tipo de publicación personalizada es:

<?php 
// args  
$args = array(
    'numberposts'   => -1,
    'post_type'     => 'speaker',
    'meta_key'      => 'speaker-front-page',
    'meta_value'    => '1',
    'orderby' => 'speaker_last_name',
    'order'   => 'ASC'
);
// query
add_filter( 'posts_orderby' , 'posts_orderby_lastname' );
$the_query = new WP_Query( $args );
?>
<?php if( $the_query->have_posts() ): ?> <div id="speakerrow"><h1>SPEAKERS<h1><hr>
    <?php while( $the_query->have_posts() ) : $the_query->the_post(); 
echo '<div class="flex_column av_one_third flex_column_div">';
echo do_shortcode("[av_image src='". get_field('speaker-photo')."' attachment='' attachment_size='full' align='center' animation='pop-up' styling='' hover='av-hover-grow' link='".get_the_permalink()."' target='' caption='' font_size='' appearance='' overlay_opacity='0.4' overlay_color='#000000' overlay_text_color='#ffffff'][/av_image]" );
echo do_shortcode("[av_heading tag='h2' padding='10' heading='". get_the_title()."' color='' style='blockquote modern-quote modern-centered' subheading_active='subheading_below' subheading_size='15']". get_field('speaker-company')."[/av_heading]");
echo '</div>';
?>

lo mejor que pude pensar fue agregar un metafield personalizado llamado apellido y, de ser posible, me gusta no tener que escribir el apellido del orador dos veces, si es posible.

¿Cómo agrego el orden por campo para ordenar por la segunda (y última) palabra en el título de la publicación?

    
pregunta rudtek 14.08.2015 - 08:47

2 respuestas

7

Ordenar por la última palabra en el título de la publicación

Para ordenar por apellido del hablante , puede usar la siguiente configuración (PHP 5.4+):

// args  
$args = [
    'posts_per_page'   => 10,
    'post_type'        => 'speaker',
    'meta_key'         => 'speaker-front-page',
    'meta_value'       => '1',
    'orderby'          => 'wpse_last_word',          //<-- Our custom ordering!
    'order'            => 'ASC'
];

// query
$the_query = new WP_Query( $args );

donde la entrada 'wpse_last_word' es compatible con lo siguiente:

/**
 * Order posts by the last word in the post_title. 
 * Activated when orderby is 'wpse_last_word' 
 * @link https://wordpress.stackexchange.com/a/198624/26350
 */
add_filter( 'posts_orderby', function( $orderby, \WP_Query $q )
{
    if( 'wpse_last_word' === $q->get( 'orderby' ) && $get_order =  $q->get( 'order' ) )
    {
        if( in_array( strtoupper( $get_order ), ['ASC', 'DESC'] ) )
        {
            global $wpdb;
            $orderby = " SUBSTRING_INDEX( {$wpdb->posts}.post_title, ' ', -1 ) " . $get_order;
        }
    }
    return $orderby;
}, PHP_INT_MAX, 2 );

Esto se basa en mi respuesta aquí en términos de pedido por la última palabra.

    
respondido por el birgire 14.08.2015 - 11:21
3

La respuesta aceptada es bastante frágil y no podrá manejar las muchas variaciones de ordenar por parámetros .

Aquí hay un filtro que debería ser un poco más robusto:

/**
 * Order posts by the last word in the post_title.
 * Activated when orderby is 'wpse_last_word'
 * @link http://wordpress.stackexchange.com/a/198624/26350
 */
add_filter('posts_orderby', function($orderby_sql, \WP_Query $q) {
  $orderbys = $q->get('orderby');
  if (!$orderbys) {
    return;
  }
  if ($orderby_sql) {
    $orderby_sql_array = [$orderby_sql];
  }
  else {
    $orderby_sql_array = [];
  }
  if (!is_array($orderbys)) {
    $words = explode(' ', $orderbys);
    $orderbys = [];
    foreach ($words as $word) {
      $orderbys[$word] = $q->get('order');
    }
  }
  global $wpdb;
  foreach ($orderbys as $orderby => $direction) {
    if ($orderby == 'wpse_last_word') {
      if (!$direction || !in_array(strtoupper($direction), ['ASC', 'DESC'])) {
        $direction = 'DESC';
      }
      $orderby_sql_array[] = "SUBSTRING_INDEX({$wpdb->posts}.post_title, ' ', -1) $direction";
    }
  }
  return implode(', ', $orderby_sql_array);
}, 100, 2);

El uso básico es (pero aceptará variaciones más complejas de orden por parámetros ):

$args = [
    'posts_per_page'   => 10,
    'post_type'        => 'speaker',
    'meta_key'         => 'speaker-front-page',
    'meta_value'       => '1',
    'orderby'          => 'wpse_last_word',
    'order'            => 'ASC'
];

$the_query = new WP_Query( $args );
    
respondido por el Dalin 16.05.2017 - 17:22

Lea otras preguntas en las etiquetas