Postări aleatorii cu wp_query
Vreau să afișez toate postările ca mywebsite.com/postname/1/
, mywebsite.com/postname/2/
...... mywebsite.com/postname/7/
..
Codul de mai jos funcționează perfect pentru mine, singura problemă este că afișează doar primele postări mywebsite.com/postname/
...
Cum pot face acest lucru?
<?php
/**
* Template Name: Random Post
* Acest șablon va afișa doar conținutul pe care l-ai introdus în editorul de pagină
*/
?>
<html>
<head>
</head>
<body>
<?php
/*
Selector de Postări Aleatorii
Folosește pe pagină pentru a trimite vizitatorul către o postare aleatorie cu query opțional modificat
*/
// setează argumentele pentru WP_Query pentru postări publicate pentru a obține 1 aleatorie
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'rand',
'order' => 'DESC',
// Folosirea date_query pentru a filtra postările din ultima săptămână
'date_query' => array(
array(
'after' => '2 week ago'
)
)
);
// E timpul! Mergi undeva aleatoriu
$my_random_post = new WP_Query ( $args );
while ( $my_random_post->have_posts () ) {
$my_random_post->the_post ();
// redirecționează către postarea aleatorie
wp_redirect ( get_permalink () );
exit;
}
?>
</body>
</html>
A face acest lucru în PHP este o idee proastă:
- Această pagină nu poate fi cache-uită
- Ordonarea aleatorie este extrem de costisitoare pentru interogare, implicând crearea de tabele temporare în baza de date și scanări, deoarece trebuie să copieze întregul tabel de postări, apoi să reordonare aleatoriu postările, și abia apoi să efectueze interogarea pe noul tabel înainte de a-l distruge
- Aceasta vă expune la atacuri de epuizare a resurselor
De exemplu, această comandă va accesa în mod repetat URL-ul postării aleatorii. Dacă este rulată de suficiente ori pe suficiente computere, poate să distrugă baza voastră de date:
for i in `seq 1 20000`; do curl http://mywebsite.com/postname; done
Dacă sunteți pe un hosting partajat ieftin, poate fi suficient să accesați URL-ul în mai multe file de browser simultan pentru a provoca probleme.
Fără să mai vorbim despre faptul că redirectarea trimite antete HTTP, dar codul afișează etichete înainte, așa că antetele au fost deja trimise, stricând funcționalitatea și generând avertismente PHP.
Alternativa Super Rapidă și Ușoară
Deci, în loc de asta, faceți o interogare normală ordonată după dată și afișați datele ca JSON. Apoi, în javascript pe browser, alegeți aleatoriu una dintre acele postări și faceți o redirectare pe partea de client.
În acest fel, pagina poate fi cache-uită, baza de date este protejată, iar browserul face toată munca grea. Interogarea bazei de date va fi foarte rapidă în comparație
Acum problema dvs. se reduce la afișarea unor date într-o listă, alegerea aleatorie a ceva din listă în JS, apoi utilizarea window.location= ...
pentru redirectare. Nu este necesară cunoașterea WP

+1 pentru alternativa pe partea de client. Dar am o întrebare aici, setarea aleatorie în WP_Query
va alege un post aleatoriu dintre să zicem, 15.000 de postări. Dar este eficient să trimiți un răspuns JSON care conține cel puțin 15K de șiruri către browser?

Nu, trimiterea a 15k postări nu este eficientă, nici interogarea pentru 15k postări. Orice implică aleatoriu și baze de date va fi excesiv de costisitor. În schimb, oferiți o alegere mai inteligentă, de exemplu cele mai recente 20 de postări sau cele mai comentate 20 de postări. Există atât de multe alternative la aleatoriu când listezi postări, iar aleatoriu rareori înseamnă ceea ce oamenii cred că înseamnă. Dacă site-ul ar returna aceeași postare de 10 ori, acesta ar fi un rezultat valid al unei selecții cu adevărat aleatorii, la fel ar fi și 5 postări la rând, dar oamenii se referă de fapt la 10 postări distribuite uniform pe întreg intervalul

Deci, ce sugerezi pentru un blog care are mii de postări? Este o idee bună să setezi un offset aleatoriu și apoi să interoghezi 1 postare?

nu, sugestia mea este să nu încerci să alegi la întâmplare dintre mii de postări, în același mod în care retragerea a 1 milion de lire sterline de la bancă este la fel de costisitoare indiferent dacă o faci prin card, cec sau alte mijloace. Aleatorul este o idee proastă, cu adevărat aleatoriu este și mai rău, trebuie să faci un compromis și să dai aparența aleatoriei sau să-ți limitezi sfera de acțiune. Există un număr enorm de alternative care arată la fel, obținerea unui număr cu adevărat aleatoriu din 15k postări fără să le cunoști în prealabil pe toate este fundamental costisitoare

Interesant. Dar dacă utilizatorul vizualizează o versiune cache a paginii (page caching), nu ar conta, nu? Evident, postarea returnată aleatoriu va rămâne aceeași până când cache-ul este golit. Doar dacă cumva 'orderby' => 'rand'
declanșează caching fragmentat...

Da, ar trebui să cache-ui doar acele părți ale paginii, decât dacă nu ai face asta în javascript, oricum aleatorul este o idee groaznică și nu înseamnă niciodată ceea ce intenționezi oricum

Salut Tom, știu că postarea este veche, dar poți să oferi un exemplu cu JSON? Nici măcar nu știu de unde să încep.

@rudtek orice endpoint REST API va returna date în format JSON, iar JSON este același lucru cu obiectele și array-urile în JavaScript, de exemplu [1,2,3,4,5]
este JSON, dar este și un array în JavaScript. Cum ai alege un element aleatoriu dintr-un array în JS este o întrebare pentru stackoverflow, iar cum ai decoda un răspuns JSON dintr-un call AJAX este tot o întrebare pentru stackoverflow, la fel cum este și cum să incluzi un array de elemente într-o pagină HTML pentru a fi folosit în JS. Pentru orice altceva, există json_encode
, standard în vanilla PHP. Sincer, este foarte puțină implicare WordPress, dacă există vreuna

Există și o cale de mijloc în PHP: shuffle($my_random_post->posts)
- dacă este folosit direct înaintea loop-ului - va crea și el o ordine "aleatoare" - dar reține că sortarea unui număr mare de postări ALEATORIU va fi întotdeauna foarte costisitoare și poate fi mai bine gestionată în browser, așa cum sugerează @TomJNowell!

Doar 1 articol este afișat pe partea ta pentru că folosești exit()
în bucla ta. În codul tău, când WP_Query începe și bucla se încheie după un singur contor.
Elimină exit()
și folosește acest cod:
<?php
/*
* Random Post Picker
* Folosește pe pagină pentru a trimite vizitatorul la un articol aleatoriu, opțional modificând interogarea
*/
// setează argumentele pentru WP_Query pe articole publicate pentru a obține 1 la întâmplare
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'rand',
'order' => 'DESC',
// Folosind date_query pentru a filtra articolele din ultima săptămână
'date_query' => array(
array(
'after' => '2 week ago'
)
)
);
// E timpul! Mergem într-un loc aleatoriu
$my_random_post = new WP_Query ( $args );
if($my_random_post->have_posts()){
while ( $my_random_post->have_posts () ) {
$my_random_post->the_post ();
echo '<a href="'.get_the_permalink().'">'.get_the_title().'</a>';
}
}
?>

vreau să fie afișat un singur post și să se facă redirecționare către postul complet. șablonul folosește "mywebsite.com/random/,,,, când un vizitator accesează mywebsite.com/random/ vreau ca utilizatorul să fie redirecționat la postul complet, dar aleatoriu la toate postările, așa cum am explicat " mywebsite.com/postname/15/..... și așa mai departe, postul este ca o galerie, cu "următorul post" vreau ca vizitatorul să fie redirecționat aleatoriu la un număr de post, nu doar la post.

folosind pagina mea random redirecționez utilizatorii către un post aleatoriu. același domeniu. mypage.com/random/ către mypage.com/somepost/ .... mypage.com/anotherpost/.... până aici este totul ok, vreau mai mult.... > mypage.com/somepost/2/..mypage.com/somepost/3

Îmi pare rău că nu te-am înțeles. Spune-mi mai întâi dacă acest permalink al codului nu funcționează sau dorești să schimbi permalink-ul postărilor. Te rog să clarifici cerința ta.

@adikica dacă faci redirectare PHP => trebuie să o faci ÎNAINTE de orice HTML este afișat... nu în mijlocul template-ului - poți folosi redirectare javascript pe partea de client sau acțiunea template_redirect

Nu este nevoie să redirecționezi utilizatorul către pagina cu articolul aleatoriu și nici nu poți face acest lucru, chiar dacă ai vrea, deoarece nu poți fi redirecționat către mai multe locații simultan.
Prin urmare, pur și simplu afișează articolele aleatorii în interiorul buclei tale:
while ( $my_random_post->have_posts () ) {
$my_random_post->the_post ();
echo '<a href="'.get_the_permalink().'">'.get_the_title().'</a>';
}
