Использование произвольного поля в качестве заголовка записи

10 нояб. 2011 г., 06:29:47
Просмотры: 14.9K
Голосов: 3

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

function custom_post_type_title ( $post_id ) {
    global $wpdb;
    if ( get_post_type( $post_id ) == 'listing' ) {
        $title = get_post_meta($post_id, 'listing_name', true);
        $where = array( 'ID' => $post_id );
        $wpdb->update( $wpdb->posts, array( 'post_title' => $title ), $where );
    }
}

add_action('init', 'listing_save_post');
function listing_save_post( $post_id ) {
        if ( ! defined( 'DOING_AUTOSAVE' ) && ! DOING_AUTOSAVE ) return;
        add_action('save_post', 'custom_post_type_title', 100);
        add_action('publish_post', 'custom_post_type_title', 100);
}

И также (временно закомментировал nonce-поля, пока не разберусь, как они работают):

add_filter('wp_insert_post_data', 'change_title', 99, 2);
function change_title($data, $postarr)
{    
    // Если форма не отправлена, ничего не делаем
    if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;

    // Проверяем, что данные пришли с нужной страницы и с правильными правами,
    // так как save_post может вызываться в других случаях
    // if(!isset($_POST['my_nonce_field'])) return;

    // Если nonce установлен, проверяем его
    // if(isset($_POST['my_nonce_field']) && !wp_verify_nonce($_POST['my_nonce_field'], plugins_url(__FILE__))) return;

    // Объединяем адрес с термином
    $title = $_POST['listing_name'];
    $data['post_title'] = $title;

    return $data;
}

В обоих случаях результат одинаков:

  1. При сохранении новой записи страница перезагружается, показывает сообщение об успешном сохранении, но все произвольные поля оказываются пустыми. (Без этого кода пользовательский тип записи работает нормально, и поля сохраняются).

  2. При просмотре списка записей пользовательского типа, записи не отображаются.

Есть идеи?

ОБНОВЛЕНИЕ

Для уточнения: я использую пользовательский тип записи без поддержки заголовка. Тем не менее я пытаюсь заполнить поле заголовка значением из произвольного поля.

0
Все ответы на вопрос 3
3

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

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

НО я предполагаю, что это делается для целей отображения: вы хотите, чтобы этот тип записи показывал другой заголовок на фронтенде, основанный на значении произвольного поля. Фильтры — это простой способ реализовать такое поведение.

the_title, стандартный тег шаблона, является тонкой обёрткой вокруг get_the_title, которая содержит фильтр под названием the_title. Он получает два аргумента: сам заголовок и ID записи. Подключитесь к этому фильтру и измените заголовок на основе вашего произвольного поля.

<?php
add_filter( 'the_title', 'wpse33385_filter_title', 10, 2 );
function wpse33385_filter_title( $title, $post_id )
{
    if( $new_title = get_post_meta( $post_id, 'custom_field_name', true ) )
    {
        return $new_title;
    }
    return $title;
}

Несколько важных моментов о вашем коде:

Действия не получают аргументы произвольно. Например, функции, подключённые к init, не получают никаких аргументов. Когда вызывается do_action, первый аргумент — это название хука. Последующие аргументы передаются подключённым функциям, если это указано (через четвёртый, опциональный аргумент add_action).

Вызов do_action( 'init' ); находится в wp-settings.php. Посмотрите, аргументов нет.

Так что вот такой код:

<?php
add_action('init', 'listing_save_post');
function listing_save_post( $post_id ) {
        if ( ! defined( 'DOING_AUTOSAVE' ) && ! DOING_AUTOSAVE ) return;
        add_action('save_post', 'custom_post_type_title', 100);
        add_action('publish_post', 'custom_post_type_title', 100);
}

Не будет работать так, как вы ожидаете. Более того, вызовы add_action внутри функции можно просто вынести наружу... Вот так будет работать:

add_action('save_post', 'custom_post_type_title', 100);
function custom_post_type_title( $post_id ) {
    // здесь действия
}

Нужно использовать только save_post, а не его вместе с publish_post.

Я всегда стараюсь избегать прямого обращения к $wpdb, если это возможно, потому что часто есть более удобные API. То, что вы пытались сделать — это обновление записи. Используйте wp_update_post. В вашем случае это не подходящий вариант (как указано в кодексе, это может вызвать бесконечный цикл).

Это получилось довольно многословно, извините. Надеюсь, это прояснило некоторые моменты о системе хуков WordPress!

Сделайте эти ресурсы своими лучшими друзьями:

10 нояб. 2011 г. 07:40:53
Комментарии

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

Jonathan Wold Jonathan Wold
10 нояб. 2011 г. 19:21:34

Фильтр, который я вам показал, сработает для этого. Если вы хотите полностью убрать поле заголовка, в массиве $args для register_post_type есть аргумент под названием post_type_supports, установите его так: 'post_type_supports' => array( 'content' ), и поле заголовка исчезнет с экрана редактирования.

chrisguitarguy chrisguitarguy
10 нояб. 2011 г. 21:47:01

Это сработало! Итак, я использую фильтр для достижения нужного эффекта. Если бы я попытался получить значение, скажем, через WPDB, поля post_title, я бы получил значение "auto draft" - верно? "Перфекционист" во мне хочет это исправить, хотя я понимаю, что "фильтр" работает. Есть мысли? ОГРОМНОЕ спасибо за помощь!

Jonathan Wold Jonathan Wold
11 нояб. 2011 г. 04:05:35
0

Спасибо, ваш фильтр отлично сработал.

К вашему сведению:

Я добавил проверку на админку, чтобы избежать изменения entry-title на мой кастомный "longtitle" (по умолчанию = menu-item-title) во время редактирования страницы.


function pcdg_filter_title( $title, $post_id )
{
    if(!is_admin())
    {
        if( $new_title = get_post_meta( $post_id, 'longtitle', true ) )
        {
            return $new_title;
        }
    }
    return $title;
}
add_filter( 'the_title','pcdg_filter_title',10,2 );
25 мар. 2015 г. 13:08:08
0

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

местоположение • заселенность • цена

в качестве заголовка фильтра вместо отображения только одного имени произвольного поля.

Спасибо!

29 авг. 2023 г. 02:01:34