post_ico4

Tworzenie pluginu WordPress – krok po kroku

W ostatnim czasie postanowiłem zapoznać się z tworzeniem wtyczek pod WordPressa – stworzenie kilku pluginów przyspieszy i ułatwi codzienną pracę :). Zaskoczyło mnie lekko to, że w polskim internecie jest mało tutoriali na ten temat (znalazłem raptem dwa), a więc postanowiłem dodać coś od siebie…

Założenia pluginu

Stworzona przez nas wtyczka będzie umożliwiała:

  • skonfigurowanie slidera;
  • dodanie i edycję wyświetlanych obrazków;
  • wyświetlanie slidera;

Założenia już znamy, a co musi zawierać takki plugin?

  • opis pluginu;
  • funkcję instalującą;
  • funkcję usuwającą;
  • funkcję do zmiany konfiguracji;
  • funkcję do dodawania / usuwania obrazków;
  • funkcję wyświetlającą slider na stronie

No to tworzymy…

W teorii wszystko już wiemy. Pora na napisanie kodu :)

Na początek musimy stworzyć folder zawierający plugin oraz główny plik (ważne jest, by główny plik miał taką samą nazwę jak folder), ja go nazwałem wp-logo-carousel-by-racy-mind. Następnie musimy opisać naszą wtyczkę:

<?php
/*
  Plugin Name: WP logo carousel created by Racy Mind
  Version: 0.1
  Description: Plugin adds logo carousel
  Author: Racy Mind
  Author URI: http://www.racymind.pl/
 */

Chyba nie muszę nic tu tłumaczyć :). Teraz stworzymy funkcję instalującą.

/**
 * Tworzy tabele bazy danych dla pluginu
 * 
 * @global $wpdb
 */
function rmlc_install() {
    global $wpdb;
    $prefix = $wpdb->prefix;
    $rmlc_tablename = $prefix . "rm_logo_carousel";

    $rmlc_db_version = "1.0";

    if ($wpdb->get_var("SHOW TABLES LIKE '" . $rmlc_tablename . "'") != $rmlc_tablename) {
        $query = "CREATE TABLE " . $rmlc_tablename . " ( 
        id int(9) NOT NULL AUTO_INCREMENT, 
        image varchar(250) NOT NULL,  
        link varchar(250) NOT NULL,  
        title varchar(250) NOT NULL, 
        PRIMARY KEY  (id)
        )";

        $wpdb->query($query);

        add_option("rmlc_db_version", $rmlc_db_version);
        add_option( 'rmlc_speed', '2000' );
        add_option( 'rmlc_interval', '2000');
        add_option( 'rmlc_type', 'vertical');
    }
}

Obiekt $wpdb służy do obsługi bazy danych, na stronach WordPress znajduje się dokumentacja tej klasy. W 8 i 9 linijce pobieramy prefix tabel w bazie danych i przypisujemy do zmiennej nazwę naszej tabeli. W kolejnej linii przypisujemy wersję bazy danych pluginu (może się przydać przy aktualizacjach). W kolejnych wierszach sprawdzamy czy taka tabela już nie istnieje, jeżeli nie, tworzymy ją. Na koniec dodajemy opcję z informacją o wersji bazy danych wtyczki. Funkcja gotowa, musimy jeszcze poinformować WordPress, że funkcja ta ma być uruchamiana podczas aktywacji wtyczki.

register_activation_hook(__FILE__, 'rmlc_install');

Jak mamy funkcję do instalacji to i potrzeba nam do od instalowania…

/**
 * Usuwa tabele bazy danych
 * @global $wpdb $wpdb
 */
function rmlc_uninstall() {
    global $wpdb;
    $prefix = $wpdb->prefix;
    $rmlc_tablename = $prefix . "rm_logo_carousel";
    $query ='DROP TABLE '.$rmlc_tablename;
        $wpdb->query($query);
}
register_deactivation_hook(__FILE__, 'rmlc_uninstall');

Kolejnym krokiem będzie dodanie naszej wtyczki do menu w panelu administracyjnym.

/**
 * Dodaje Logo carousel do menu w PA
 */
function rmlc_plugin_menu() {
    add_menu_page('Logo Carousel', 'Logo Carousel', 'administrator', 'rmlc_settings', 'rmlc_display_settings');
    add_submenu_page('rmlc_settings', __('Images'), __('Images'), 'edit_themes', 'rmlc_images', 'rmlc_images');
}
add_action('admin_menu', 'rmlc_plugin_menu');

Nasza wtyczka jest już widoczna w WordPressie. Zajmijmy się teraz napisaniem kodu odpowiedzialnego za administrację sliderem. Zacznijmy od stworzenia modelu w nowym pliku.

<?php
/**
 * Model pluginu
 *
 * @author Łukasz Socha <biuro@racymind.pl>
 */
class LogoCarousel {

    private $tableName;
    private $wpdb;

    public function __construct() {
        global $wpdb;
        $prefix = $wpdb->prefix;
        $this->tableName = $prefix . "rm_logo_carousel";
        $this->wpdb = $wpdb;
    }

    /**
     * Pobiera wszystkie obrazki
     * @global $wpdb $wpdb
     * @return array Tablica z obrazkami
     */
    public function getAll() {
        $query = "SELECT * FROM  " . $this->tableName . " ORDER BY id DESC;";
        return $this->wpdb->get_results($query, ARRAY_A);
    }

    /**
     * Dodaje obrazki
     * @global $wpdb $wpdb
     * @param array $data
     */
    public function add($data) {
        $this->wpdb->insert($this->tableName, $data, array('%s', '%s', '%s'));
    }

    /**
     * Usuwa wszystkie obrazki
     * @global $wpdb $wpdb
     */
    public function deleteAll() {
        $sql = "TRUNCATE TABLE " . $this->tableName;
        $this->wpdb->query($sql);
    }

}

?>

Myślę, że tu nie trzeba nic tłumaczyć. Korzystając z klasy wpdb tworzę podstawowe zapytania do bazy danych. Mając gotowy plik z modelem, dodajmy go na początku głównego pliku.

define( 'RMLC_PATH', plugin_dir_path( __FILE__ ) );
require RMLC_PATH.'model/logo-carousel.php';

No to teraz możemy wykorzystać model do funkcji zarządzającej obrazkami.

/**
 * Wyswietla formularz do edycji obrazkow
 */
function rmlc_images() {
    $model=new LogoCarousel();
    if (isset($_POST['rmlc_images'])) {
        $model->deleteAll();
        foreach ($_POST['rmlc_images'] as $img) {
            $model->add(array('image' => $img['image'], 'link' => $img['link'], 'title' => $img['title']));
        }
    }
    $results = $model->getAll();

    echo '<h2>' . __('Images') . '</h2>';
    echo '<form action="?page=rmlc_images" method="post">';
    echo '<table class="form-table" style="width:auto;" cellpadding="10">
        <thead>
        <tr>
        <td>' . __('Image') . '</td><td>' . __('Link') . '</td><td>' . __('Title') . '</td><td>' . __('Delete') . '</td>
        </tr>
        </thead>
        <tbody class="items">';
    $i=0;
    foreach ($results as $row) {
        echo '<tr>
            <td><input name="rmlc_images['.$i.'][image]" type="text" value="' . $row['image'] . '" /></td>';
        echo '<td><input name="rmlc_images['.$i.'][link]" type="text" value="' . $row['link'] . '" /></td>';
        echo '<td><input name="rmlc_images['.$i.'][title]" type="text" value="' . $row['title'] . '" /></td>';
        echo '<td><a class="delete" href="">' . __('Delete') . '</a></td>
            </tr>';
        $i++;
    }
    echo '</tbody><tr><td colspan="4"><a class="add" href="">' . __('Add') . '</a></td></tr>';
    echo '<tr><td colspan="4"><input type="submit" value="' . __('Save') . '" /></td></tr>';
    echo '</table>';
    echo '</form>';
    
    echo '
        <script type="text/javascript">
        jQuery(document).ready(function($) {
        $("table .delete").click(function() {
        $(this).parent().parent().remove();
        return false;
        });
        $("table .add").click(function() {
        var count = $("tbody.items tr").length+1;
        var code=\'<tr><td><input type="text" name="rmlc_images[\'+count+\'][image]" /></td><td><input type="text" name="rmlc_images[\'+count+\'][link]" /></td><td><input type="text" name="rmlc_images[\'+count+\'][title]" /></td><td><a class="delete" href="">' . __('Delete') . '</a></td></tr>\';
        $("tbody.items").append(code);
        return false;
        });
        });
        </script>
        ';
}

Jeżeli przesłano do skryptu zmienną POST, czyszczę bazę danych i dodaję dane od nowa. W kolejnych liniach znajduje się formularz do dodawania z elementami JS.

W panelu administracyjnym brakuje nam jeszcze tylko funkcji do konfiguracji.

/**
 * Wyswietla formularz do modyfikacji ustawien pluginu
 */
function rmlc_display_settings() {

    $slider_horizontal = (get_option('rmlc_type') == 'horizontal') ? 'selected="selected" ' : '';

    $slider_vertical = (get_option('rmlc_type') == 'vertical') ? 'selected="selected" ' : '';

    $interval = (get_option('rmlc_interval') != '') ? get_option('rmlc_interval') : '2000';
    $speed = (get_option('rmlc_speed') != '') ? get_option('rmlc_speed') : '2000';

    $html = '
<div class="wrap"><form action="options.php" method="post" name="options">
<h2>Select Your Settings</h2>
' . wp_nonce_field('update-options') . '
<table class="form-table" width="100%" cellpadding="10">
<tbody>
<tr>
<td scope="row" align="left">
 <label>Slider type: </label>
<select name="rmlc_type">
<option '.$slider_horizontal.' value="horizontal">Horizontal</option>
<option '.$slider_vertical.' value="vertical">Vertical</option></select></td>
</tr>
<tr>
<td scope="row" align="left">
 <label>Transition Interval: </label><input type="text" name="rmlc_interval" value="' . $interval . '" /></td>
</tr>
<tr>
<td scope="row" align="left">
 <label>Speed: </label><input type="text" name="rmlc_speed" value="' . $speed . '" /></td>
</tr>
</tbody>
</table>
 <input type="hidden" name="action" value="update'.__('Update').'" />

 <input type="hidden" name="page_options" value="rmlc_speed,rmlc_type,rmlc_interval" />

 <input type="submit" name="Submit" value="Update" /></form></div>
';

    echo $html;
}

Do określenia ustawień slidera wykorzystuję mechanizm opcji.

Mamy już gotową całą część administracyjną, teraz zajmijmy się wyświetlaniem wtyczki na stronie. Na początek załadujmy pliki JS.

function rmlc_scripts() {
    wp_enqueue_script('jquery');
    wp_register_script('jcarousel_core', plugins_url('js/jcarousellite_1.0.1.min.js', __FILE__), array("jquery"));
    wp_enqueue_script('jcarousel_core');

    wp_register_script('jcarousel_init', plugins_url('js/rmlc_slider_init.js', __FILE__));
    wp_enqueue_script('jcarousel_init');

    $type = (get_option('rmlc_type') == '') ? "horizontal" : get_option('rmlc_type');
    $interval = (get_option('rmlc_interval') == '') ? 2000 : get_option('rmlc_interval');
    $speed = (get_option('rmlc_speed') == '') ? 500 : get_option('rmlc_speed');
    $vertical=($type == 'vertical') ? 'true' : 'false';
    $config_array = array(
        'interval' => $interval,
        'speed' => $speed,
        'vertical' => $vertical,
    );

    wp_localize_script('jcarousel_init', 'setting', $config_array);
}

W pluginie tym wykorzystuję tę wtyczkę jQuery. W kolejnych liniach dodaję plik JS z ustawieniami slidera. Korzystam do tego z wcześniej dodanych opcji. Tak wygląda plik JS:

jQuery(document).ready(function($) {
    $("#rmlc_logo_carousel div").jCarouselLite({
        auto: parseInt(setting['interval']),
        speed: parseInt(setting['speed']),
        vertical: parseBool(setting['vertical']),
    });
});
function parseBool(str) {
    if (str.toLowerCase() === 'true')
        return true;
    else
        return false;
}

Ostania funkcja stworzona przez nas będzie służyć do wyświetlania obrazków z bazy danych.

function rmlc_show_logo() {
    rmlc_scripts();
    $model=new LogoCarousel();
    $results = $model->getAll();

    echo '<div id="rmlc_logo_carousel"><div><ul>';
    foreach ($results as $result) {
        echo '<li>';
        if ($result['link'] != '') {
            echo '<a href="' . $result['link'] . '" title="' . $result['title'] . '"><img src="' . $result['image'] . '" alt="' . $result['title'] . '" /></a>';
        } else {
            echo '<img src="' . $result['image'] . '" alt="' . $result['title'] . '" />';
        }
        echo '</li>';
    }
    echo '</ul></div></div>';
}

Na koniec dodajemy wywołanie powyższej funkcji w naszym szablonie i gotowe :)

<?php rmlc_show_logo(); ?>

Gotową wtyczkę możecie pobrać stąd.

Co sądzisz o wpisie?
BeżnadziejnySłabyŚredniDobryBardzo dobry (Brak ocen, bądź pierwszy!)
Loading...
  • Marek

    Przydały by się screeny pokazujące efekt pracy.
    Dopisz strukturę plików. Obecnie brak informacji jak powinien nazywać się plik zawierający dany fragment kodu.

  • Strukturę plików można podejrzeć w gotowym pluginie, ale ok dodam screeny i nazwy plików :)

  • Mariusz

    Na podstawie tej wtyczki piszę bardziej rozbudowany plugin i niestety utknąłem na mechanizmie ustawień. Podany wyżej kod nie działa. Mam WP 4.1, ale wątpię żeby zadziałał na niższych nawet bo nawet nie użyto nigdzie funkcji add_option(). Będę szukał dalej rozwiązania, żeby mieć te ustawienia na własnej stronie, a nie w menu ustawień WP, bo taki poradnik tylko znalazłem.

    • Mariusz

      Znalazłem rozwiązanie:

      Po pierwsze jest błąd w kodzie

      Nie potrzebnie jest tam ‚.__(‚Update’).’ Samo „update” wystarcza.
      Nie rozumiem też tego dodatkowego na początku i na końcu. W ogóle to zmieniłem cały ten układ na taki z ustawień. Z tego co przeczytałem do generowania opcji są gotowe funkcje API, ale ja na razie użyłem czystego htmla do stworzenia formularza.

      Po drugie do funkcji instalacyjnej trzeba dodać po:
      add_option(„rmlc_db_version”, $rmlc_db_version);
      kolejne opcje z wartościami domyślnymi:
      add_option( ‚rmlc_speed’, ‚2000’ );
      add_option( ‚rmlc_interval’, ‚2000’);
      add_option( ‚rmlc_type’, ‚vertical’);

      Oczywiście można się jeszcze bawić w grupowanie tych opcji itp itd, ale na razie tyle mi wystarczy choć już widzę, że w moim przypadku opcji będzie około 20, więc pewnie będę musiał to rozważyć żeby nie zaśmiecić zbytnio bazy.

      • Funkcja __(‚Tekst’) jest funkcją do tłumaczeń w WordPressie. Co do pre i add_option faktycznie masz rację. Już to poprawiłem.

        Dzięki! :)

    • Mariusz

      Przepraszam że się tak rozjechało, ale wstawiłem znaczniki pre i /pre, a nie mogę tego poprawić. „dodatkowego /pre na początku i pre na końcu.”

  • Poradnik jak najbardziej na plus. Wiem, że nie jest to kurs SQL, jednak fajnie byłoby wspomnieć o różnicy między TRUNCATE a DROP :)

    • W manualu dość jasne jest to opisane i łatwo przetestować te funkcje w praktyce, więc za bardzo nie ma o czym pisać. Wpis miałby ze 4 linijki :)

  • Leszek Kobyłecki

    a a alaa