Статьи

Создание поддерживаемых мета-боксов WordPress: сохранение и получение

Когда мы подойдем к концу этой серии, у нас появятся еще две темы:

  1. Сохранение информации и извлечение информации из базы данных
  2. Рефакторинг кода, чтобы он стал более понятным для нас

В предыдущей статье мы рассмотрели проверку, дезинфекцию и реализацию этой функциональности для элементов, которые мы отображали во внешнем интерфейсе. В этой статье мы продолжим процесс, сохранив информацию в базе данных, извлекая информацию и отображая ее во внешнем интерфейсе.

Попутно мы также рассмотрим некоторые встроенные функции WordPress API, разработанные, чтобы помочь сделать это немного проще для нас, а также несколько советов для двойной проверки нашей работы в базе данных, чтобы убедиться, что наша информация сохраняется. именно так, как мы ожидаем.

Нам нужно еще немного, чтобы воплотить этот плагин в жизнь, так что давайте начнем.

Чтобы отобразить данные на внешнем интерфейсе, нам, очевидно, нужно сначала поместить их в базу данных. Поскольку мы работаем с мета-блоками, мы можем использовать функции, которые доступны через Meta Box API, чтобы сохранить эту информацию.

В частности, мы будем работать со следующими функциями:

  • update_post_meta для сохранения информации в базе данных
  • delete_post_meta для удаления информации из базы данных

Есть еще одна функция, add_post_meta , которая также доступна для записи информации в базу данных; однако update_post_meta делает то же самое, если данные еще не существуют в базе данных.

Другой вопрос, который я видел, возникает, когда дело доходит до удаления метаданных поста, почему? То есть зачем удалять информацию, а не сохранять пустое значение?

Вы можете утверждать, что это личное предпочтение — и это так, — но если вы работаете со сложным плагином, который имеет несколько различных полей, и поля не имеют значения, то имеет смысл не поддерживать пустую строку.

Кроме того, если отсутствие значения не имеет смысла для чего-либо в пользовательском интерфейсе, то также нет причин поддерживать пустое значение, поскольку мы позволяем базе данных более точно отражать информацию, отображаемую на экране.

Сохранение пользовательского интерфейса, кода прикладного уровня и базы данных настолько согласованными, насколько это возможно, полезно при попытке написания поддерживаемого кода.

Итак, с учетом сказанного, давайте рассмотрим процесс сохранения полей для каждого из наших полей ввода.

Вспомните из предыдущего поста, что вкладка « Черновик » содержит одну textarea , предназначенную для того, чтобы авторы могли собирать различные заметки и URL-адреса со всего Интернета, которые имеют отношение к контенту, который они готовят к публикации.

Когда мы последний раз оставляли этот код, у нас было следующее:

01
02
03
04
05
06
07
08
09
10
11
12
<?php
  
// If the ‘Drafts’ textarea has been populated, then we sanitize the information.
if ( ! empty( $_POST[‘authors-commentary-drafts’] ) ) {
  
    // We’ll remove all white space, HTML tags, and encode the information to be saved
    $drafts = trim( $_POST[‘authors-commentary-drafts’] );
    $drafts = esc_textarea( strip_tags( $drafts ) );
  
    // More to come…
  
}

Здесь мы посмотрим, заполнено ли содержимое массива $_POST . Если это так, мы затем esc_textarea информацию, используя trim и esc_textarea .

На данный момент мы готовы записать его в базу данных, поэтому давайте заменим строку, которая читает // More to come... следующим кодом (обратите внимание, что мы более подробно рассмотрим код после блок):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<?php
     
// If the ‘Drafts’ textarea has been populated, then we sanitize the information.
if ( ! empty( $_POST[‘authors-commentary-drafts’] ) ) {
 
    // We’ll remove all white space, HTML tags, and encode the information to be saved
    $drafts = trim( $_POST[‘authors-commentary-drafts’] );
    $drafts = esc_textarea( strip_tags( $drafts ) );
 
    update_post_meta( $post_id, ‘authors-commentary-drafts’, $drafts );
 
} else {
     
    if ( » !== get_post_meta( $post_id, ‘authors-commentary-drafts’, true ) ) {
        delete_post_meta( $post_id, ‘authors-commentary-drafts’ );
    }
     
}

Здесь мы используем функцию update_post_meta для добавления или обновления содержимого в базе данных. Обратите внимание, что функция принимает три параметра:

  1. Идентификатор поста, который используется для связи этой информации с постом.
  2. Мета-ключ, который используется для уникальной идентификации значения
  3. Фактическое мета-значение, связанное с мета-ключом

Также обратите внимание, что если значение массива $_POST пусто, мы проверяем, есть ли значение для черновика в базе данных, и, если оно существует, мы удаляем его.

Поскольку мы уже заложили все основы для дезинфекции информации и увидели, как обновлять и удалять информацию в базе данных, делать то же самое для вкладки « Ресурсы » — это почти то же самое.

Единственное исключение состоит в том, что, поскольку мы имеем дело с динамическим набором информации, нам необходимо динамически связать сообщение с уникальным идентификатором на основе того, сколько ресурсов мы экономим.

В предыдущем посте наш код выглядел так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<?php
 
// If the ‘Resources’ inputs exist, iterate through them and sanitize them
if ( ! empty( $_POST[‘authors-commentary-resources’] ) ) {
 
    $resources = $_POST[‘authors-commentary-resources’];
    foreach ( $resources as $resource ) {
 
        $resource = esc_url( strip_tags( $resource ) );
 
        // More to come…
 
    }
 
}

Когда дело доходит до динамической обработки информации, цикл foreach работает отлично; однако при сохранении информации нам нужно ассоциировать уникальный ключ с каждым значением.

Одним из вариантов может быть установка цикла for, чтобы суффиксировать мета-ключ уникальным ключом (используя итератор для каждого значения в цикле), но это может вызвать проблемы при удалении информации. В частности, если пользователь вводит значение для первого, второго и третьего ввода, но затем удаляет второй ввод, оставляя только первое и третье при обновлении записи, нам нужно правильно удалить эти пустые значения и соответственно сместить все записи.

Это можно сделать несколькими различными способами, но на самом деле проще сохранить один сериализованный массив в уникальный индекс, а не пытаться делать что-либо необычное со строками базы данных, запросами и так далее.

Таким образом, мы обновляем код выше, чтобы выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<?php
     
// If the ‘Resources’ inputs exist, iterate through them and sanitize them
if ( ! empty( $_POST[‘authors-commentary-resources’] ) ) {
 
    $resources = $_POST[‘authors-commentary-resources’];
    $sanitized_resources = array();
    foreach ( $resources as $resource ) {
 
        $resource = esc_url( strip_tags( $resource ) );
        if ( ! empty( $resource ) ) {
            $sanitized_resources[] = $resource;
        }
 
    }
     
    update_post_meta( $post_id, ‘authors-commentary-resources’, $sanitized_resources );
 
}

Если вы загляните в базу данных и посмотрите на этот конкретный ключ, вы должны увидеть что-то вроде этого, сохраненное в качестве значения:

1
a:3:{i:0;s:22:»http://tommcfarlin.com»;i:1;s:19:»http://tutsplus.com»;i:2;s:17:»http://google.com»;}

Мы увидим, как это получится, когда мы получим информацию из базы данных позже в этой статье. Также обратите внимание, что нам нужно учитывать случай, когда пользователь удалил все экземпляры ресурсов.

Как и в первой части статьи, мы просто удаляем метаданные публикации, если значение существует. Это можно сделать с помощью очень похожего кода:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
     
// If the ‘Resources’ inputs exist, iterate through them and sanitize them
if ( ! empty( $_POST[‘authors-commentary-resources’] ) ) {
 
    $resources = $_POST[‘authors-commentary-resources’];
    $sanitized_resources = array();
    foreach ( $resources as $resource ) {
 
        $resource = esc_url( strip_tags( $resource ) );
        $sanitized_resources[] = $resource;
 
    }
 
    update_post_meta( $post_id, ‘authors-commentary-resources’, $sanitized_resources );
 
} else {
 
    if ( » !== get_post_meta( $post_id, ‘authors-commentary-resources’, true ) ) {
        delete_post_meta( $post_id, ‘authors-commentary-resources’ );
    }
 
}

Теперь нам нужно сохранить значения для последнего мета-блока.

Последняя вкладка мета-блока, вкладка Опубликовать , станет для нас самой простой в обновлении, поскольку она объединяет все, что мы рассмотрели в этой статье.

В частности, мы перебираем коллекцию значений, записываем их в массив и затем сериализуем массив в базу данных. Пожалуй, самое важное, что следует отметить, это то, что мы используем ассоциативный массив и индексируем каждое значение по значению идентификатора комментария.

Как мы увидим позже в этой статье, это значительно упростит установку значений в пользовательском интерфейсе.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?php
     
// If there are any values saved in the ‘Resources’ input, save them
if ( ! empty( $_POST[‘authors-commentary-comments’] ) ) {
 
    $comments = $_POST[‘authors-commentary-comments’];
    $sanitized_comments = array();
    foreach ( $comments as $comment_id => $comment_value ) {
 
        $comment = strip_tags( stripslashes( $comment_value ) );
        $sanitized_comments[ $comment_id ] = $comment;
 
    }
     
    update_post_meta( $post_id, ‘authors-commentary-comments’, $sanitized_comments );
 
}

Как и в предыдущем разделе, если в массиве $_POST ничего не указано, мы проверяем наличие значений в базе данных и, если они существуют, мы удаляем их:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
     
// If there are any values saved in the ‘Resources’ input, save them
if ( ! empty( $_POST[‘authors-commentary-comments’] ) ) {
 
    $comments = $_POST[‘authors-commentary-comments’];
    $sanitized_comments = array();
    foreach ( $comments as $comment_id => $comment_value ) {
 
        $comment = strip_tags( stripslashes( $comment_value ) );
        $sanitized_comments[ $comment_id ] = $comment;
 
    }
     
    update_post_meta( $post_id, ‘authors-commentary-comments’, $sanitized_comments );
 
} else {
 
    if ( » !== get_post_meta( $post_id, ‘authors-commentary-comments’, true ) ) {
        delete_post_meta( $post_id, ‘authors-commentary-comments’ );
    }
 
}

Как уже упоминалось, этот последний пример объединяет все, что мы видели на последних двух вкладках, поэтому на этом этапе должен быть относительно понятный код.

Прежде чем идти дальше, давайте уделим немного времени, чтобы понять, как мы можем в конечном итоге запрашивать информацию из базы данных.

Допустим, у вас есть пост с идентификатором 9000 (ваш будет зависеть от вашей настройки). Вы можете взять этот идентификатор и заглянуть в таблицу wp_postmeta чтобы увидеть всю метаинформацию, связанную с публикацией.

Таблица метаданных Post

Кроме того, вы можете указать ключ для извлечения только информации, связанной с идентификатором поста и ключом.

Если вы укажете только идентификатор сообщения, вы увидите всю мета-информацию, связанную с сообщением. Если вы укажете только ключ, вы увидите все идентификаторы постов, которые содержат контент для их черновиков. Если вы укажете и идентификатор сообщения, и ключ, вы извлечете только черновую информацию, указанную для одного сообщения.

Говоря о получении данных, давайте рассмотрим шаги, необходимые для отображения метаданных записей на панели инструментов нашего плагина.

Теперь, когда вся информация была сохранена в базе данных, мы можем ввести код, который будет ее извлекать и отображать на соответствующей вкладке каждого плагина. Приятно то, что он будет использовать функции и конструкторы (например, get_post_meta и for ), которые мы уже использовали.

Найдите admin/views/partials/drafts.php . Предполагая, что вы следили за всем до этого момента, код должен выглядеть следующим образом:

1
2
3
<div class=»inside»>
    <textarea id=»authors-commentary-drafts» name=»authors-commentary-drafts»></textarea>
</div>

Чтобы заполнить эту textarea , нам нужно вызвать get_post_meta используя текущий идентификатор сообщения и ключ, который мы использовали для сохранения информации ранее в этой статье. Посмотрите на следующий код:

1
2
3
<div class=»inside»>
    <textarea id=»authors-commentary-drafts» name=»authors-commentary-drafts»><?php echo get_post_meta( get_the_ID(), ‘authors-commentary-drafts’, true );
</div>

Обратите внимание, что мы передаем три параметра:

  1. Первый — это идентификатор сообщения, который получается с помощью функции get_the_ID .
  2. Второй — это ключ, который мы указали при сохранении данных для однозначной идентификации.
  3. Третье — это логическое значение true, которое сообщает функции, чтобы она возвращала нам значение в виде строки, а не в виде массива.

Если значение не существует, то оно просто возвращает пустую строку, поэтому textarea пустое.

Для Ресурсов мы делаем аналогичный звонок; однако на этот раз мы хотим перебрать результаты, чтобы мы могли динамически создавать пользовательский интерфейс.

Из-за способа, которым WordPress сериализует массив, мы все еще хотим, чтобы информация возвращалась в строковом формате (хотя это будет десериализованный массив), который позволит нам использовать цикл foreach для итерации по нему.

1
2
3
4
5
6
7
8
9
<div class=»inside hidden»>
    <div id=»authors-commentary-resources»>
        <?php $resources = get_post_meta( get_the_ID(), ‘authors-commentary-resources’, true );
        <?php foreach ( $resources as $resource ) { ?>
            <input type=»text» value=»<?php echo $resource; ?>» />
        <?php } ?>
    </div><!— #authors-commentary-resources —>
    <p><input type=»submit» id=»authors-commentary-add-resource» value=»Add Resource» class=»button» />
</div>

Вкратце, мы извлекаем информацию из базы данных, перебираем ее, создаем элемент input для каждого значения и затем отображаем ее на странице.

Это также позволяет нам удалять элементы, просто удаляя значение и затем обновляя сообщение. Оттуда дисплей будет перерисовываться так, чтобы не было пустых элементов ввода.

Возможно, это самая легкая часть плагина. Поскольку в шаблоне уже содержится так много кода, единственное, что нам действительно нужно сделать, это определить, установлено ли значение для флажка в массиве метаданных.

Поскольку мы используем идентификатор комментария в качестве числового индекса массива, мы можем просто проверить, содержится ли идентификатор комментария в массиве мета-ключей, который возвращается из метаданных.

Вот как:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<div class=»inside hidden»>
    <?php $comments = $this->load_post_comments();
    <ul id=»author-commentary-comments»>
        <?php foreach ( $comments as $comment ) { ?>
            <li>
                <label for=»authors-commentary-comment-<?php echo $comment->comment_ID ?>»>
                    <?php $comments = get_post_meta( get_the_ID(), ‘authors-commentary-comments’, true );
                    <input type=»checkbox» name=»authors-commentary-comments[<?php echo $comment->comment_ID ?>]» id=»authors-commentary-comment-<?php echo $comment->comment_ID ?>» <?php echo array_key_exists( $comment->comment_ID, $comments ) ?
                    This comment has received a reply.
                </label>
                <p>
                    <em><?php echo $comment->comment_author;
                    <?php echo $comment->comment_content;
                </p>
                <hr />
            </li>
        <?php } ?>
    </ul>
</div>

Обратите внимание, что мы получаем значение из базы данных, снова передавая true в качестве третьего значения.

Затем мы берем текущий идентификатор комментария и проверяем, содержится ли это значение в ключах массива (с помощью array_key_exists ) метаданных записи, которые были возвращены. Если так, мы отмечаем флажок как проверенный; в противном случае мы ничего не делаем.

На данный момент у нас есть полностью функционирующий плагин, который отвечает всем требованиям, которые мы собирались построить, начиная с первой статьи в серии.

Но поддерживается ли сам плагин? То есть выполняет ли он главную задачу этой серии?

В некоторых случаях да, но есть возможности для улучшения. Поскольку часть разработки должна работать с кодом, который мы наследуем, мы рассмотрим, как реорганизовать некоторый код, который мы написали, чтобы сделать его более понятным и более понятным.

Кроме того, мы рассмотрим причины, по которым мы выполняем часть рефакторинга, который мы делаем. В конце концов, было бы бессмысленно упрощать код или перемещать его без каких-либо обоснований.

Но прежде чем делать это, продолжайте работу над этой статьей, взгляните на код из соответствующего репозитория GitHub и оставьте любые комментарии, вопросы или общие отзывы ниже.