Postări aleatorii cu wp_query

23 aug. 2017, 15:16:44
Vizualizări: 25.6K
Voturi: 1

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>
3
Comentarii

Ține minte că ordonarea prin rand este extrem de lentă și costisitoare, iar acea pagină nu poate fi stocată în cache. Orice hacker măcar vag competent poate acum să lanseze un atac de tip denial of service ieftin prin accesarea repetată a acelei URL-uri, pentru a-ți suprasolicita serverul de baze de date prin epuizarea resurselor

Tom J Nowell Tom J Nowell
23 aug. 2017 16:01:21

cred că hackerul va avea lucruri mai bune de făcut decât să atace serverul meu care este doar un site local și nu un site de top. despre "lent" - nu vor fi mai mult de 50-100 de utilizatori online simultan. totuși, putem schimba de la "rand" la altceva. mai întâi trebuie să îl fac să funcționeze așa cum îmi doresc.

adi kica adi kica
23 aug. 2017 16:23:49

La momentul când am scris comentariul, aveam în vedere doar 4 sau 5 utilizatori concurenți, dar aceasta este o problemă care poate fi evitată complet. Răspunsul meu de mai jos va funcționa la scară de miliarde de utilizatori concurenți, oferind în același timp încărcări de pagini semnificativ mai rapide

Tom J Nowell Tom J Nowell
23 aug. 2017 16:36:37
Toate răspunsurile la întrebare 3
10

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

23 aug. 2017 16:11:09
Comentarii

+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?

Johansson Johansson
25 aug. 2017 17:11:30

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

Tom J Nowell Tom J Nowell
25 aug. 2017 19:56:04

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?

Johansson Johansson
25 aug. 2017 20:54:48

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

Tom J Nowell Tom J Nowell
25 aug. 2017 21:40:31

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...

Christine Cooper Christine Cooper
11 iun. 2018 13:59:15

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

Tom J Nowell Tom J Nowell
11 iun. 2018 18:34:49

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 rudtek
13 mar. 2019 21:17:18

@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

Tom J Nowell Tom J Nowell
13 mar. 2019 22:17:30

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!

jave.web jave.web
11 aug. 2019 08:24:40

Amestecarea în PHP funcționează și ea, costul constă în a face baza de date să efectueze aleatorizarea, dacă poți muta asta în altă parte, fie în PHP, în browser sau precalculat, atunci obții îmbunătățiri majore

Tom J Nowell Tom J Nowell
12 aug. 2019 16:36:25
Arată celelalte 5 comentarii
6

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>';
    }
}
?>
23 aug. 2017 15:50:20
Comentarii

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.

adi kica adi kica
23 aug. 2017 16:08:28

Doriți să redirecționați utilizatorul către o altă pagină.

Jitender Singh Jitender Singh
23 aug. 2017 16:38:08

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

adi kica adi kica
23 aug. 2017 16:45:56

Î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.

Jitender Singh Jitender Singh
23 aug. 2017 17:05:07

@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

jave.web jave.web
11 aug. 2019 08:20:15

@adikica De asemenea, dacă apelezi exit() după primul post, nu există buclă - așa că folosește doar o instrucțiune if

jave.web jave.web
11 aug. 2019 08:21:00
Arată celelalte 1 comentarii
0

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>';
}
23 aug. 2017 15:36:03