Как сохранить метаданные только для определенного пользовательского типа записи?

16

Я пытаюсь настроить пользовательский тип сообщения после этого урока . Тем не менее, я немного смущен тем, как / где реализовывать update_post_meta(). Учебник предлагает этот шаблон:

add_action('save_post', 'save_my_metadata');

function save_my_metadata()
{
    global $post;
    update_post_meta($post->ID, 'my_metadata', $_POST['my_metadata']);
}

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

Я положил выше, functions.phpи я предполагаю, что это может быть частью проблемы. Я предполагаю, что мне нужно ограничить действие «save_post», чтобы срабатывать только для сообщений моего пользовательского типа.

Бобби Джек
источник
Хороший вопрос, Бобби Джек, но могу ли я попросить вас поменять вопрос на что-то вроде «Как сохранить метаданные только для определенных пользовательских типов записей»; так как ваш заголовок слишком общий для людей, чтобы понять, когда они ищут решение этой проблемы.
MikeSchinkel
@Mike: готово (полностью согласен с вашим предложением, спасибо!)
Бобби Джек,

Ответы:

18
function save_my_metadata($ID = false, $post = false)
{
    if($post->post_type != 'your_post_type')
        return;
    update_post_meta($ID, 'my_metadata', $_POST['my_metadata']);
}

Это должно работать. Просто замените 'your_post_type' на имя типа поста. Также малоизвестный факт: хук save_post передает идентификатор сообщения в качестве аргумента.

РЕДАКТИРОВАТЬ

Я обновил функцию, чтобы отразить комментарий Яна. Спасибо, Ян!

Джон П Блох
источник
1
Он даже добавляет сам пост в качестве второго аргумента , поэтому вам не нужно использовать глобальную переменную.
Ян Фабри
Это решение работает ... Я использовал его в клиентских проектах раньше с большим успехом.
EAMann
Блестящий - работает как шарм. И я предполагаю, что имеет смысл сделать "if ($ post-> post_type == 'animal') {update_post_meta ($ ID," number_of_legs ", $ _POST ['number_of_legs']);} еще if ($ post-> post_type == 'vehicle') {update_post_meta ($ ID, "number_of_wheels", $ _POST ['number_of_wheels']);} // ... и т. д. для обработки нескольких различных типов записей? (Извинения за плохие возможности форматирования комментариев!)
Бобби Джек
На самом деле, с несколькими типами записей, я бы рекомендовал вместо этого использовать оператор switch. Меньшая разметка, более высокая производительность, проще добавлять дела в будущем.
EAMann
@EAMann - да, наполовину написав это, я понял, что переключение будет лучше, но комментарии - не идеальное место для начала редактирования кода, поэтому я ленился;)
Бобби Джек,
4

Если вы хотите обрабатывать несколько типов записей, я бы порекомендовал базовый оператор switch:

add_action('save_post', 'save_my_metadata');

function save_my_metadata($ID = false, $post = false)
{
    switch($post->post_type) 
    {
        case 'post_type_1':
            // Do stuff for post type 1
            update_post_meta($ID, 'my_metadata', $_POST['my_metadata']); // Example...
            break;
        case 'post_type_2':
            // Do stuff for post type 2
            break;
        default:
            return;
    }
}

Случаи в основном такие же, как if($post->post_type) == 'post_type_1') {}Но не требуют нескольких блоков if-else. defaultБлок в коммутаторе обрабатывает случаи , когда тип пост не в пользовательском наборе.

EAMann
источник
4

@John P Bloch и @EAMann уже дали отличные ответы, так что мой в дополнение:

  1. Подумайте над префиксом ваших meta_keys подчеркиванием . Это скрывает их от списка настраиваемых полей, отображаемых на экране редактирования сообщения, т.е.

    функция save_my_metadata ($ post_id, $ post = false) {
       если ($ post-> post_type == 'your_post_type')
          update_post_meta ($ post_id, '_my_metadata', $ _POST ['my_metadata']);
    }
    
    Очевидно, это означает, что вам понадобится пользовательский метабокс, чтобы иметь возможность редактировать поля тоже. Вот экран редактирования для контекста:



  2. Другая вещь, которую вы можете сделать, это добавить свой собственный хук, чтобы упростить сохранение определенных типов постов, т. Е. Ваш хук может быть " save_{$post_type}_post"; для movieтипа сообщения это было бы save_movie_post. Вот что вам нужно добавить в functions.phpфайл вашей темы или в плагин где-нибудь:

    add_action ('save_post', 'save_custom_post_type_posts', 10,2);
    функция save_custom_post_type_posts ($ post_id, $ post = false) {
       do_action ( "сохранить _ {$ post-> post_type} _POST");
    }
    
    После этого вы можете переписать свой оригинальный код следующим образом (включая трюк с подчеркиванием из # 1 выше):

    add_action ( 'save_my_postype_post', 'save_my_postype_metadata', 10,2);
    функция save_my_postype_metadata ($ post_id, $ post) {
        update_post_meta ($ post_id, '_my_metadata', $ _POST ['my_metadata']);
    }
MikeSchinkel
источник
1

Лично я предпочитаю следовать шаблону ниже для добавления пользовательских мета-обработчиков к типам записей. Ниже вы можете добавить мета-поддержку к типу поста, просто добавив ключ support ('subtitle' в примере ниже) в массив support для типа поста, вызвав add_post_type_support ('my_post_type', 'subtitle');

class Subtitle_Meta_Handler {
    public function initialize() {
        add_action('add_meta_boxes', array($this, 'add_metabox'), 10, 2);
        add_action('save_post', array($this, 'update'));
    }

    public function add_metabox($post_type, $post)
    {
        if(post_type_supports($post_type, 'subtitle'))
        {
            add_meta_box('subtitle', 'Subtitle', array($this, 'metabox'), $post_type);
        }
    }

    public function metabox($post)
    {
        $subtitle = get_post_meta($post->ID, 'subtitle', true);
        if(!$subtitle)
        {
            $subtitle = '';
        }
        ?>
        <input type="text" style="width: 70%;" value="<?php echo esc_attr($subtitle);?>" name="subtitle" id="subtitle">
        <?php
        wp_nonce_field('update_subtitle', 'subtitle_nonce');
    }

    public function update($post_id)
    {
        if(wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
            return $post_id;
        }
        if(isset($_REQUEST['subtitle_nonce']) && wp_verify_nonce($_REQUEST['subtitle_nonce'], 'update_subtitle')) {
            $subtitle = trim(strip_tags($_REQUEST['subtitle'], '<b><strong><span><a>'));
            if(empty($subtitle)) {
                delete_post_meta($post_id, 'subtitle');
            } else {
                update_post_meta($post_id, 'subtitle', $subtitle);
            }
        }
    }
}
add_action('init', array(new Subtitle_Meta_Handler(), 'initialize'));

Надеюсь, что-то подобное скоро будет добавлено в ядро.

prettyboymp
источник
0

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

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

Получение сообщения типа: get_post_type()или$post->post_type;

hakre
источник
0

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

 function update_meta ($ID = false, $post = false) {
  update_post_meta($ID, 'rest_long', 'Test 1');
  update_post_meta($ID, 'rest_lat', 'Test 2');
}

add_action('post_updated', 'update_meta');
jrutter
источник
Неважно - я понял это!
Jrutter