Wpisy, własne pola i alchemia

Pierwotnie miał być to bardzo długi wpis o tym, jak możemy odpicować własne pola (custom fields) przy wpisach w WordPressie, jednak gdy doszedłem do 4. strony A4 zauważyłem, że ani ja nie chcę tak dużo pisać, ani nikt inny chyba nie będzie chciał tak dużo czytać. Na pewno nie w internecie. Dlatego potraktujemy ten wpis jako:

wstęp do własnych pól, metadanych i metaboksów

Na początek kilka wyjaśnień czy są powyżej wymienione zagadnienia. Na pewno każdy coś o nich kiedyś słyszał, ale nie zawsze stosował.

Metadane to różne, nieokreślone informacje towarzyszące wpisowi (czy stronie, czy własnym typom treści, ale będę dla uproszczenia odnosił się tylko do wpisów). Wpis jak wiecie ma tytuł, treść, czasem wypis i kilka innych danych. W WordPressie do wpisu można jednak dodać kolejne elementy i są one właśnie trzymane w metadanych. Metadane składają się z predefiniowanej nazwy tej metadanej i zawartości, którą najczęściej wprowadza autor wpisu. Metadane najczęściej wprowadzane są w kokpicie na ekranie edycji wpisu, a potem wyświetlane we frontendzie dla odwiedzających stronę.

Własne pola (custom fields) to specjalny formularz w WordPressie służący wprowadzaniu metadanych.

Metaboksy są dla tych, którym własne pola nie wystarczą. Jeśli ktoś chciałby stworzyć własny formularz wprowadzania metadanych, wyglądający inaczej niż standardowe własne pola, prędzej czy później trafia na wyrażenie custom metabox.

Jeszcze raz to samo ale na przykładach.

Myślę, że wszyscy znacie WPzlecenia.pl (w końcu jesteście w podserwisie tej strony). Zapraszam Was dzisiaj na chwilę na zaplecze. Jeśli ktoś z Was próbował dodać kiedyś tam zlecenie, na pewno zauważył, że należy wypełnić tam 4 pola: tytuł zlecenia, treść, budżet i dane kontaktowe.

Każdy się na pewno domyśla, że tytuł zlecenia zapisywany jest w WordPressie jako po prostu tytuł wpisu. Treść zlecenia, to treść owego wpisu. Dwa ostatnie pola są jednak niestandardowe dla WordPressa i zdecydowałem, że będą one zapisywane właśnie jako metadane danego wpisu.

To są właśnie metadane: zawierają jakąś nazwę – nazwą metadanej budżetu jest budzetOgloszenia a jego wartością liczba przesłana przez formularz.

Czy mogę te dane jakoś edytować? Tak. WordPress automatycznie dla każdej metadanej (której nazwa nie zaczyna się od znaku podkreślenia) tworzy własne pola. Tak to wygląda u mnie w Kokpicie:

Jak widać, nawet jeśli komuś uda się przesłać jakimś cudem tu nieprawidłowe dane, zawsze przed publikacją ogłoszenia mogę je ręcznie poprawić.

Czy rozumiecie już zależność między metadanymi a własnymi polami?  Myślę, że tak.

Co z metaboksami? Jak wspomniałem, jeśli się nie zgadzam aby metadane były wprowadzane jak powyżej, mogę stworzyć własny formularz i taki formularz nazywa się właśnie metaboks.

Co prawda na WPzlecenia nie tworzyłem sam żadnych metaboksów, ale mam wtyczkę, która je wykorzystuje. Jest to WordPress SEO, która przy każdym wpisie dodaje taki oto mały (a może nie mały) formularz:

I to jest właśnie metaboks. Przez niego, podobnie jak i przez własne pola wprowadzamy do WordPressa matadane, tyle, że nie musimy już im nadawać nazwy: zostały one zakodowane we wtyczce na stałe i nie są wyświetlane nigdzie. Wprowadzamy tylko wartość metadanej.

Zalety i wady metaboksów

Metaboksy mają jedną wielką zaletę: są o wiele przyjaźniejsze dla użytkownika, niż własne pola. Wyobraźcie sobie dwóch developerów, którzy oddają klientowi z branży nieruchomości serwis i mówią:

Deweloper 1: I oto gotowa strona. Tutaj musi pan wpisać nazwę nieruchomości, poniżej dodać jakiś jej opis. Następnie proszę w opcjach ekranu włączyć wyświetlanie własnych pól i gdy te się pojawią, wpisać w nie pary wartości. Aby podać adres obiektu, proszę wpisać nazwę własnego pola 'adresOb’ i w pole wartości wpisać ten adres. Aby wprowadzić metraż wpisujemy własne pole o nazwie 'mkw’ i dodajemy odpowiednią wartość.

Deweloper 2: Ja też już przygotowałem stronę. Na górze wpisuje pan nazwę obiektu, pod spodem opis, niżej w te pole adres, a jeszcze niżej metraż. Wszystkie pola są podpisane, więc na pewno się pan nie pogubi.

Zgadnijcie, który z deweloperów zostanie odesłany przez klienta do wykonania poprawek? ;)

Metaboksy mają jednak pewną wadę: dość topornie wygląda API dodawania takiego metaboksu. Nie sposób nauczyć się go na pamięć, a zrozumienie też zabiera sporo czasu. Z tego też powodu po przeczytaniu dokumentacji powiedziałem: ja się poddaję. I zacząłem się rozglądać, czy da się to zrobić prościej.

Magia wokół metaboksów

Dziękuję ci internecie, i tym razem mnie nie zawiodłeś. Okazało się bowiem dość szybko, że był już ktoś, kto podobnie jak ja miał alergię na to API i obudował je w bardzo ładną, wygodną i intuicyjną klasę. Klasa ta nazywa się WPAlchemy MetaBox, dostępna jest do pobrania na licencji GPL i naprawdę przyspiesza tworzenie metaboksów oraz ich obsługę.

Jak proste to jest? Zobaczcie na przykładzie. Specjalnie na potrzeby tego wpisu stworzyłem mały plugin, który dodaje przy każdym wpisie w Kokpicie pole na korespondencję pomiędzy autorami dev.WPzlecenia. Wygląda ono tak:

Metaboks ten pozwala na wprowadzanie i wyświetlanie komentarzy edytorskich do dzielenia się uwagami o wpisie. Właściciel serwisu czyta wpis autora i jeśli uważa, że autor przed publikacją powinien coś jeszcze zmienić, dodaje w nim swój komentarz. Autor zmienia (lub nie) i dopisuje swoje uwagi. I tak dalej. Plugin jest prosty, a jego kod jeszcze prostszy.

Główny plik wtyczki – komentarze-w-kokpicie.php

Zacząłem od utworzenia katalogu wtyczki o nazwie komentarze-w-kokpicie w którym umieściłem pierwszy plik o tej samej nazwie (tyle, że z rozszerzeniem .php). Kod pliku wygląda tak:

<?php
/* 
Plugin Name: Komentarze w kokpicie
*/

include_once 'wpalchemy/MetaBox.php';

if (is_admin()) { 
wp_enqueue_style('custom_meta_css', 
      WP_PLUGIN_URL . '/komentarze-w-kokpicie/metaboxes/meta.css');
wp_enqueue_style('custom_meta_css_komentarze', 
      WP_PLUGIN_URL . '/komentarze-w-kokpicie/metaboxes/komentarze.css');  
}

add_action('init', 'metaboks');
function metaboks() {
$komentarze_metabox = new WPAlchemy_MetaBox(array
(
	'id' => '_kom_meta',
	'title' => 'Komentarze edytorskie',
	'template' => 
            WP_PLUGIN_DIR . '/komentarze-w-kokpicie/metaboxes/komentarze.php',
	'context' => 'side'
));
return;
}

Obejrzyjmy ten plik po kolei. Najpierw załączamy plik wpalchemy/MetaBox.php, który zawiera klasę obsługującą metaboksy. Plik ten pobraliśmy wraz z paczką innych plików ze strony autora klasy i jak widać umieszczony jest w podkatalogu wpalchemy w katalogu naszej wtyczki.

Następnie (linijki 8-13) wczytujemy dwa pliki stylów odpowiedzialne za wygląd metaboksu. Plik meta.css jest dostarczany przez autora klasy i odpowiada za ogólne stylowanie metaboksu. Plik komentarze.css napiszemy sami.

Dalsza część kodu to zainicjowanie obiektu klasy WPAlchemy_MetaBox. Podczas takiej inicjacji musimy podać tablicę z kilkoma wartościami. „id” określa jak będzie nazywała się metadana, „title” odpowiada za wyświetlanie tytułu metaboksu (spójrzcie na zrzut ekranu nieco wyżej), „context” za umiejscowienie metaboksu (czy ma być to w głównej kolumnie pod oknem edycji wpisu, czy w kolumnie bocznej). W polu „template” przekazujemy plik, który będzie odpowiedzialny za wyświetlanie zawartości metaboksu (czyli najczęściej będzie tam kod odpowiednich elementów formularza).

Zawartość metaboksu – plik metaboxes/komentarze.php

Nie wylistuję tu całego pliku na raz. Podzielmy go na części:

<div class="my_meta_control">
<?php 
$metabox->the_field('komentarz'); 
global $current_user;
$odlicz = time();?>

Otworzyłem div należący do klasy my_meta_control (musi być to klasa o właśnie takiej nazwie, bowiem tak ją autor dodatku zdefiniował w swoim pliku meta.css).

W kolejnej linijce inicjuję pole formularza, a będzie się ono nazywało „komentarz”. Dzięki temu w dalszej części kodu klasa WPAlchemy_MetaBox będzie wiedziała co wyświetlić, jak nazwać zmienne formularza itp. To za chwilę. Na razie należy pamiętać, że taki kod powinien pojawić się zawsze w początkowej części pliku wyglądu wnętrza metaboksa.

Na liście z komentarzami będę wyświetlał avatar komentatora i treść komentarza. Do avatara potrzebna jest mi informacja o osobie, która za chwilę doda komentarz, w tym celu zglobalizowałem wordpressową zmienną $current_user.

Komentatora i komentarz będę parował wewnątrz małej dwuelementowej tablicy. Ta tablica z kolej będzie elementem długiej tablicy z wszystkimi komentarzami indeksowanej znacznikami czasu. Z tego też powodu stworzyłem zmienną, która ten znacznik czasu pobierze (zostanie użyty później).

Powyższy akapit na pewno sporo namieszał, więc spójrzmy na pseudokod, który przedstawia strukturę jak zapisywane będą wszystkie komentarze w metadanej:

array komentarze =
 array timestamp = 
  var autor = ...
  var tresc = ...
 array timestamp = 
  var autor = ...
  var tresc = ...
 array timestamp = 
  var autor = ...
  var tresc = ...
...

Teraz pominę fragment odpowiedzialny za wyświetlanie już dodanych komentarzy. Przejdźmy do tego jak będzie wyglądał kod formularza dodawania komentarza, czyli koniec naszego pliku komentarze.php:

<!-- dodawanie nowego komentarza -->
<label>Komentarz</label>
<input type="hidden" 
       name="<?php $metabox->the_name(); ?>[id<?php echo $odlicz ?>][autor]" 
       value="<?php echo $current_user->ID ?>">
<textarea 
       name="<?php $metabox->the_name(); ?>[id<?php echo $odlicz ?>][tresc]" 
       rows="3">
</textarea>

</div> <!-- .my_meta_control koniec -->

Jak widać mamy tu dwa pola formularza. Pierwsze jest ukryte i w wartości ma wpisany identyfikator autora komentarza. Drugie to textarea, w które autor wprowadzi komentarz. Warto zwrócić uwagę jak konstruowane są nazwy tych pól. W pierwszej kolejności wywołujemy $metabox->the_name(). Metoda ta wpisuje nazwę metadanej. Potem pojawia się nasz $odlicz przechowujący timestamp i na końcu jest ostatni element tablicy: albo autor, albo tresc.

Tak, jeśli przyszło Wam teraz do głowy pytanie „To metadana może być tablicą?” odpowiedź brzmi właśnie – tak.

I teraz jak ktoś wciśnie przycisk publikacji wpisu lub jego aktualizacji, dane wpisane w formularz komentarzy edytorskich zostaną przesłane do WordPressa, a ten zapisuje je jako odpowiednie metadane.

Jak wygląda kod odpowiedzialny za wyświetlanie już dodanych komentarzy na żółtym tle? Ciesze się, że pytacie:

<!-- komentarze już przesłane -->
<?php
 $wpisane = $metabox->get_the_value();
 foreach ($wpisane as $key => $wpis) {
 if ($wpis['tresc'] == '') continue;
?>

<div class="wpis">
<div class="autor">
<input type="hidden" 
       name="<?php $metabox->the_name(); ?>[<?php echo $key; ?>][autor]" 
       value="<?php echo $wpis['autor'] ?>">
<?php echo get_avatar($wpis['autor'], 16); ?>
</div>
<div class="tresc">
<input type="hidden" 
       name="<?php $metabox->the_name(); ?>[<?php echo $key; ?>][tresc]" 
       value="<?php echo $wpis['tresc'] ?>">
<?php echo $wpis['tresc']; ?>
</div>
</div>
<?php
 }
?>

Najpierw do zmiennej $wpisane pobieramy wszystkie komentarze, jakie już są zapisane w metadanej (będzie to oczywiście tablica taka, jak pokazana powyżej w pseudokodzie).

Następnie tworzymy pętlę, która wyświetli całą zawartość tej tablicy. Na podstawie id autora wyświetli jego avatar (linijka 13.), potem wyświetli treść jego komentarza.

Należy też pamiętać aby wraz z wyświetlaniem komentarzy w sposób wizualny, umieścić ich zawartość w ukrytych polach formularza (linijki 10. i 16.). Inaczej przy kolejnym zapisaniu wpisu zostanie to utracone i nadpisane jedynie przez nową zawartość wprowadzoną w pole textarea.

Spójrzcie też na linijkę 5. Jeśli by jej nie było, po każdej aktualizacji wpisu do listy dodawałyby się puste komentarze zawierające tylko avatar autora – informacje o autorze przesyłane są bowiem zawsze przy aktualizacji, nawet jeśli autor nie wpisał żadnego nowego komentarza.

I to już wszystko. Pozostało nam jedynie odpicowanie wyglądu naszej mini komunikatora przez dodanie pliku:

Plik metaboxes/komentarze.css

A jego zawartość wygląda tak:

.wpis {
 border: 1px #E6DB55 solid;
 background-color: #FFFFE0;
 margin-bottom: 5px;
 padding: 3px;
 overflow: auto;
}
.wpis .autor {
 float: left;
 margin: 0 3px 3px 0;
}
.wpis .tresc {
 margin-left: 20px;
}

I tyle. Teraz wystarczy wtyczkę aktywować i używać.

Podsumowanie

Już po napisaniu tego wszystkiego przyszło mi do głowy, że może nie jest to super intuicyjne, ale uwierzcie mi – na pewno jest to wygodniejsze niż ręczne tworzenie metaboksów wg wordpressowego API. W przyszłości wiele razy będę jeszcze odwoływał się do tej klasy w kolejnych poradników i na pewno wszystko stanie się klarowniejsze. Uwielbiam ją bowiem i na jej bazie stworzyłem już niezliczone ilości metaboksów.

Jeśli ktoś już teraz potrzebuje więcej infomacji na jej temat – odsyłam na stronę autora.

Jeśli ktoś jednak nie chce pisać wtyczki od początku samemu, a chce jej użyć, może ją pobrać tutaj.

Jakub zgłosił mi kilka uwag odnośnie usability tej wtyczki. Ma rację, jednak nie chciałem jeszcze bardziej komplikować jej kodu i postarałem się skupić tylko na samej kwintesencji metaboksów.

…i jak zwykle czekam na Wasze komentarze. Czy znaliście już tę klasę? A może macie swoje, lepsze metody na zapanowanie nad metaboksami?


Opublikowano

w

przez

Komentarze

13 odpowiedzi na „Wpisy, własne pola i alchemia”

  1. Awatar Łukasz Więcek - myDIY.pl

    Na własne potrzeby zawsze wykorzystywałem tylko custom fields. Dzisiaj w nocy oficjalnie wpuściłem na myDIY nowych redaktorów, więc chyba ułatwię im życie i przygotuję metaboks do definiowania miniatur dla FB i G+ :)

  2. Awatar Konrad Karpieszuk

    ooo, podziel sie :) tak w ogole jak sie definiuje miniature dla G+? mam tu na dev meta image_src ktore łyka facebook, ale google+ w ogole go nie widzi

    1. Awatar Łukasz Więcek - myDIY.pl

      Na swoich wszystkich blogach stosuję taki zestaw: http://screen.więcek.pl/2011-11-03_194508.png

      Pierwsze dwa linki dla FB (nie pamiętam już, dlaczego aż dwa, ale miałem w tym jakiś cel;), a ten trzeci dla G+ :)

      1. Awatar Konrad Karpieszuk

        czy obrazek dla g+ musi spelniac jakies warunki? bo dla FB wiem ze musi miec okreslone proporcje

        1. Awatar Łukasz Więcek - myDIY.pl

          Jeszcze tego nie rozgryzłem ;) A FB jakiś czas temu chyba olało te swoje proporcje i teraz przyjmuje kwadraty 90px.

      2. Awatar Łukasz Więcek - myDIY.pl

        Chm… przed chwilą sprawdziłem i chyba Google przestało brać pod uwagę tą deklarację obrazka :/ Niedobrze, niedobrze…

        1. Awatar Konrad Karpieszuk

          no ja sobie to tez dodalem kilka dni temu i nie dziala

          1. Awatar Łukasz Więcek - myDIY.pl

            W ogóle nie można znaleźć żadnej informacji, czy teraz Google wspiera coś takiego…

  3. Awatar Marcin

    Jeszcze nie skończyłem czytać więc nie skomentuję wpisu ;)

    Jest szansa, że pojawi się tutorial dotyczący ustawień SEO w WP?

    1. Awatar Konrad Karpieszuk

      nigdy nie mow nigdy :) ja nie jestem specem od seo, ale moze znajdzie sie ktos chetny by to opisac :)

  4. Awatar Artur
    Artur

    Mam pytanie odnośnie wstawiania metadanych do wpisu lub na stronę.
    Chcę zrobić na stronie formularz gdzie użytkownik będzie mógł polecić swoim znajomym np, newsletter. Chcę, żeby user miał dostęp to tej strony po zalogowaniu, ale to załatwi plugin. MOje pytanie dotyczy tego jak uzupełnić formularz o dane zalogowanego użytkownika; imię i nazwisko, e-mail i firma.
    Będę wdzięczny za sugestie i podpowiedź.

    1. Awatar Konrad Karpieszuk

      to nie jest pytanie o metadane ale o http://codex.wordpress.org/Function_Reference/get_currentuserinfo. taak pobierzesz dane zalogowanego

  5. Awatar Artur
    Artur

    Mam pytanie odnośnie wstawiania metadanych do wpisu lub na stronę.
    Chcę zrobić na stronie formularz gdzie użytkownik będzie mógł polecić swoim znajomym np, newsletter. Chcę, żeby user miał dostęp to tej strony po zalogowaniu, ale to załatwi plugin. MOje pytanie dotyczy tego jak uzupełnić formularz o dane zalogowanego użytkownika; imię i nazwisko, e-mail i firma.
    Będę wdzięczny za sugestie i podpowiedź.