✅ Nowości, motywy, wtyczki WEB i WordPress. Tutaj dzielimy się wskazówkami i najlepszymi rozwiązaniami dla stron internetowych.

Tworzenie niestandardowej kontroli selektora łączy CMB2 dla WordPress

33

W tym samouczku przyjrzę się, jak utworzyć niestandardową kontrolkę, aby rozszerzyć funkcjonalność CMB2 (Custom Meta Boxes 2) przez WebDevStudios.

Tworzę strony internetowe (i aplikacje internetowe) za pomocą CMS WordPress (system zarządzania treścią), a kiedy trafi nowy projekt, możesz zagwarantować, że będzie wymagał ode mnie opracowania „Niestandardowych skrzynek meta", aby umożliwić użytkownikowi pełną kontrolę nad zawartością i układem witryn.

Opiszę szczegółowo, w jaki sposób zbudowałem kontrolkę CMB2 Link Picker dla CMB2 (dostępną we wszystkich dobrych repozytoriach wtyczek WordPress). Zrzut ekranu można zobaczyć poniżej.

Sterowanie CMB2 „Link Picker” w akcji

Selektor linków uruchamia wbudowane okno dialogowe „Wstaw/edytuj link” WordPress po kliknięciu przycisku „Wybierz”. Widać to na poniższym zrzucie ekranu:

Tworzenie niestandardowej kontroli selektora łączy CMB2 dla WordPressNaciśnięcie przycisku pozwala wybrać link (lub dodać własny)

Jestem pewien, że zgodzisz się, że taka kontrola jest niezwykle przydatna, jeśli chcesz dać redaktorom swojej witryny możliwość dodawania linków, a także przeszukiwania WordPress pod kątem wewnętrznych linków, zamiast wycinania i wklejania linków do linku pole.

Wstęp / Historia

Dla tych, którzy nie wiedzą, metabox znajduje się na ekranie edytora posta WordPress i prawdopodobnie będzie zawierał różne kontrolki formularzy (pola tekstowe, listy rozwijane, pola wyboru itp.). Te kontrolki umożliwiają użytkownikom Twojej witryny łatwą zmianę niestandardowego fragmentu tekstu lub funkcji w witrynie.

Tworzenie niestandardowej kontroli selektora łączy CMB2 dla WordPressTworzenie niestandardowej kontroli selektora łączy CMB2 dla WordPressPrzykład meta pola z różnymi kontrolkami formularza

WordPress pozwala tworzyć metaboxy za pomocą funkcji (takich jak [add_meta_box](https://developer.wordpress.org/reference/functions/add_meta_box/)), ale tworzenie metaboxów w ten sposób może być długotrwałym procesem z dużą ilością powtórzeń kodu (zwłaszcza jeśli chcesz używać tych samych kontrolek formularza w wielu projektach).

Dlaczego CMB2?

Niektórzy z was mogli słyszeć o zaawansowanych polach niestandardowych (ACF), które zapewniają GUI (graficzny interfejs użytkownika), który pozwala tworzyć meta pola bezpośrednio za pomocą WordPressa.

ACF moim zdaniem nie jest świetnym narzędziem do skalowania jakiegokolwiek rozwiązania webowego. Wtyczka zbytnio polega na danych przechowywanych w bazie danych. Powoduje to ból podczas wdrażania zmian w witrynie, ponieważ nie można po prostu przesłać kodu i natychmiast zobaczyć zmiany. Zamiast tego musisz ponownie wykonać pracę w różnych środowiskach wdrożeniowych (staging, live itp.). Potrzebowaliśmy więc rozwiązania, które pozwoli nam programowo tworzyć metaboxy. Wpisz CMB2.

Zanim przyjęliśmy CMB2, wcześniej używaliśmy HM Custom Meta Boxes od tych uroczych ludzi z Human Made (która zaczęła się jako rozwidlenie poprzednika WebDevStudio do CMB2, „Custom Meta Boxes”).

Uwielbialiśmy HM Custom Meta Boxes, a dzięki najprostszym fragmentom kodu mogliśmy szybko stworzyć niestandardowe Meta Boxy, aby zrobić prawie wszystko!

Tworzenie niestandardowej kontroli selektora łączy CMB2 dla WordPressPrzykład HM Custom Meta Boxes Markup (to jest oznaczenie dla Instagram Meta Box na pierwszym zrzucie ekranu)

Dlaczego więc przejście na CMB2? Cóż, HM Custom Meta Boxes niestety nie cieszył się zbytnią sympatią (rozmawiałem z jego głównym deweloperem i jest on bardzo zajętym człowiekiem), podczas gdy CMB2 posuwał się naprzód z nowymi funkcjami, nowymi kontrolkami i zyskał na popularności w społeczności WordPress z wieloma osobami, które ją adoptują i wydają wtyczki, aby ją rozszerzyć (w tym kilka naszych agencji partnerskich).

Wreszcie, jak można się domyślić, praca z CMB2 jest tak niewiarygodnie prosta, jak do tego przywykliśmy, ponieważ obie platformy mają wspólnego przodka.

Instruktaż

Zanim zaczniemy, każdy ma swój własny zestaw ideałów dotyczących tworzenia wtyczki WordPress, a ja wypróbowałem sporo, jednak samouczek na temat „ Kompozycja korzenia w WordPressie ” autorstwa Toma J Nowella całkowicie zmienił sposób, w jaki pracuję. Uważam, że jego podejście jest czyste, proste i sprawia, że ​​​​przyszła konserwacja dowolnej wtyczki jest łatwa. Jeśli pobierzesz źródło wtyczki Link Picker for CMB2, możesz zobaczyć metody, których naucza w praktyce.

Budowanie formy

Aby zbudować formularz, który renderuje selektor linków, pierwszą rzeczą, którą musimy zrobić, jest zaczepienie się o cmb2_render_[control_name]akcję. Jak nazwałem tę kontrolkę „link_picker”, możemy uzupełnić podpięcie w następujący sposób:

<?php
add_action( 'cmb2_render_link_picker', array( $this, 'cmb2_render_link_picker' ), 10, 5 );
`

Dla tych z Was, którzy tak naprawdę nie rozumieją add_actionhaka, działa to w następujący sposób:

  1. Pierwszym argumentem cmb2_render_link_pickerjest nazwa haka, do którego chcemy się podłączyć.
  2. Drugim argumentem array( $this, 'cmb2_render_link_picker' )jest funkcja, którą chcemy wywołać po uruchomieniu tego podpięcia. Zauważ, że zawijam to w tablicę, z $thispierwszym parametrem, ponieważ wywołuję funkcję wewnątrz klasy. Jeśli nie pracujesz z klasami, możesz po prostu użyć nazwy funkcji cmb2_render_link_picker.
    3., 10to kolejność, w jakiej chcemy uruchomić funkcję (im niższa liczba, tym szybciej uruchamia się po wywołaniu akcji).
  3. Jest 5to ilość parametrów, które zostaną przekazane do wywoływanej funkcji (wkrótce stanie się to jasne).

Następnie tworzymy funkcję, która wyrenderuje formularz:

<?php

public function cmb2_render_link_picker( $field, $value, $object_id, $object_type, $field_type_object) {
…
}
`

Zostawiłem „DocBlock” w powyższym kodzie, który opisuje, co robi każdy z parametrów przekazanych do cmb2_render_link_picker()funkcji.

Zauważ, że moja funkcja zaczyna się od publicdeklaracji. To znowu dlatego, że pracuję w klasie. Jeśli nie pracujesz z klasami, możesz to pominąć.

Wartość tego pola jest przekazywana do funkcji poprzez $valueparametr. W przypadku tego pola będziemy przechodzić przez tablicę, ponieważ nasza kontrolka ma do niej trzy oddzielne elementy:

  • Tekst
  • Adres URL
  • Jeśli link otwiera się w nowym oknie (lub nie)

Ponieważ $valuenie zawsze jest ustawiony (na przykład przy pierwszym renderowaniu kontrolki), musimy zainicjować go z pewnymi wartościami domyślnymi. Robimy to za pomocą następującego fragmentu kodu:

<?php
$value = wp_parse_args( 
    $value, 
    array(
        'text'  => '',
        'url'   => '',
        'blank' => 'false',) );

Możemy wtedy zabrać się do renderowania formularza. Oto przykład pierwszej kontrolki wprowadzania tekstu:

<p>
    <label for="<?php echo $field_type_object->_id( '_text' ); ?>'">
        <?php echo esc_html( $field_type_object->_text( 'link_picker_text', 'Text') ); ?>
    </label>
</p>
<?php 
    echo $field_type_object->input( 
            array(
            'class' => 'cmb_text',
            'name'  => $field_type_object->_name( '[text]' ),
            'id'    => $field_type_object->_id( '_text' ),
            'value' => $value['text'],) ); 
?>

Uff! To wygląda trochę niechlujnie, prawda? Rozłóżmy to, linia po linii:

  1. Znacznik otwierającego akapitu.
  2. Znacznik etykiety otwierającej dla kontrolki, ale z foratrybutem automatycznie ustawionym przez $field_type_object _idparametr. Spowoduje to automatyczne wygenerowanie identyfikatora kontrolki podczas jej renderowania.
  3. Tekst naszej etykiety, zbudowany przy użyciu tekstu z tablicy opcji kontroli (lub powraca do słowa „Tekst”).
  4. Znacznik etykiety zamykającej
  5. Znacznik zamykającego akapitu.
  6. Rozpocznij deklarację PHP
  7. Użyj kontrolki wejściowej (część, $field_type_objectaby utworzyć dane wejściowe formularza (domyślnym typem będzie tekst).
  8. Uruchom tablicę parametrów
  9. Ustaw klasę danych wejściowych.
  10. Ustaw nazwę wejścia, ponownie używając $field_type_objecthelpera.
  11. Ustaw identyfikator wejścia na ten sam identyfikator, który został ustawiony na etykiecie.
  12. Pobierz wartość z $value, ponieważ jest to tablica, potrzebujemy klucza 'text’ dla tej kontrolki.
  13. Zamknij tablicę.
  14. Zamknij funkcję wprowadzania.
  15. Zamknij deklarację PHP.

Znaczniki pola formularza adresu URL są bardzo podobne, tylko aby używać typów wejściowych HTML5, możemy ustawić dodatkowy parametr „type” na „url”:

<?php 
…
'type'  => 'url',
…

Na koniec chcemy zaimplementować listę rozwijaną. Znacznik jest bardzo znajomy:

<?php
echo $field_type_object->select( 
    array(
        'class'   => 'cmb_dropdown',
        'name'    => $field_type_object->_name( '[blank]' ),
        'id'      => $field_type_object->_id( '_blank' ),
        'options' => $blank_options,) );

Zauważ, że $field_type_objectfunkcja, której używamy, to selectgenerowanie listy rozwijanej. Zauważ też, że w linii 6 mamy nowy atrybut options. Do tego przekazujemy ciąg „opcji”. Jest to generowane przed tą kontrolką, tak jak:

<?php 
$blank_options = '';
$blank_options .= '<option value="false" '. selected( $value['blank'], 'false', false) .'>Opens in same</option>';
$blank_options .= '<option value="true" '. selected( $value['blank'], 'true', false) .'>Opens in new</option>';

Następnie wszystko, co musimy zrobić, to zawinąć go w kilka <div>i mamy w pełni renderowaną kontrolę:

<?php
public function cmb2_render_link_picker( $field, $value, $object_id, $object_type, $field_type_object) {
    $value = wp_parse_args( $value, array(
        'text'  => '',
        'url'   => '',
        'blank' => 'false',) );
    $blank_options = '';
    $blank_options .= '<option value="false" '. selected( $value['blank'], 'false', false) .'>Opens in same</option>';
    $blank_options .= '<option value="true" '. selected( $value['blank'], 'true', false) .'>Opens in new</option>';
    ?>
    <div class="link-picker">
        <div class="text">
            <p>
                <label for="<?php echo $field_type_object->_id( '_text' ); ?>'">
                    <?php echo esc_html( $field_type_object->_text( 'link_picker_text', 'Text') ); ?>
                </label>
            </p>
            <?php 
                echo $field_type_object->input( 
                    array(
                        'class' => 'cmb_text',
                        'name'  => $field_type_object->_name( '[text]' ),
                        'id'    => $field_type_object->_id( '_text' ),
                        'value' => $value['text'],
                        'desc'  => '',) ); 
            ?>
        </div>
        <div class="url">
            <p>
                <label for="<?php echo $field_type_object->_id( '_url' ); ?>'">
                    <?php echo esc_html( $field_type_object->_text( 'link_picker_url', 'URL') ); ?>
                </label>
            </p>
            <?php 
                echo $field_type_object->input( 
                    array(
                        'class' => 'cmb_text_url',
                        'name'  => $field_type_object->_name( '[url]' ),
                        'id'    => $field_type_object->_id( '_url' ),
                        'value' => $value['url'],
                        'type'  => 'url',
                        'desc'  => '',) ); 
            ?>
        </div>
        <div class="blank">
            <p>
                <label for="<?php echo $field_type_object->_id( '_blank' ); ?>'">
                    <?php echo esc_html( $field_type_object->_text( 'link_picker_blank', 'Window') ); ?>
                </label>
            </p>
            <?php 
                echo $field_type_object->select( 
                    array(
                        'class'   => 'cmb_checkbox',
                        'name'    => $field_type_object->_name( '[blank]' ),
                        'id'      => $field_type_object->_id( '_blank' ),
                        'options' => $blank_options,
                        'desc'    => '',) ); 
            ?>
        </div>
        <div class="choose">
            <p>
                <label>Choose</label>
            </p>
            <button class="dashicons dashicons-admin-links js-insert-link button button-primary" title="<?php esc_html_e( 'Insert Link', 'cmb' ); ?>">
                 <span class="screen-reader-text"><?php esc_html_e( 'Choose Link', 'cmb' ); ?></span>
             </button>
        </div>
    </div>
    <p class="clear">
        <?php echo $field_type_object->_desc();?>
    </p>
<?php
}

I to wszystko! Przejęliśmy kontrolę! CMB2 automatycznie obsługuje wszystkie dane, które chcemy zapisać, więc nic tam nie robimy.

Style

Zrzut ekranu kontrolki, którą tworzymy (w górnej części tego posta) ma kilka niestandardowych stylów zastosowanych do niego, więc renderuje się w tekście. Nie będę dzisiaj zagłębiał się w stylizację formularza, ale jeśli jesteś ciekawy, możesz pobrać wtyczkę i zobaczyć źródło.

Zapewnienie powtarzalności kontroli

Dla tych, którzy chcą być trochę bardziej zaawansowani, możesz sprawić, by sterowanie działało z powtarzalnymi regionami CMB2. Aby to zrobić, musisz zrobić trochę mapowania tablic. Aby to zrobić, użyj poniższego kodu:

<?php

public function cmb2_sanitize_link_picker( $check, $meta_value, $object_id, $field_args, $sanitize_object) {

    if (! is_array( $meta_value) ||! $field_args['repeatable']) {
        return $check;
    }
    foreach ($meta_value as $key => $val) {
        $meta_value[ $key ] =  null;
        if(! empty( $val['url'])) {
            $meta_value[ $key ] = array_map( 'sanitize_text_field', $val );
        }
    }
    return $meta_value;
}
public function cmb2_types_esc_link_picker( $check, $meta_value, $field_args, $field_object) {

    if (! is_array( $meta_value) ||! $field_args['repeatable']) {
        return $check;
    }
    foreach ($meta_value as $key => $val) {
        $meta_value[ $key ] =  null;
        if(! empty( $val['url'])) {
            $meta_value[ $key ] = array_map( 'esc_attr', $val );
        }
    }
    return $meta_value;
}

Wybór łącza

Oczywiście celem selektora linków jest integracja z własną funkcjonalnością wyboru linków WordPressa, dzięki czemu po kliknięciu przycisku „Wybierz” pojawi się okno dialogowe „Wstaw/edytuj link”.

Aby tak się stało, w dużym stopniu polegamy na JavaScript. W szczególności używam jQuery, aby coś się wydarzyło.

Zanim pokażę Ci JavaScript, który uruchamia to okno dialogowe, musimy najpierw umieścić w kolejce własny wewnętrzny JavaScript WordPressa, który wstępnie załaduje modalne i biblioteki, od których zależy nasz kod. To wygląda trochę mniej więcej tak:

<?php
global $post_id;

if (isset( $post_id)) {
    wp_enqueue_media( array( 'post' => $post_id) );
}

$plugin_js_url  = plugins_url( 'js/plugin.js', ROOT );
wp_enqueue_script( 'wholesomecode', $plugin_js_url, array( 'jquery', 'jquery-ui-core', 'jquery-ui-draggable', 'jquery-ui-droppable', 'thickbox', 'wpdialogs' ), '1.0.0', true );

Jak widać, wiele wewnętrznych bibliotek WordPressa korzysta z jQuery do ładowania wyskakujących okienek, więc sensowne jest, aby nasz wyzwalacz wyskakujących okien robił to samo. Odbywa się to za pomocą programu /js/plugin.js, który jest ładowany w wierszu 10 powyższego przykładu.

jQuery(document).ready(function($) {

    var url   = $('body');
    var text = $('body');
    var blank = $('body');

    $('body').on('click', '.js-insert-link', function(event) {

        event.preventDefault? event.preventDefault(): event.returnValue = false;
        event.stopPropagation();

        url            = $(this).closest('.link-picker').find('input.cmb_text_url ');
        text           = $(this).closest('.link-picker').find('input.cmb_text ');
        blank          = $(this).closest('.link-picker').find('input.cmb_checkbox ');

        wpActiveEditor = true;
        wpLink.open();
        wpLink.textarea = url;

        return false;
    });

    $('body').on('click', '#wp-link-cancel, #wp-link-backdrop, #wp-link-close', function(event) {

        wpLink.textarea = url;
        wpLink.close();
        event.preventDefault? event.preventDefault(): event.returnValue = false;
        event.stopPropagation();
        return false;
    });

    $('body').on('click', '#wp-link-submit', function(event) {
        console.log(text)
        var linkAtts = wpLink.getAttrs();

        linkAtts.text = $('#wp-link-text').val();

        url.val(linkAtts.href);

        if( linkAtts.text != '') {
            text.val(linkAtts.text);
        }

        if (linkAtts.target == '_blank') {
            blank.prop('checked', true);
        } else {
            blank.prop('checked', false);
        }

        wpLink.textarea = url;
        wpLink.close();
        event.preventDefault? event.preventDefault(): event.returnValue = false;
        event.stopPropagation();
        return false;
    });
});

Używając klas, które otoczyliśmy wokół naszych kontrolek formularza, JavaScript kieruje swoje kontrolki i wypycha wybrany wynik z wyskakującego okienka selektora linków do odpowiednich pól kontrolnych.

Korzystanie z Kontroli

Tak więc, po przejrzeniu powyższego samouczka i być może po przejrzeniu kodu źródłowego wtyczki Link Picker dla CMB2 lub po prostu pobraniu mojej wersji, możesz teraz zastanawiać się, jak używać tego z CMB2. Cóż, łatwiej być nie może:

<?php
function wholesomecode_create_meta_boxes() {
  $prefix = '_profile_';

    $cmb = new_cmb2_box(
        array(
            'id'            => 'cta',
            'title'         => __( 'Call to Action', 'cmb2' ),
            'object_types'  => array( 'profile' ),
            'context'       => 'normal',
            'priority'      => 'low',
            'show_names'    => true,) );

    $field1 = $cmb->add_field( 
        array(
            'name' => __( 'Link Picker', 'cmb2' ),
            'id'   => $prefix. 'cta_link',
            'type' => 'link_picker',) );
}
add_action( 'cmb2_admin_init', 'wholesomecode_create_meta_boxes' );

Źródło nagrywania: wholesomecode.ltd

Ta strona korzysta z plików cookie, aby poprawić Twoje wrażenia. Zakładamy, że nie masz nic przeciwko, ale możesz zrezygnować, jeśli chcesz. Akceptuję Więcej szczegółów