UPDATE: J'ai élaboré la mise en œuvre de la réponse sélectionnée au bas de ce message.
J'implémente un algorithme de tri basé sur l'algorithme de hotness de Reddit , en plus d'une décroissance temporelle (comme Hacker Algorithme d'actualités d'actualités ).
Le code dont je suis actuellement satisfait est le résultat d'essais et d'erreurs dans certaines feuilles d'Excel et autres. Voici le code de travail en PHP:
<?php get_header();
$timenow = time() - 1211380200; // this is my custom Epoch time, it translates to when my first WP post was made ?>
<?php
if ( have_posts() ) : while ( have_posts() ) : the_post();
$hearts = get_post_meta($post->ID, '_tjnz_hearts', true);
$plays = get_post_meta($post->ID, '_tjnz_deals_plays', true);
$downloads = get_post_meta($post->ID, '_tjnz_deals_downloads', true);
$ups = get_post_meta($post->ID, '_tjnz_temperature_upvotes', true);
$downs = get_post_meta($post->ID, '_tjnz_temperature_downvotes', true);
$date = get_post_time('U', true); // fetches the GMT postdate of post in Unix format
$score = ( ( $hearts * 2 ) + $plays + $downloads + $ups ) - $downs;
$order = log( max( abs( $score ), 1 ), 6 );
$seconds = $date - 1211380200;
if( $score > 0 ) { $sign = 1; } elseif( $score < 0 ) { $sign = -1; } else { $sign = 0; }
$hotness = round( $order + ( ( $sign * $seconds ) / 336000 ), 7 );
$degrees = round( ( $order * ( $sign * 32 ) ) + ( ( -4 * ( $timenow - $seconds ) ) / 336000 ), 7 ); ?>
<p>
<?php the_title(); ?> <?php echo $post->ID; ?><br />
<?php echo 'hearts: ' . $hearts . '<br />';
echo 'plays: ' .$plays . '<br />';
echo 'dls: ' .$downloads . '<br />';
echo 'up: ' .$ups . '<br />';
echo 'down: ' .$downs . '<br />';
echo 'date: ' .$date . '<br /><br />';
echo 'score: ' .$score . '<br />';
echo 'order: ' .$order . '<br />';
echo 'seconds: ' .$seconds . '<br />';
echo 'timenow: ' .$timenow . '<br />';
echo 'difference: ' .($timenow - $seconds) . '<br />';
echo 'sign: ' .$sign . '<br /><br />';
echo 'hotness: ' .$hotness . '<br />';
echo 'degrees: ' .$degrees; ?><hr />
</p>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>
Le problème
Le problème avec ce code PHP est que la requête WordPress a déjà été effectuée, elle renvoie donc les publications dans un ordre anti-chronologique.
pre_get_posts
ou utiliser le crochet request
. Oui, j'ai lu la documentation, mais pour moi, cela devient trop avancé maintenant.La structure de la base de données
J'enregistre des méta-valeurs dans la table wp_postmeta
, comme vous pouvez le constater dans mon extrait de code PHP. Le score Hotness réel est calculé à la volée et n'est pas enregistré dans la base de données car il ne serait pas très efficace et surtout pas en temps réel pour les utilisateurs.
Ma question actuelle
Je ne peux pas trier la requête par meta_value
, car les méta-valeurs ne constituent qu'une partie de l'équation. Je veux utiliser le résultat de l'équation comme ordre de tri.
Comment puis-je modifier la requête WordPress principale pour consulter les méta_valeurs, calculer chaque publication en temps réel et renvoyer ces publications de la plus chaude à la plus froide?
Ma mise en œuvre de la réponse choisie
Dans functions.php
j'ai ajouté les deux fonctions suivantes.
// add custom wp_postmeta when a new post is created
add_action( 'wp_insert_post', 'tjnz_prepare_postmeta' );
function tjnz_prepare_postmeta( $post_id ) {
if ( !wp_is_post_revision( $post_id ) ) {
$hotness = round( ( time() - 1211380200 ) / 336000, 7 );
add_post_meta( $post_id, '_tjnz_hearts', 0, true );
add_post_meta( $post_id, '_tjnz_plays', 0, true );
add_post_meta( $post_id, '_tjnz_downloads', 0, true );
add_post_meta( $post_id, '_tjnz_upvotes', 0.000, true );
add_post_meta( $post_id, '_tjnz_downvotes', 0.000, true );
add_post_meta( $post_id, '_tjnz_hotness', $hotness, true );
}
}
// build an array of Hotness stats for post
function tjnz_temperature( $tjnz_post_id, $tjnz_timenow ) {
$hearts = get_post_meta($tjnz_post_id, '_tjnz_hearts', true);
$plays = get_post_meta($tjnz_post_id, '_tjnz_plays', true);
$downloads = get_post_meta($tjnz_post_id, '_tjnz_downloads', true);
$ups = get_post_meta($tjnz_post_id, '_tjnz_upvotes', true);
$downs = get_post_meta($tjnz_post_id, '_tjnz_downvotes', true);
$hotness = get_post_meta($tjnz_post_id, '_tjnz_hotness', true);
$date = get_post_time('U', true);
$score = $hearts + $downloads + $ups - $downs;
$log = log( max( abs( $score ), 1 ), 6 );
$seconds = $date - 1211380200;
if( $score >= 0 ) {
$sign = 1;
} else {
$sign = -1;
}
$degrees = round( ( $log * ( $sign * 32 ) ) + ( ( -9.6 * ( $tjnz_timenow - $seconds ) ) / 336000 ) + 10, 7 );
// round to 7 digits positive/negative -2.4 degrees/day realtime post age +10 free degrees
return array(
'hearts' => $hearts,
'plays' => $plays,
'downloads' => $downloads,
'ups' => $ups,
'downs' => $downs,
'score' => $score,
'hotness' => $hotness,
'degrees' => $degrees
);
}
_tjnz_hotness
est maintenant une méta_valeur pour chaque publication publiée et sera mise à jour chaque fois qu'un utilisateur votera, obtiendra une évaluation négative, téléchargera ou favoris (cœur) une publication. La valeur de _tjnz_hotness
est initialement basée sur l'heure de publication (GMT) de la publication avec une variable score
de 0. L'heure de publication est basée sur l'horodatage Unoch Epoch de la publication, moins mon époque personnelle (date de lancement de mon blog). Peu importe le nombre, cela rend la valeur _tjnz_hotness
inférieure. Un article publié juste après le lancement de mon blog aura une valeur proche de 0.
_tjnz_degrees
est calculé à chaque chargement de page. La page utilise la fonction tjnz_temperature()
pour calculer la valeur degrees
au moment du chargement de la page. Il récupère toutes les méta-informations de la publication et les utilise pour calculer la température actuelle de la publication.
La principale différence entre hotness
et degrees
est que hotness
est utilisé pour le tri réel du courrier. Augmenter/diminuer cette valeur permet de compenser la publication sur une chronologie, par rapport aux autres publications. La valeur degrees
est basée sur cela, mais elle prend en compte l’âge en temps réel d’une publication.
Cela signifie essentiellement que si la variable hotness
d'un message ne change pas, la valeur degrees
commence réellement à chuter (0,1 degré par heure, 2,4 par jour).
La configuration de la log
base 6 fait également en sorte que de plus en plus de votes positifs sont nécessaires pour que le message reste à jour. Finalement, il y aura un moment où il ne pourra tout simplement plus gagner de nouveaux messages. Avec ma formule, il faut environ 5 à 7 jours à un message pour qu'il devienne inévitablement "froid".
Sur ma page personnalisée, je liste les publications de la manière suivante (il s’agit d’une sortie de débogage, aucun contenu de publication n’a encore été affiché).
<?php
/*
Template Name: Hot
*/
get_header();
$timenow = time() - 1211380200;
$hot_query = new WP_Query(
array(
'post_status' => 'publish',
'post_type' => 'post',
'meta_key' => '_tjnz_hotness',
'posts_per_page' => 30,
'orderby' => 'meta_value_num',
'order' => 'DESC'
)
);
if ( $hot_query->have_posts() ) : while ( $hot_query->have_posts() ) : $hot_query->the_post();
$tjnz_temperature = tjnz_temperature( $post->ID, $timenow );
?>
<?php the_title(); ?> <?php echo $post->ID; ?><br />
<?php echo 'hearts: ' . $tjnz_temperature['hearts'] . '<br />';
echo 'plays: ' . $tjnz_temperature['plays'] . '<br />';
echo 'dls: ' . $tjnz_temperature['downloads'] . '<br />';
echo 'up: ' . $tjnz_temperature['ups'] . '<br />';
echo 'down: ' . $tjnz_temperature['downs'] . '<br />';
echo 'score: ' . $tjnz_temperature['score'] . '<br />';
echo 'hotness: ' . $tjnz_temperature['hotness'] . '<br />';
echo 'degrees: ' . $tjnz_temperature['degrees']; ?><hr />
<?php endwhile; else : ?>
<p>Oops, Post Not Found!</p>
<?php endif; get_footer(); ?>
L'autre jour, je pensais comment faire quelque chose comme ça, je recommanderais de sauvegarder les bombes comme une méta-valeur post, qui est mise à jour à chaque vote, sauvegarde ou mise à jour, pour cela vous aurez besoin du filtre save_posts et vous pourrez ensuite obtenir les messages commandés avec pre_get_posts et une méta-requête quelque chose comme
$query->set('meta_key'=>'hottnes');
$query->set('orderby'=>'meta_value_num');
$query->set('order'=>'DESC');
J'espère que cela t'aides.