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:
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
.
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.
$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.
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
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 page
post_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.
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>
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.
$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?