web-dev-qa-db-fra.com

Utilisation d'un appel direct à la base de données sans erreur de mise en cache

J'ai une fonction personnalisée qui crée une plage d'année de copyright dynamique basée sur l'année du premier et du dernier article de la base de données:

function jldc_copyright_dates() {
    global $wpdb;
    $copyright_dates = $wpdb->get_results( "
        SELECT
            YEAR(min(post_date_gmt)) as firstdate,
            YEAR(max(post_date_gmt)) as lastdate
        FROM
            $wpdb->posts
    " );

    if ( $copyright_dates ) {
        $copyright_year = $copyright_dates[0]->firstdate;
        if ( $copyright_dates[0]->firstdate !== $copyright_dates[0]->lastyear ) {
            $copyright_year .= '—' . $copyright_dates[0]->lastdate;
        }
        echo esc_html( $copyright_year . ' '; );
    }
}

J'utilise PHPCS avec les normes de code WordPress VIP et lorsque je l'exécute sur ce fichier, un avertissement s'affiche: Usage of a direct database call is discouraged.

De plus, je reçois aussi une erreur Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set or wp_cache_delete.

Comment pourrais-je effectuer des tests pour voir si ces valeurs sont mises en cache et si non, les mettre en cache pour que cette erreur disparaisse?

2
Cedon

Je suis d'accord avec @Tom J Nowell:

Je vous suggère de le supprimer ou, mieux encore, de dire "Tous droits réservés".

Mais dans la quête de réponses, voici une suggestion utilisant un champ d’option pour mettre en cache les années:

/**
 * Get year range for posts.
 * 
 * @return str
 */
function wpse_226627_get_copyright() {
    if ( ! $years = get_option( 'copyright' ) ) {
        $args = [
            'posts_per_page' => 1,
            'post_type'      => get_post_types([ 'public' => true ]),
            'post_status'    => 'publish',
            'orderby'        => 'post_date',

            /**
             * Don't waste memory we don't need
             */
            'update_post_term_cache' => false,
            'update_post_meta_cache' => false,
            'cache_results'          => false,
        ];

        $newest = get_posts([ 'order' => 'DESC' ] + $args );
        $oldest = get_posts([ 'order' => 'ASC'  ] + $args );
        $years  = [
            'from' => $oldest ? mysql2date( 'Y', $oldest[0]->post_date_gmt ) : '',
            'to'   => $newest ? mysql2date( 'Y', $newest[0]->post_date_gmt ) : '',
        ];

        update_option( 'copyright_years', $years );
    }

    return $years;
}

/**
 * Bust the cache.
 */
function wpse_226627_flush_years( $post_id ) {
    if ( in_array( get_post_type( $post_id ), get_post_types([ 'public' => true ]) ) )
        update_option( 'copyright_years', '' );
}

add_action( 'before_delete_post', 'wpse_226627_flush_years' );
add_action( 'save_post',          'wpse_226627_flush_years' );

De cette façon, le cache n'est vidé et rempli que lorsqu'une publication est créée/mise à jour/supprimée, de sorte que quelques requêtes supplémentaires (au lieu d'un appel direct à la base de données) ne sont pas très compliquées ici.

$years     = wpse_226627_get_years();
$copyright = $years['from'];
if ( $years['from'] != $years['to'] )
    $copyright .= ' — ' . $years['to'];

J'ai choisi de mettre en cache les années sous forme de tableau sérialisé (par opposition à la chaîne de droits d'auteur compilée) afin de toujours disposer des valeurs à utiliser de manière indépendante, au cas où vous souhaiteriez jamais changer leur disposition/faire quelque chose de différent.

3
TheDeadMedic