Dawno, dawno temu napisałem poradnik jak korzystać z settings API, jednak po ostatnich doniesieniach, jest on już nie do końca zgodny ze standardami. Dlatego postanowiłem napisać co nieco o Customize API.
W moim podejściu do tego tematu zastosuję metodę obiektową, która jest dużo bardziej czytelna i daje o wiele większe możliwości.
No to zaczynamy na początku tworzymy nowy plik, który będzie odpowiedzialny za nasze opcje
class ThemeOptionsAPI { protected static $instance; private $classes = array(); public static function init() { if(is_null(self::$instance) AND self::$instance = new self) { return self::$instance; } } }
i dołączamy go to pliku functions.php motywu
require_once('sciezka_do_pliku/theme-options-api.php'); ThemeOptionsAPI::init();
Teraz należy dodać klasę, która będzie przechowywała wszystkie opcje
class ThemeOptions { private $options = array(); public function __construct() { $this->options = array(); } public function getOptions() { return $this->options; } public function addOption(array $opt) { $this->options[] = $opt; }
}
Teraz do klasy ThemeOptionsAPI, należy dodać konstruktor
private function __construct() { $this->classes = array( 'ThemeOptions' => get_template_directory().'sciezka_do_pliku/theme-options.php', ); $this->theme_options_include_classes(); }
oraz metodę autloadera.
private function theme_options_include_classes() { if (function_exists("spl_autoload_register")) { if (function_exists("__autoload")) { spl_autoload_register("__autoload"); } spl_autoload_register(array($this,'autoload')); } else { foreach ($this->classes() as $id => $path) { if (is_readable($path) && !class_exists($id)) { require_once($path); } } } } private function autoload($class) { if (isset($this->classes[$class]) && is_readable($this->classes[$class])) { require_once($this->classes[$class]); } }
Etap początkowy można uznać za zakończony, teraz w konstruktorze klasy ThemeOptions, dodamy przykładowe pola.
$this->options = array( 'section_id' => array(//ID sekcji 'title' => 'Tytuł sekcji', //Tytuł sekcji 'priority' => 35, //Priorytet 'capability' => 'edit_theme_options',//Poziom uprawnień 'description' => 'Opis sekcji', //Opis sekcji 'fields' => array( //Tablica z polami 'field_id' => array(//ID pola 'label' => 'Field Label',//Etykieta 'description' => 'Field Desc',//Opis pola 'type' => 'image',//Typ pola 'default' => '',//Wartość domyślna 'options' => array()//Tablica wartości ) ) ));
Opis pól:
- ID sekcji: WordPress udostępnia domyślne sekcje:(title_tagline,colors,header_image,background_image,nav,static_front_page) ustawienie, któreś z wymienionych jako ID sekcji spowoduje wyświetlenie pól w któreś z nich, gdy ID sekcji będzie własne zostanie utworzona nowa sekcja
- Priorytet: definiuje w jakim miejscu wyświetli się nowa sekcja, wyłącznie w przypadku tworzenie nowej sekcji
- Poziom uprawnień: definiuje jakie uprawnienia powinien posiadać użytkownik aby móc edytować wartości w tej sekcji
- Tablica z polami: zawiera tablicę pól jakie zostaną wyświetlone w danej sekcji
- ID pola: wartość wstawiana jako id oraz name pola
- type: Typ pola możliwe opcje takie same jak w przypadku znaczników HTML, dodatkowo Worpdress udostępnia własne typy(color,image,media)
- Wartość domyślna: w przypadku gdy pole nie powinno być puste można ustawić wartość domyślna
- Tablica wartości: w przypadku pól typu select, checkbox, radio tablica zawierająca dostępne wartości w postaci 'wartosc’ => 'etykieta’
Teraz należy wyświetlić uprzednio dodane opcje oraz pogrupować jej w sekcje,w tym celu w konstruktorze klasy ThemeOptionsAPI, należy dodać następującą linijkę:
add_action('customize_register',array($this,'theme_options_api_customize_register'));
oraz metodę theme_options_api_customize_register
public function theme_options_api_customize_register($wp_customize) { $this->customize = $wp_customize; $class = new ThemeOptions(); $options = $class->getOptions(); if(!empty($options)) { foreach ($options as $section_id => $section_opt) { $this->sectionID = $section_id; $this->addSection($section_id, $section_opt); $this->addFeilds($section_id, $section_opt['fields']); $this->options[$section_id] = array_keys($section_opt['fields']); } } }
Powyższa metoda w pętli dodaje pobrane z tablicy pola oraz sekcje korzystając z odpowiednich metod, które zostaną opisane za chwilę.
Wcześniej należy dodać jeszcze trzy prywatne pola do klasy ThemeOptionsAPI
private $customize = null; private $options = array(); private $sectionID = null;
Kolejnym krokiem jest dodanie wypomnianych metod dodających pola oraz sekcje.
private function addSection($section_id,array $section_opt) { $default_sections = array('title_tagline','colors','header_image','background_image','nav','static_front_page'); if(!in_array($section_id, $default_sections)) { if(isset($section_opt['fields'])) { unset($section_opt['fields']); } $this->customize->add_section($section_id, $section_opt); } } private function addFeilds($section_id,array $fields) { if(!empty($fields)) { foreach($fields as $id => $field) { $this->addField($id, $field); } } }
Powyższe metody nie mają skomplikowanej struktury dlatego też nie zostaną dokładnie opisane, a wszystkie wątpliwości rozwieją przeprowadzane przez siebie testy.
Jednym z ostatnich kroków jest zapis utworzonych przez nas opcji do bazy, w tym celu należy utworzyć metodę storeInDB
private function storeInDB($id, array $field) { $default = isset($field['default']) ? $field['default'] : ''; $capability = isset($field['capability']) ? $field['capability'] : 'edit_theme_options'; $this->customize->add_setting($id, //No need to use a SERIALIZED name, as `theme_mod` settings already live under one db record array( 'default' => $default, //Wartość domyślna 'type' => 'theme_mod', //dostępne wartości theme_mod, option 'capability' => $capability, //Poziom uprawnień 'transport' => 'postMessage', //Sposób w jaki zapisywać ustawienia refresh,postMessage ) ); }
W tej metodzie tak samo jak w poprzedniej najlepszym wytłumaczeniem będą testy, param transport określa w jaki sposób powinny być zapisywane ustawienia, ustawienie go na postMessage umożliwi podgląd zmian „na żywo”
No i w końcu przyszedł czas na najważniejszą metodę w całej klasie czyli wyświetlenie pól umożliwiających edycję szablonu.
private function addField($id, array $field) { $this->storeInDB($id, $field); $default_type = array( 'color' => 'WP_Customize_Color_Control', 'image' => 'WP_Customize_Image_Control', 'media' => 'WP_Customize_Upload_Control', ); $priority = isset($field['priority']) && is_numeric($field['priority']) ? $field['priority'] : ''; $options = isset($field['options']) && is_array($field['options']) ? $field['options'] : array(); if(key_exists($field['type'], $default_type)) { $class = new $default_type[$field['type']]( $this->customize,$id, array( 'label' => $field['label'], 'section' => $this->sectionID, 'priority' => $priority, ) ); $this->customize->add_control($class); } else { $class = array( 'label' => $field['label'], 'section' => $this->sectionID, 'type' => $field['type'], 'choices' => $options, ); $this->customize->add_control($id,$class); } }
I to wszystko opcje powinny się wyświetlać w sekcjach jakie zostały zdefiniowane. Dodatkowo do podglądu zmiany w ustawieniach „na żywo”, należy dołączyć plik JavaScript z następującą zawartością:
(function($) { wp.customize('YOUR_SETTING_ID', function(value) { value.bind( function(newval) { //Do stuff (newval variable contains your "new" setting data) }); }); })(jQuery);
W celu dołączenia pliku w konstruktorze klasy ThemeOptionsAPI należy dodać następującą linijkę:
add_action(’customize_controls_enqueue_scripts’,array($this,’theme_options_api_customizer_live_preview’));
oraz metodę, która zarejestruje skrypt oraz doda do niego w postaci tablicy wszystkie zarejestrowane pola wraz z przypisanymi do nich sekcjami, co pozwoli na łatwy dostęp do konkretnych wartości
public function theme_options_api_customizer_live_preview() { wp_register_script('theme_options_api_script',get_template_directory.'sciezka_do_pliku/theme-customize.js'); wp_localize_script('theme_options_api_script','thme_options_fields',$this->options); wp_enqueue_script('theme_options_api_script'); }
Teraz to już na prawdę wszystko, starałem się tłumaczyć w taki sposób aby wszystko było jasne; ale też bez przepisywania codexa. Wydaj mi się, że napisany w ten sposób kod pozwoli ograniczyć jego ilość do minimum pozostając czytelnym.
W razie wątpliwości, pytań, sugestii wszystkie komentarze są mile widziane
Komentarze
2 odpowiedzi na „Korzystanie z Customize API”
Dzięki za ten poradnik!
Bardzo ciekawy poradnik!