Wrz
12
2012

Jak wyświetlić autorów piszących w danej kategorii?

Dzisiaj jeden z czytelników mojego prywatnego bloga napisał:

Witam, chciałem zapytać czy może spotkał się Pan z rozwiązaniem, które chciałbym zastosować na swojej stronie poetyckiej, opartej na WordPressie. Chciałbym np. na podstronie „Nasza poezja” wyświetlić listę tylko tych autorów, którzy opublikowali coś w tej kategorii. W tej chwili wyświetla mi wszystkich autorów. Starałem się znaleźć jakieś rozwiązanie, ale ciągle gdzieś błądzę, stąd pomyślałem o Panu, może będzie mi Pan wstanie pomóc.


Pewnie moja odpowiedź dla wielu będzie banalna ale postanowiłem opisać dokładnie jak działa rozwiązanie aby opis stał się bardziej edukacyjny – często zwłaszcza na początku zabawy z WordPressem bardzo tego typu wpisów brakuje…

Oto rozwiązanie:

  • sprawdzić w jakiej jesteśmy kategorii i pobrać jej ID
    $cats = get_the_category();
    $cat = $cats[0]->term_id;
    
  • pobrać wszystkie wpisy z tej kategorii
  • $cat_posts = get_posts(array('numberposts'=>-1, 'category'=>$cat));
    
  • zrobić tablicę autorów, a następnie dla każdego wpisu sprawdzić autora i umieścić go w naszej tablicy (sprawdzając jednocześnie, czy ten autor już tam nie występuje)
  • $authors = array();
    foreach ($cat_posts as $cat_post) :
    if (!in_array($cat_post->post_author,$authors)) {
    $authors[] = $cat_post->post_author;
    }
    endforeach;
    
  • dla każdego autora znajdującego się w tablicy wyciągnąć jego nazwę (display_name) oraz login (user_login)
  • foreach ($authors as $author) :
    $auth = get_userdata($author)->display_name;
    $auth_link = get_userdata($author)->user_login;
    
  • nadal w pętli „dla każdego” autora wyświetlić nazwę z odpowiednim linkiem do strony /author/nazwa_autora
  • echo '';
    echo $auth;
    echo '
    ';
  • zamknąć „dla każdego” (endforeach)
  • endforeach;
    

Poniżej cały skrypt, który po ostylowaniu wstawiamy do pliku archive.php, category.php lub pochodnych…

$cats = get_the_category();
$cat = $cats[0]->term_id;
$cat_posts = get_posts(array('numberposts'=>-1, 'category'=>$cat));
$authors = array();
foreach ($cat_posts as $cat_post) :
if (!in_array($cat_post->post_author,$authors)) {
$authors[] = $cat_post->post_author;
}
endforeach;
foreach ($authors as $author) :
$auth = get_userdata($author)->display_name;
$auth_link = get_userdata($author)->user_login;
echo '';
echo $auth;
echo '
'; endforeach;

Czy mieliście podobny problem? albo może istnieje jeszcze prostsze rozwiązanie?

O autorze: Jakub Milczarek

Miłośnik wszystkiego co związane ze sprawami użyteczności, a także specjalista z dziedziny fizykochemii kryminalistycznej. Stronami internetowymi zajmuje się od 1997 roku, a z samym WordPressem zaprzyjaźnił się już w 2007 roku. Miał zaszczyt być szefem organizacji pierwszego polskiego WordCampu w 2010 roku, a w latach 2010-2012 prowadził z sukcesami firmę WP-Expert. Obecnie pracuje jako UX Specialist w OnTheGoSystems. W wolnych chwilach zdobywa Koronę Europy, poszukuje skrzynek OpenCaching i bloguje jako Lodzermensch.

14 komentarzy + Dodaj komentarz

  • Dla bloga, który ma dużo wpisów (1k+), nielimitowany get_posts zarżnie wszystko poniżej własnego dedyka… ale patrząc w kod WP, to lepiej można zrobić tylko pakując czystego SQL’a.

    • Znając liczbę autorów całego bloga lub zdroworozsądkową maksymalną liczbę ludzi publikujących w danej kategorii zawsze można dopisać regułę zatrzymującą pętlę w momencie, w którym długość wygenerowanej tabeli jest równa maksymalnej założonej liczbie autorów.

      Może nie sprawi to, że pętla zawsze będzie się zatrzymywać przed przejrzeniem WSZYSTKICH postów, ale przynajmniej nie będzie za każdym razem próbowała ‚zarżnąć wszystkiego poniżej własnego dedyka’…

      • Pętla _nie zostanie_ wykonana ponieważ `get_posts` oprze się o limit pamięci i czasu, więc do „możliwości” wyjścia z pętli nie dojdzie.

        Dodatkowo założenia tego typu nie obejmują statystycznie istotnego toku: ktoś zakłada daną kategorię robiąc w niej pierwszy wpis, po czym nigdy więcej tej kategorii nie używa, więc jako autor jest on dobierany w ostatnim obrocie pętli. Takie życzeniowe uproszczenia są źródłem niesamowicie ciężkich do wytropienia błędów aplikacji (bo wszystko działa bez błędu, ale działa źle).

        • Dziękuję za uwagę – rzeczywiście przy większych stronach może pojawić się problem ale jak sam piszesz trzeba robić zapytanie w SQLu, a ja chciałem spróbować zrobić to w wersji clean WP.
          Jak widać nie zawsze „clean WP” jest opcją najlepszą:)

  • nie testowałem, ale widzę kilka potencjalnych błędów (w działaniu i wydajnosciowych)

    #1
    $cat = $cats[0]->term_id;

    to zwróci ID pierwszej kategorii, do której wpis został przypisany. niekoniecznie bedzie to ‚poezja’. jesli wpis jest przypisany do wiekszej ilosci kategorii niz jedna, efekt moze byc inny niz oczekiwany

    #2
    $authors[] = $cat_post->post_author;

    czy ja sie nie myle ze petla zawierajace powyzsze bedzie w efekcie dawac tablice z powtarzajacymi sie autorami? jesli wpis o id 1 ma autora o id 1, wpis o id 2 tez ma autora 1 to ten autor w tablicy znajdzie sie dwa razy

    na koniec trzeba jeszcze zrobic:
    $authors = array_unique($authors);

    #3
    $auth = get_userdata($author)->display_name;
    $auth_link = get_userdata($author)->user_login;

    dwa razy wywolywana jest funkccja get_userdata(). nie sprawdzilem czy ona kejczuje dane ale lepiej zawsze zalozyc, ze nie. przepisalbym to tak:
    $userdata = get_userdata($author);
    $auth = $userdata->display_name;
    $auth_link = $userdata->user_login;

    #4
    echo ‚‚;

    zadziala, tylko jesli ustawione mamy permalinki o takiej wlasnie strukturze. odnosnik do wszystkich wpisow danego autora uzyskamy dzieki funkcji:
    http://codex.wordpress.org/Function_Reference/get_author_posts_url

    #5

    i na koniec to o czym wszyscy pisali :) wydajnosc. pobranie wszystkich wpisow zarżnie hosting. Jakubie, zwróć uwagę, że na blogu zawsze autorów jest mniej niż wpisów, wiec najlepiej jest pobrac wlasnie samych autorow :) zapytanie sql wyciagajace zarejestrowanych uzytkownikow, ktorzy maja przynajmniej jeden wpis na blogu (uzywam go w stopce tej strony do pokazania naszych awatarow):

    SELECT post_author, count(*) AS liczba_artow FROM $wpdb->posts WHERE post_type = ‚post’ GROUP BY post_author ORDER BY liczba_artow DESC

    gdy juz mamy autorow, dla kazdego mozna zrobic wp_query, ktore pobierze wpisy tego autora przypisane do interesujacej nas kategorii. jesli wpisow jest wiecej niz zero, wyswietlamy tego autora. jesli zero – idziemy do nastepnego

    rozpisalem sie, ale mam nadzieje, ze nie wyjdzie ze sie wymądrzam :) uczmy sie tutaj nawzajem, pewnie ktos i poprawi i moje rozwiazania ;)

    • #1 – Masz niestety rację – pisałem to dla pokazu kategorii i myślałem o jednej kategorii ale przecież listujemy wpisy i sprawdzamy ich wszystkie kategorie – więc tak jak piszesz może być rożnie :)

      #2 – Tutaj się mylisz, bo właśnie po to masz ifa, który sprawdza czy danego autora juz nie wsadziliśmy do tablicy… Oczywiście Twoje rozwiązanie z array_unique tez będzie tutaj OK.

      #3 – Nie pomyślałem o tym, a w testach było generalnie OK… Dzięki za podpowiedź!

      #4 – Oczywiście, ale to już każdy może sobie sam ustawić wedle uznania. Myślę, że nawet niektórzy mogą chcieć jedynie listować autorów bez linków etc.

      #5 – OK masz racje – zapytaniem SQL najłatwiej to zrobić ale ja chciałem spróbować wykorzystania jedynie funkcji WP

      Może napiszesz ripostę do mojego wpisu właśnie rozpisując się o takim podejściu?

      Dzięki za uwagi! Rzeczywiście masz Konradzie rację – ja czuję, ze się uczę cały czas :)

      • #2, racja, przegapilem ifa :) jest jeszcze we mnie mała chęć by powymądrzać się, że natywne array_unique bedzie szybsze niz testowanie ifem, ale już i tak się nawymądrzałem i pewności nie mam czy mam rację, więc milczę ;P

        • #1 – Przemyślałem ten punkt i można spróbować zamiast:
          $cats = get_the_category();
          $cat = $cats[0]->term_id;

          zrobić raczej tak:

          $current_category = single_cat_title(”, false);
          $term = get_term_by(‚name’, $current_category, ‚category’);
          $cat = $term->term_id;

          Wtedy mamy pewność, ze stosowane dalej ID jest dla wyświetlanej kategorii :)

          PS. Wymądrzaj się dalej :), bo jak sam napisałeś – czegoś dzięki temu się nauczymy…

          • Jest jeszcze:
            $cat = get_query_var(‚cat’);

            Krótsze niż 3 linijki a robi chyba to samo…

            P.S. Czuję licytację: kto da mniej! [linii kodu] ;)

  • U mnie, jak na razie „źródłowy kod skryptu” spisuje się bez problemu. Został tylko lekko edytowany, gdyż na każdej statycznej podstronie (dokładnie trzech: poezja, opowiadania, felietony) potrzebuję osobną listę autorów piszących w tak samo nazwanych kategoriach. Efekt jaki chciałem, generalnie się udało mi uzyskać, dorobiłem listę wykropkowaną i mam ową listę autorów :)

    Chciałem po prosić o pomoc w ewentualnym posortowaniu wyników. Chodzi mi o to, by lista autorów była wyświetlana alfabetycznie. Proszę o sugestie w tym temacie:) Pozdrawiam!

    • W oparciu o porady @Konrada #4 i #3 i uwagę @anoriell modyfikujemy trochę kod

      $auth = get_userdata($author)->display_name;

      i po tym jak już wyciągniemy display_name (user_login nie będzie nam już potrzebny) tworzymy tablicę (ID, Nazwa autora):

      $writers[] = array (‚nazwa’ => $auth, ‚id’ => $author);

      (oczywiście to wstawiamy przed endforeach;)

      potem sortujemy naszą tablicę:

      asort($writers);

      i potem całość wyświetlamy w następujący sposób:

      foreach ($writers as $writer) :
      echo ‚<a href=”‚.get_author_posts_url($writer[id]).'”>’;
      echo $writer[nazwa];
      echo ‚</a><br>’;
      endforeach;

      Cały kod, po wszystkich modyfikacjach wygląda (uwagi Konrada i anoriell) następująco:

      $cat = get_query_var(‚cat’);
      $cat_posts = get_posts(array(‚numberposts’=>-1, ‚category’=>$cat));
      $authors = array();
      foreach ($cat_posts as $cat_post) :
      if (!in_array($cat_post->post_author,$authors)) {
      $authors[] = $cat_post->post_author;
      }
      endforeach;

      foreach ($authors as $author) :
      $auth = get_userdata($author)->display_name;

      $writers[] = array (‚nazwa’ => $auth, ‚id’ => $author);
      endforeach;

      asort($writers);

      foreach ($writers as $writer) :
      echo ‚<a href=”‚.get_author_posts_url($writer[id]).'”>’;
      echo $writer[nazwa];
      echo ‚</a><br>’;
      endforeach;

      Jak to pisała @anoriell – kto jeszcze skróci ten kod? :)

  • Mam głupie spostrzeżenie, w tym kodzie już poprawionym ” , i ’ ” powinno być zamienione na” ‚ „? ;)

    Niestety, rezultatem nie jest lista alfabetycznie ułożona. Cały mój kod:

    -1, ‚category’=>1));
    $authors = array();
    foreach ($cat_posts as $cat_post) :
    if (!in_array($cat_post->post_author,$authors)) {
    $authors[] = $cat_post->post_author;
    }
    endforeach;

    foreach ($authors as $author):
    $auth = get_userdata($author)->display_name;

    $writers[] = array (‚id’ => $author, ‚nazwa’ => $auth);
    endforeach;

    asort($writers);

    echo ”;

    foreach ($writers as $writer):

    echo ‚‚;
    echo $writer[nazwa];
    echo ‚
    ‚;
    endforeach;
    echo ”;
    ?>

    • Tak oczywiście – trzeba pozmieniać wszędzie pojedyncze apostrofy – niestety tutaj w komentarzach WP inteligentnie je podmieniał :)

      Co do samego skryptu to na koniec dodałem jeszcze do tablicy $writers dodatkowo id autora usuwając user_login (aby zrobić tak jak pisał Konrad w #4) i zapomniałem odwrócić kolejność.
      Prawidłowo ta linijka powinna wyglądać następująco:
      $writers[] = array (‚nazwa’ => $auth, ‚id’ => $author);

      (Poprawiłem już w skrypcie powyżej i usunąłem również zbędne rel=nofollow, które te dodał WP przy publikacji komentarza).

      Czy teraz juz działa jak trzeba?

  • Tak,
    DZIĘKUJĘ! Działa jak powinno. Tutaj przykład tego skryptu – pod ostatnimi wpisami, lista autorów, którzy publikowali w danej kategorii: http://tyskastronapoezji.pl/nasza-poezja/.

    Dziękuję za pomoc! Pozdrawiam

Uwaga, leci reklama:



Gdzie nas czytać?

Autorzy »
Komentujący »
#wpzlecenia »