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

Szybkie prototypowanie: Prototypowanie do kodu, część 1

20

Jeśli chodzi o szybkie prototypy i WordPress, do tej pory zrobiliśmy dwie rzeczy:

  1. zaplanował wtyczkę ,
  2. naszkicowałem schemat, w jaki sposób można zorganizować kod

W tym momencie wykonaliśmy wystarczająco dużo pracy, aby uzasadnić rozpoczęcie refaktoryzacji naszego kodu. Oznacza to, że zaczniemy konwertować prototyp na kod. Ale to jest coś, co trzeba będzie zrobić w dwóch fazach.

Najpierw po prostu wprowadzimy klasy, które reprezentują diagramy z poprzedniego postu i zawierają odpowiedzialność za każdy projekt.

Następnie przyjrzymy się organizacji kodu w przestrzenie nazw i pakiety. Zanim jednak będziemy mogli to zrobić, musimy upewnić się, że kod jest zorientowany obiektowo i pozostaje funkcjonalny. A więc to właśnie wydarzy się w tym poście.

Prototyp do kodu

Jeśli czytałeś poprzednie posty, pamiętaj, że zamierzam śledzić organizację, którą naszkicowałem w ostatnim poście. Oczywiście nie musisz podążać za tym konkretnym projektem.

Słowo o kontroli źródeł

Jeśli używasz kontroli źródła, w tym miejscu zalecam utworzenie gałęzi z gałęzi master (jeśli używasz Git), aby móc wykonywać swoją pracę bez naruszania stabilnej wersji kodu.

Jest to nieco poza zakresem serii, więc jeśli nie używasz kontroli źródła, nie martw się. Jeśli tak, to wybieram rozwinięcie jako nazwę tej gałęzi. Połączę go z powrotem w master , gdy będę pewien, że działa.

Pisanie kodu

Zgodnie z naszkicowaną wczoraj pracą stworzę dwie klasy:

  1. klasa meta box,
  2. klasa wyświetlania metabox.

Nastąpi ponowne wykorzystanie kodu z tego, co już widzieliśmy, jak zobaczysz w poniższym kodzie.

Kod

Po pierwsze, nasze meta box :

<?php
/**
 * Registers the Meta Box with WordPress.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */

/**
 * Registers the Meta Box with WordPress. Defines the ID, title, display function,
 * and the post type on which it will live.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */
class Meta_Box {

    /**
     * A reference to the class that will display the contents in the meta box.
     *
     * @access private
     * @var    Meta_Box_Display
     */
    private $meta_box_display;

    /**
     * Instantiates the class by setting its property equal to a reference to its display.
     */
    public function __construct() {
        $this->meta_box_display = new Meta_Box_Display();
    }

    /**
     * The function responsible for hooking into the WordPress API.
     */
    public function init() {

        add_meta_box(
            'three-recent-posts',
            'Three Recent Posts',
            array( $this->meta_box_display, 'display' ),
            'post',
            'side'
        );
    }
}

A następnie nasz wyświetlacz :

<?php
/**
 * Defines the display for the meta box.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */

/**
 * Defines the display for the meta box that will render the content in the
 * context of its meta box.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */
class Meta_Box_Display {

    /**
     * A reference to the class that will display the contents in the meta box.
     *
     * @access private
     * @var    Post_Messenger
     */
    private $messenger;

    /**
     * Instantiates the object by setting a property equal to that of the class
     * responsible for rendering the messages from the post query.
     */
    public function __construct() {
        $this->messenger = new Post_Messenger( $this );
    }

    /**
     * If there are posts to display, renders them in the metabox. Otherwise, displays
     * a note that there are no posts to display.
     */
    public function display( $message) {
        $this->messenger->get_message();
    }
}

Że w kodzie meta box, w kodzie meta box jawnie tworzymy instancję wyświetlania, abyśmy w razie potrzeby mogli wywołać jego metodę wyświetlania.

Inną alternatywą byłoby utworzenie oddzielnego wystąpienia dwóch obiektów, a następnie wstrzyknięcie wyświetlacza do pola meta za pomocą wstrzyknięcia konstruktora lub czegoś podobnego. Musiałoby to zostać zrobione w klasie innej firmy.

Zaletą tego jest nieco większe rozdzielenie obu klas. Być może omówimy, jak to zrobić w następnym poście.

Następnie musimy przejść dalej i zdefiniować klasę odpowiedzialną za wyświetlanie wiadomości w kontekście Meta Box Display. Oto, co nazwiemy Post Messenger :

<?php
/**
 * Display content for the meta box when requested.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */

/**
 * Retrieves information from the class responsible for querying the database and
 * renders it in the context of our meta box when called via the Meta Box Display.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */
class Post_Messenger {

    /**
     * A reference to the query resonsible for retrieving post information from
     * the database.
     *
     * @access private
     * @var    WP_Query
     */
    private $query;

    /**
     * A reference to the message that's displayed in the view of the
     * meta box.
     *
     * @access private
     */
    private $message;

    /**
     * Instantiates the class by setting a reference to the query.
     */
    public function __construct() {
        $this->query = new Post_Query();
    }

    /**
     * Retrieves the content to be displayed in the meta box.
     */
    public function get_message() {

        $this->get_description();

        if ($this->query->has_posts()) {
            $this->get_post_message();
        } else {
            $this->get_no_posts_message();
        }
    }

    /**
     * Displays the description of the content of the meta box.
     *
     * @access private
     */
    private function get_post_message() {
        include_once 'post-list.php';
    }

    /**
     * Displays the description of the content of the meta box.
     *
     * @access private
     */
    private function get_description() {
        include_once 'message-description.php';
    }

    /**
     * Displays a message of there are no recent posts.
     *
     * @access private
     */
    private function get_no_posts_message() {
        include_once 'no-post-list.php';
    }
}

Zauważ, że Post Messenger również odwołuje się do Post Query. Jest to klasa, w której odbywa się komunikacja z bazą danych. Dołączyłem również kilka funkcji pomocniczych, aby kod widoku był nieco prostszy, jak zobaczymy za chwilę.

<?php
/**
 * Queries the database for three most recent posts.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */

/**
 * Queries the database for three most recent posts. Returns the query to the
 * caller so that it can be interrogates for posts or not.
 *
 * @author Tom McFarlin
 * @since  0.2.0
 */
class Post_Query {

    /**
     * A reference to the WP_Query this class wraps.
     *
     * @access private
     * @var    WP_Query
     */
    private $query;

    /**
     * Instantiates the class by preparing instance data and executing the
     * query so the display can render the contents.
     */
    public function __construct() {

        $this->query = null;
        $this->get_posts();
    }

    /**
     * Executes the query for returning the post recent posts ordered by date.
     *
     * @access private
     */
    private function get_posts() {

        $args = array(
            'post_type'   => 'post',
            'post_status' => 'publish',
            'orderby'     => 'date',
            'order'       => 'desc',
        );
        $this->query = new WP_Query( $args );

        return $this->query;
    }

    /**
     * A helper function to determine if the query has any posts.
     */
    public function has_posts() {
        return! $this->query->have_posts();
    }

    /**
     * A helper function for retrieving the next post in the list of
     * posts
     */
    public function the_post() {
        return $this->query->the_post();
    }
}

I to wszystko w przypadku klas podstawowych. Oczywiście musimy jeszcze porozmawiać o poglądach.

Widoki

Widoki odpowiadają za renderowanie kodu HTML w kontekście pola meta. Nie lubię pisać HTML w kontekście PHP (ani też lubię mieszać PHP w kontekście HTML, ale jest to nieuniknione w tym projekcie).

Jest kilka świetnych projektów szablonów, które to ułatwiają, ale mam dygresję. W każdym razie zauważysz, że w  pliku post-list.php znajdują się odniesienia do funkcji pomocniczych w klasie Post Query. Ma to na celu upewnienie się, że nie ujawniam zbyt wielu właściwości i nie naruszam Prawa Demeter.

Przyjrzyjmy się najpierw temu plikowi, ponieważ jest najbardziej skomplikowany :

<ol>
    <?php while ($this->query->has_posts()) {  ?>
        <?php $this->query->the_post(); ?>
        <li>
            <a href="<?php get_the_permalink(); ?>" target="_blank">
                <?php echo get_the_title(); ?>
            </a>
        </li>
    <?php } ?>
</ol>

Wygląda jak standardowy kod WordPressa, ale pamiętaj, że skoro ten plik jest wywoływany w Post Messenger, będzie odnosić się do zapytania jako do zapytania, które jest opakowane przez tę klasę.

Ostatnie dwa pliki są dość proste. Jeden z nich zawiera opis :

<p>
    <span class="description">
        Displays up to the three most recent posts.
    </span><!-- .description -->
</p>

Drugi wyświetla komunikat, gdy nie ma żadnych postów :

<p>There are no recent posts.</p>

Poza tym jest wykonywana podstawowa funkcjonalność.

Uruchamianie wtyczki

Ostatnią rzeczą, którą musimy zrobić, to uruchomić wtyczkę. W tym celu zmieniamy kod w głównym pliku wtyczki tak, aby wyglądał tak :

<?php
/**
 * Three Recent Posts
 *
 * @package     TRP
 * @author      Tom McFarlin
 * @copyright   2017 Tom McFarlin
 * @license     MIT
 *
 * @wordpress-plugin
 * Plugin Name: Three Recent Posts
 * Plugin URI:  https://tommcfarlin.com/three-recent-posts/
 * Description: Displays the three mot recent posts in your post editor screen.
 * Version:     0.2.0
 * Author:      Tom McFarlin
 * Author URI:  https://tommcfarlin.com
 * Text Domain: three-recent-posts
 * License:     GPL
 * License URI: http://www.gnu.org/licenses/gpl-3.0.txt
 */

include 'class-meta-box.php';
include 'class-meta-box-display.php';
include 'class-post-messenger.php';
include 'class-post-query.php';

add_action( 'add_meta_boxes', 'trp_start' );
/**
 * Starts the plugin.
 */
function trp_start() {

    $meta_box = new Meta_Box();
    $meta_box->init();
}

To podłączy się do WordPressa, utworzy instancję naszej wtyczki, a następnie wprawi ją w ruch. Kiedy uruchomisz go w swojej instalacji WordPressa, powinien wyglądać dokładnie tak, jak w pierwszej wersji.

Jedyna różnica polega na tym, że mamy teraz rzeczy zorganizowane w klasy, a nie w poszczególne funkcje.

Uwagi

Po pierwsze, istnieją tutaj możliwości refaktoryzacji, która jeszcze bardziej zmniejszyłaby rozdzielenie (takie jak różne rodzaje wstrzykiwania zależności itp.), ale celem tej serii nie jest pokrycie tego.

Zamiast tego jest to pomysł zobaczenia wtyczek napisanych przez wiele funkcji proceduralnych, a następnie rozbicie ich na bardziej konceptualne klasy, które obejmują ich obowiązki.

Po drugie, jeśli przejrzysz kod źródłowy w repozytorium dla tej wersji projektu, zobaczysz, że wprowadziłem również composer.json. Dzieje się tak, aby podczas pisania kodu móc korzystać z PHP CodeSniffer i WordPress Coding Standards .

W ostatniej części serii zajmiemy się przestrzenią nazw i reorganizacją plików. Jeśli czas pozwoli, dodamy autoloader, dzięki czemu nie będziemy musieli ręcznie umieszczać plików na górze naszego pliku wtyczki.

W końcu połączyłem ten kod z masterem i oznaczyłem go jako 0.2.1 (ponieważ musiałem zrobić małą poprawkę), ponieważ wciąż jest to bardzo w toku.

Posty z serii

  1. Szybkie prototypowanie z WordPress: od koncepcji do wtyczki
  2. Szybkie prototypowanie z WordPress: analiza koncepcji
  3. Szybkie prototypowanie: Prototypowanie do kodu, część 1
  4. Szybkie prototypowanie: Prototypowanie do kodu, część 2
  5. Szybkie prototypowanie: Przedstawiamy automatyczne ładowanie

Źródło nagrywania: tommcfarlin.com

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