web-dev-qa-db-fra.com

Postes collants sur la page d'accueil, la recherche, les balises et les archives sans plugin

J'ai une question aujourd'hui. Je recherche une solution pour rendre le post-it disponible sur mon site. Mais, je viens de le faire fonctionner sur la page d'accueil avec le code ci-dessous.

function wpb_latest_sticky() { 

/* Get all sticky posts */
$sticky = get_option( 'sticky_posts' );

/* Sort the stickies with the newest ones at the top */
rsort( $sticky );

/* Get the 5 newest stickies (change 5 for a different number) */
$sticky = array_slice( $sticky, 0, 5 );

/* Query sticky posts */
$the_query = new WP_Query( array( 'post__in' => $sticky, 'ignore_sticky_posts' => 1 ) );
// The Loop
if ( $the_query->have_posts() ) {
    $return .= '<ul>';
    while ( $the_query->have_posts() ) {
        $the_query->the_post();
        $return .= '<li><a href="' .get_permalink(). '" title="'  . get_the_title() . '">' . get_the_title() . '</a><br />' . get_the_excerpt(). '</li>';

    }
    $return .= '</ul>';

} else {
    // no posts found
}
/* Restore original Post Data */
wp_reset_postdata();

return $return; 

} 
add_shortcode('latest_stickies', 'wpb_latest_sticky');

Je pensais que le post collant serait également affiché dans les recherches, les tags et les catégories.

Toute solution? Merci!

3
Jornes

Cette même question a été posée plus tôt cette semaine ou ce week-end, et elle m'a fait réfléchir. Voici l'idée que je suis venu avec.

Si vous regardez le code source de la classe WP_Query, vous verrez que les post-its ne sont ajoutés qu'à la première page de la page d'accueil. De plus, aucun filtre n'est fourni pour modifier ce comportement afin de définir les modèles requis en fonction de vos préférences.

Il existe de nombreuses façons d’afficher des articles collants sur d’autres modèles via des widgets, des requêtes personnalisées, des codes abrégés (ce que je ne recommanderai pas, car utiliser do_shortcode() est plus lent que l’utilisation de la fonction elle-même) ou des fonctions personnalisées pour lesquelles vous devez les afficher. J'ai choisi d'utiliser le filtre the_posts et l'action pre_get_posts.

VOICI COMMENT:

  • Récupère les identifiants de post comme post-it avec get_option( 'sticky_posts' )

  • Supprimez ces publications de la requête principale avec pre_get_posts. Les stickies étant inclus sur la page d'accueil, nous exclurons la page d'accueil. Nous exclurons également les pages normales

  • Dans une fonction personnalisée, exécutez une requête personnalisée avec get_posts pour obtenir les publications définies en tant que publications permanentes.

  • Fusionner le tableau renvoyé de post-it avec les posts actuels de la requête principale avec array_merge

  • Accrochez cette fonction personnalisée au filtre the_posts

Voici le code: ( Nécessite PHP 5.4+ )

add_action( 'pre_get_posts', function ( $q )
{
    if (    !is_admin()
         && $q->is_main_query()
         && !$q->is_home()
         && !$q->is_page()
    ) {

        $q->set( 'post__not_in', get_option( 'sticky_posts' ) );

        if ( !$q->is_paged() ) {
            add_filter( 'the_posts', function ( $posts )
            {
                $stickies = get_posts( ['post__in' => get_option( 'sticky_posts' ), 'nopaging' => true] );

                $posts = array_merge( $stickies, $posts );

                return $posts;

            }, 10, 2);
        }

    }
});
3
Pieter Goosen

J'avais besoin de quelques modifications (original, voir la réponse de Pieters) pour que cela fonctionne uniquement sur les pages de catégorie. Cette solution affichera tous les post-its de la catégorie actuelle (et des catégories enfants), mais pas dans les pages de recherche, les balises et les pages simples:

add_action( 'pre_get_posts', function ( $q ) {
    if ( !is_admin()
         && $q->is_main_query()
         && !$q->is_home()
         && !$q->is_tag()
         && !$q->is_search()
         && !$q->is_page()
         && !$q->is_single()
    ) {

      function is_existing_cat($q_catName) {
           $existingCats = get_categories();
           $isExistingCat = false;

           foreach ($existingCats as $cat) {
                if ($cat->name == $q_catName) {
                     $isExistingCat = true;
                }
           }

           return $isExistingCat;
      }

        if ($q->is_category() && !$q->is_paged() && is_existing_cat($q->query['category_name'])) {

            $q->set( 'post__not_in', get_option( 'sticky_posts' ) );

            add_filter( 'the_posts', function ( $posts ) {
                $catName = get_category(get_query_var('cat'))->name;
                $catID = get_cat_ID($catName);

                if ( !empty(get_option( 'sticky_posts' )) ) {
                    $stickies = get_posts( [
                        'category' => $catID,
                        'post__in' => get_option( 'sticky_posts' )
                    ] );

                    $posts = array_merge( $stickies, $posts );
                }

                return $posts;

            }, 10, 2);
        }
    }
});

J'ai ajouté une fonction pour vérifier si la catégorie est une catégorie existante car j'ai rencontré le problème qui m'avait été dirigé vers le fichier category.php au lieu du type attendu 404.php. Des liens comme /existing-cat/not-existing-post fonctionnaient, mais pas des liens comme /not-existing-post-or-page-or-cat.

Si vous avez besoin d'une classe css sur cette publication, vous ajoutez ce code à la partie PHP du modèle qui affiche le contenu de celle-ci (par exemple, dans template-parts/content.php).

<?php
if (is_sticky()) {
    $stickyClass = 'sticky';
} else {
    $stickyClass = '';
}
?>

Ensuite, vous ajoutez cette classe aux classes CSS de la fonction post post_class($stickyClass); (cette fonction ajoutera l'attribut de classe à l'élément HTML avec quelques classes et votre classe ajoutée). Vous pouvez trouver cette fonction déjà située dans l'article:

<article id="post-<?php the_ID(); ?>" <?php post_class($stickyClass); ?>>
    ...
</article><!-- #post-## -->
1
RedNails

La réponse de Pieter fonctionne, mais elle affiche all posts collants même sur des pages lorsque nous voulons afficher des posts filtrés (dans une catégorie donnée par exemple).

Ce qui suit fonctionne pour moi. Ajouter ceci à functions.php n'affiche que les vignettes dans le sous-ensemble de publications filtrées:

add_filter('the_posts', 'bump_sticky_posts_to_top');
function bump_sticky_posts_to_top($posts) {
    $stickies = array();
    foreach($posts as $i => $post) {
        if(is_sticky($post->ID)) {
            $stickies[] = $post;
            unset($posts[$i]);
        }
    }
    return array_merge($stickies, $posts);

(Crédits: http://Pastebin.com/Y5jVrKg4 , avec une légère modification pour empêcher un Avertissement: array_merge () [function.array-merge]: L'argument n ° 1 n'est pas un tableau sur la ligne 9 erreur)

Cependant, il y a un gros défaut. Il ne fera pas la promotion d'un post-it sur le post si ce post-post ne doit pas être présent dans la page en cours.

Un système qui définirait la classe CSS .sticky sur les posts collants serait également Nice.

1
mll