web-dev-qa-db-fra.com

Renvoyer la publication parent avec ses enfants en utilisant WP_Query?

Dans certains cas, il peut être utile d’utiliser plusieurs paramètres post & page dans votre objet WP_Query. Dans mon cas, j'aimerais afficher les enfants d'une page parent, y compris la page parent elle-même.

Visualisation de ce que je veux réaliser. Imaginez les pages suivantes classées hiérarchiquement comme suit:

  • page A
  • page B
    • Page enfant A
    • Page enfant B
    • Page enfant C
  • page C

Les éléments de liste en gras sont les articles/pages que je veux récupérer.

Mes premières pensées vont en utilisant ces deux paramètres pour WP_Query:

$args = array(
   'post_id' => $parent->ID,
   'post_parent' => $parent->ID,
);

Malheureusement, ici, il n’utilisera qu’un seul paramètre. Avec le $args ci-dessus (corrigez-moi si je me trompe), toutes les publications enfants de la publication parent seront affichées et not la publication parent elle-même.

Ce problème peut être résolu en rassemblant tous les articles nécessaires et en les plaçant dans le paramètre post__in comme suit:

$args = array(
   'post__in' => $children_and_parent_ids,
);

Cependant, il existe wp_list_pages() vous permettant de include un (des) message (s) et de spécifier le message dans lequel vous voulez inclure les enfants de (child_of). Pourquoi n'est-ce pas possible avec WP_Query?

Voici un exemple de ce que j'essaie de réaliser avec wp_list_pages():

wp_list_pages(array(
    'include' => $parent->ID,
    'child_of' => $parent->ID,
));

Regardez la documentation de WP_Query.

5
Fleuv

Nous pouvons filtrer la clause posts_where du code SQL généré pour renvoyer également la publication/page parent et pas uniquement les enfants du parent. Ici, nous allons définir notre propre argument personnalisé appelé wpse_include_parent, qui, lorsqu'il est défini sur true, modifiera le SQL généré en conséquence.

Dans notre filtre posts_where, il suffit de vérifier si notre argument personnalisé est défini et si l'argument post_parent est défini. Nous obtenons ensuite cette valeur et la passons au filtre pour étendre notre requête SQL. Ce qui est bien ici, post_parent exclut une valeur entière, il suffit donc de valider la valeur en tant qu'entier.

LA REQUÊTE

$args = [
    'wpse_include_parent' => true,
    'post_parent'         => 256,
    'post_type'           => 'page'
    // Add additional arguments
];
$q = new WP_Query( $args );

Comme vous pouvez le constater, nous avons configuré 'wpse_include_parent' => true pour "activer" notre filtre.

LE FILTRE

add_filter( 'posts_where', function ( $where, \WP_Query $q ) use ( &$wpdb )
{
    if ( true !== $q->get( 'wpse_include_parent' ) )
        return $where;

    /**
     * Get the value passed to from the post parent and validate it
     * post_parent only accepts an integer value, so we only need to validate
     * the value as an integer
     */
    $post_parent = filter_var( $q->get( 'post_parent' ), FILTER_VALIDATE_INT );
    if ( !$post_parent )
        return $where;

    /** 
     * Lets also include the parent in our query
     *
     * Because we have already validated the $post_parent value, we 
     * do not need to use the prepare() method here
     */
    $where .= " OR $wpdb->posts.ID = $post_parent";

    return $where;
}, 10, 2 );

Vous pouvez étendre cela à votre guise, mais c'est l'idée de base. Cela renverra le parent passé à post_parent et ses enfants

5
Pieter Goosen

Si tout ce que vous voulez, ce sont les résultats de la "page" post_type, faites comme @birgire suggéré.

Vous pouvez également adapter ce qui suit pour vous donner un résultat similaire non seulement pour la pagepost_type mais pour tout type de publication personnalisé.

$parent = 2;      //change as desired
$type   = 'page'; //change as desired

$child_args = array( 
    'post_type'   => $type, 
    'post_parent' => $parent 
);

$ids = array($parent);
$ids = array_merge($keys, array_keys( get_children( $child_args ) ));

$query = new WP_Query( 
    array( 
        'post_type'      => 'page', 
        'post_status'    => 'publish', 
        'post__in'       => $ids, 
        'posts_per_page' => -1 
    ) 
);

Ce qui précède est essentiellement la même chose que l’accrochage sur le filtre posts_where et l’analyse de la clause SQL, mais cela donne exactement la même chose.

5
userabuser

Utiliser global $wpdb combiné à [get_results()][1] est également une option. En termes de performances, je pense que cette solution est la meilleure car elle n’exécute qu’une requête.

Voici mon code final.

<ul class="tabs"><?php

    global $wpdb, $post;

    $parent = count(get_post_ancestors($post->ID))-1 > 0 ? $post->post_parent : $post->ID;

    $sql = "SELECT ID FROM `{$wpdb->prefix}posts`";
    $sql.= " WHERE ID='{$parent}' OR post_parent='{$parent}' AND post_type='page'";
    $sql.= " ORDER BY `menu_order` ASC";

    $tabs = $wpdb->get_results($sql);

    $output = '';
    foreach ($tabs as $tab) {
        $current = $post->ID == $tab->ID ? ' class="active"' : '';

        $output .= '<li'.$current.'>';
        $output .= empty($current) ? '<a href="'.get_permalink($tab->ID).'">' : '';
        $output .=   get_the_post_thumbnail($tab->ID, 'menu-24x24');
        $output .=   '<span>'.get_the_title($tab->ID).'</span>';
        $output .= empty($current) ? '</a>' : '';
        $output .= '</li>';
    }
    print $output;

?></ul>
0
Fleuv

Si je vous ai bien compris, vous souhaitez obtenir les identifiants du parent et des pages enfants suivantes. Wordpress a des fonctions qui récupèrent les enfants de pages, telles que celle-ci:

https://codex.wordpress.org/Function_Reference/get_page_children

D'après ce que je comprends, puisque vous effectuez une WP_Query, vous récupérez déjà l'ID des pages parentes. Il vous suffit donc de transmettre l'ID correspondant à la fonction ci-dessus pour obtenir ce que vous désirez.

Remarque: je devrais souligner que cette fonction ne fait pas une requête de base de données, il est donc préférable d’en améliorer les performances car vous ne faites que sur une requête à la base de données.

0
EBennett
    $args = array(
        'post_type' => 'tribe_events',
        'posts_per_page' => '-1',
        'orderby' => 'ID',
        'order' => 'ASC',
        'post_parent' => $postID,
    );

    $children = new WP_Query($args);
    $parent[] = get_post($postID);
    $family = array_merge($parent, $children->get_posts());

Cela semble fonctionner. Commentaires?

0
egauvin