Как безопасно изменить название произвольного типа записи?

24 апр. 2013 г., 10:20:46
Просмотры: 50.6K
Голосов: 30

Я создал произвольный тип записи с названием 'portfolio', но хочу изменить его на 'projects'. Какие точные шаги мне нужно предпринять, чтобы безопасно изменить название и предотвратить исчезновение записей этого типа в панели управления?

Примечание: В типе записи portfolio уже есть записи, поэтому я не могу просто заменить portfolio на projects.

/* Регистрация типа записи Портфолио */
add_action('init', 'create_portfolio');

function create_portfolio() {

    $labels = array(
        'name' => __('Портфолио', 'общее название типа записи'),
        'singular_name' => __('Проект', 'единственное число типа записи'),
        'add_new' => __('Добавить новый', 'элемент портфолио'),
        'add_new_item' => __('Добавить новый проект'),
        'edit_item' => __('Редактировать проект'),
        'new_item' => __('Новый проект'),
        'view_item' => __('Просмотреть проект'),
        'search_items' => __('Поиск проектов'),
        'not_found' =>  __('Ничего не найдено'),
        'not_found_in_trash' => __('В корзине ничего не найдено'),
        'parent_item_colon' => ''
    );

    $args = array(
        'labels' => $labels,
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'post',
        'hierarchical' => false,
        'menu_position' => null,
        'supports' => array('title','editor','thumbnail')
      ); 

    register_post_type( 'portfolio' , $args );
}

/* Регистрация таксономии Навыки */
register_taxonomy("Skills", array("portfolio"), array("hierarchical" => true, "label" => "Навыки", "singular_label" => "Навык", "rewrite" => true));

/* Добавление полей */
add_action("admin_init", "add_portfolio_fields");

function add_portfolio_fields(){
    add_meta_box("website_url", "URL сайта", "website_url", "portfolio", "side", "low");
    add_meta_box("view_more", "Подробнее", "view_more", "portfolio", "side", "low");
    add_meta_box("screenshot_name", "Название скриншота", "screenshot_name", "portfolio", "side", "low");
    add_meta_box("thumbnail_name", "Название миниатюры", "thumbnail_name", "portfolio", "side", "low");
    add_meta_box("thumbnail_alt", "Alt миниатюры", "thumbnail_alt", "portfolio", "side", "low");
}

function website_url(){
    global $post;
    $custom = get_post_custom($post->ID);
    $website_url = $custom["website_url"][0];
    ?>
    <label>URL сайта:</label>
    <input size="50" name="website_url" value="<?php echo $website_url; ?>" />
    <?php
}

function view_more() {
    global $post;
    $custom = get_post_custom($post->ID);
    $view_more = $custom["view_more"][0];
    ?>
    <label>Подробнее:</label>
    <input size="50" name="view_more" value="<?php echo $view_more; ?>" />
    <?php
}

function screenshot_name() {
    global $post;
    $custom = get_post_custom($post->ID);
    $screenshot_name = $custom["screenshot_name"][0];
    ?>
    <label>Название скриншота:</label>
    <input name="screenshot_name" value="<?php echo $screenshot_name; ?>" />
    <?php
}

function thumbnail_name() {
    global $post;
    $custom = get_post_custom($post->ID);
    $thumbnail_name = $custom["thumbnail_name"][0];
    ?>
    <label>Название миниатюры:</label>
    <input name="thumbnail_name" value="<?php echo $thumbnail_name; ?>" />
    <?php
}

function thumbnail_alt() {
    global $post;
    $custom = get_post_custom($post->ID);
    $thumbnail_alt = $custom["thumbnail_alt"][0];
    ?>
    <label>Alt миниатюры:</label>
    <input name="thumbnail_alt" value="<?php echo $thumbnail_alt; ?>" />
    <?php
}

add_action('save_post', 'save_portfolio_details');

function save_portfolio_details(){
    global $post;

    update_post_meta($post->ID, "website_url", $_POST["website_url"]);
    update_post_meta($post->ID, "view_more", $_POST["view_more"]);
    update_post_meta($post->ID, "screenshot_name", $_POST["screenshot_name"]);
    update_post_meta($post->ID, "thumbnail_name", $_POST["thumbnail_name"]);
    update_post_meta($post->ID, "thumbnail_alt", $_POST["thumbnail_alt"]);
}

/* Пользовательские колонки */
add_action("manage_posts_custom_column",  "portfolio_custom_columns");
add_filter("manage_edit-portfolio_columns", "portfolio_edit_columns");

function portfolio_edit_columns($columns){
    $columns = array(
        "cb" => "<input type=\"checkbox\" />",
        "title" => "Название проекта",
        "description" => "Описание",
    );

    return $columns;
}

function portfolio_custom_columns($column){
    global $post;

    switch ($column) {
        case "description":
        the_excerpt();
        break;
    }
}
2
Комментарии

как насчёт замены только меток?

Bainternet Bainternet
24 апр. 2013 г. 10:26:01

Только метки? Я не совсем понимаю, что ты имеешь в виду, но я бы предпочёл изменить всё полностью.

Desi Desi
24 апр. 2013 г. 10:29:44
Все ответы на вопрос 6
0
29

Это также можно сделать напрямую через MySQL.

UPDATE `wp_posts`
SET 
    # Обновляем столбец post_type
    `post_type` = REPLACE(`post_type`,'name_of_old_post_type','name_of_new_post_type'),
    # Обновляем URL-адреса
    `guid` = REPLACE(`guid`,'name_of_old_post_type','name_of_new_post_type')
WHERE `post_type` = 'name_of_old_post_type'

Два важных момента:

  1. Вам нужно обновить все ссылки на этот тип записи в вашем коде (например, в шаблонах, определениях CMB2 или таксономиях).
  2. Если у вас есть ссылки на этот тип записи в таблице wp_postmeta внутри сериализованных массивов, не стоит делать простой UPDATE/REPLACE, так как это может их повредить! Ну, только если новая и старая строки типа записи имеют одинаковую длину.
13 янв. 2014 г. 06:42:27
2

Расширяя ответ Уилла немного дальше..., особенно если вы делаете это из своего плагина:

global $wpdb;
$old_post_types = array('old_type' => 'new_type');
foreach ($old_post_types as $old_type=>$type) {
    $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->posts} SET post_type = REPLACE(post_type, %s, %s) 
                         WHERE post_type LIKE %s", $old_type, $type, $old_type ) );
    $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->posts} SET guid = REPLACE(guid, %s, %s) 
                         WHERE guid LIKE %s", "post_type={$old_type}", "post_type={$type}", "%post_type={$old_type}%" ) );
    $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->posts} SET guid = REPLACE(guid, %s, %s) 
                         WHERE guid LIKE %s", "/{$old_type}/", "/{$type}/", "%/{$old_type}/%" ) );
}

Изменение здесь заключается в том, чтобы не заменять старый тип в guid напрямую, а заменять только если присутствует "post_type=old_type" или "/old_type/". Это позволяет избежать случайной замены валидных слагов (например, если ваш пользовательский тип записи - portfolio, и слаг страницы также содержит portfolio).

Другой альтернативный вариант - сделать что-то вроде этого:

global $wpdb, $wp_rewrite;
foreach ($old_post_types as $old_type=>$type) {
    $q = 'numberposts=-1&post_status=any&post_type='.$old_type;
    $items = get_posts($q);
    foreach ($items as $item) {
        $update['ID'] = $item->ID;
        $update['post_type'] = $type;
        wp_update_post( $update );
    }
}
$wp_rewrite->flush_rules();
17 июл. 2014 г. 09:11:37
Комментарии

Спасибо. Это работает. Одна небольшая деталь: последняя часть второго запроса в цикле должна быть "%post_type={$old_type}%", а не "%post_type={$type}%".

Betty Betty
21 дек. 2019 г. 05:15:31

Просто преобразовал wpdb-запросы в обычные SQL-запросы для упрощения.


UPDATE wp_posts SET post_type = REPLACE(post_type, old_type, type) WHERE post_type LIKE '%old_type%';

UPDATE wp_posts SET guid = REPLACE(guid, 'post_type=old_type', 'post_type=type') WHERE guid LIKE '%post_type=old_type%';

UPDATE wp_posts SET guid = REPLACE(guid, '/old_type/', '/type/') WHERE guid LIKE '%/old_type/%';

Ahmad Wael Ahmad Wael
3 апр. 2023 г. 21:46:41
2

Вот действительно простой способ:

  1. Запустите экспорт WordPress (Инструменты > Экспорт) - экспортируйте только тот тип записей, имя которого хотите изменить
  2. Откройте сгенерированный .xml файл и замените все упоминания старого имени типа записей на новое (как в метаполе "custom_post_type", так и в поле постоянных ссылок)
  3. Создайте новый тип записей с тем же именем, что и в отредактированном .xml (но пока оставьте старый тип на случай неудачи)
  4. Импортируйте отредактированный .xml файл через WordPress Importer (плагин доступен прямо в Инструменты > Импорт)
  5. Убедитесь, что контент появился в новом типе записей, а затем удалите старый
9 нояб. 2015 г. 19:22:23
Комментарии

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

kanlukasz kanlukasz
23 апр. 2020 г. 19:32:18

Спасибо за это... Я также следил за обсуждением здесь, чтобы создать новый пользовательский тип записи: https://wordpress.stackexchange.com/a/252078/142039 -- смог импортировать все свои данные, отлично!

twk twk
13 апр. 2021 г. 09:43:24
1

Используйте запрос к базе данных WordPress, но не забывайте о сериализованных данных опций

Метод, который сработал для меня — это выполнить поиск и замену в базе данных WordPress, но с обязательным условием не повредить сериализованные данные опций. Лучший способ, который я нашел — это использовать безопасный инструмент поиска и замены в базе данных от interconnect/it. Никогда не выполняйте запрос типа SETpost_type= REPLACE(post_type,'old_post_type','new_post_type'), если не уверены в своих действиях, иначе сериализованные данные могут сломаться, так как они хранят контрольную сумму и не смогут правильно десериализоваться.

Прочитайте раздел "Потенциальные проблемы" перед тем, как слепо следовать инструкции

Шаг 1 — Безопасное обновление базы данных с новым именем

  1. Сделайте резервную копию базы данных, так как следующие изменения могут реально повредить её.
  2. Скачайте и распакуйте безопасный инструмент поиска и замены в базе данных от interconnect/it.
  3. Добавьте извлечённую директорию в корень вашего веб-сайта (работает и в поддиректориях).
  4. Перейдите в директорию, например: /mywebsite.com/path/to/utility/directory/
  5. Следуйте инструкциям. Нажмите "dry-run", если хотите сначала увидеть изменения (их будет сотни, даже если у вас всего несколько записей изменяемого типа).
  6. Нажмите "live run", чтобы подтвердить изменения.
  7. Удалите директорию с инструментом из корня WordPress, так как это угроза безопасности.

Шаг 2 — Сбросьте постоянные ссылки

Если вы используете постоянные ссылки, обновление базы данных нарушит перенаправления для ваших пользовательских типов записей. Однако это легко исправить: зайдите в настройки WordPress / постоянные ссылки, запомните текущие настройки (у меня был "Название записи"). Затем переключитесь на "По умолчанию", нажмите "Сохранить", вернитесь к предыдущей настройке и снова сохраните. Теперь проблемы с перенаправлением решены.

Шаг 3 — Переименуйте шаблоны пользовательских типов записей в вашей теме

Если вы, как и я, создали шаблоны для пользовательских типов записей, вам нужно их переименовать, иначе записи будут отображаться некорректно. Просто зайдите в свою тему, найдите файлы с именем старого типа записи и переименуйте их, используя новое название. Например, мне пришлось изменить single-project-portfolio.php на single-before-after.php, когда я изменил тип записи с project-portfolio на before-after.

Шаг 5 — Обновите любой код

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

Проверьте всё

Потенциальные проблемы (прочитайте перед началом процедуры)

Проблемы с синдикацией

Если ваши пользовательские типы записей были синдицированы, учтите, что поиск и замена также изменят GUID этих записей, что заставит всех подписчиков увидеть старые записи как новые. Мне не пришлось с этим сталкиваться, но если это ваш случай, подумайте о ручном выборе таблиц для обработки в safesearch, а затем вручную обновите несериализованные данные с помощью запроса:

SET `post_type` = REPLACE(`post_type`,'old_post_type','new_post_type')
WHERE `post_type` LIKE '%old_post_type%';
17 апр. 2015 г. 22:58:53
Комментарии

очень аккуратно все перечислено. только SQL-запрос в конце неполный, так как вы забыли про guid, но они указаны в ответе Уилла. плюс я бы не использовал WHERE 'post_type' LIKE '%old_post_type%', а использовал бы WHERE 'post_type' = 'old_post_type', так как ваш вариант может случайно затронуть другие типы записей..

honk31 honk31
5 янв. 2017 г. 11:27:39
5

Если у вас еще нет записей в портфолио.

Это было бы очень просто. Переименуйте все, что называется "Portfolio", в "Projects". Вы ничего не потеряете, а просто измените название.

Редактирование:

Попробуйте использовать этот плагин http://wordpress.org/extend/plugins/ptypeconverter/ для безопасного экспорта текущих записей и их импорта в новый пользовательский тип записи.

Итак, шаги:

1 Скачайте и используйте плагин: http://wordpress.org/extend/plugins/ptypeconverter/

2 Сохраните файл вашего пользовательского типа записи "portfolio" в надежном месте. Например, назовите его portfolio_post_typeBACKUP.php

3 Теперь вы можете быть уверены, что в случае неудачи сможете восстановить данные.

4 Измените "portfolio" на "projects"

5 Импортируйте записи с помощью плагина и вуаля!

Надеюсь, это сработает.

24 апр. 2013 г. 10:34:29
Комментарии

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

Desi Desi
24 апр. 2013 г. 10:37:58

Я отредактировал ответ. Удачи!

Wesley Cheung Wesley Cheung
24 апр. 2013 г. 10:46:27

Это потрясающий плагин!

realph realph
7 янв. 2014 г. 19:47:01

этот плагин больше не работает должным образом. я попробовал его, и он не изменил все старые типы записей. но mysql-решение (ответ от Will) работает отлично.

honk31 honk31
5 янв. 2017 г. 11:09:44

Плагин не обновлялся уже два года.

rhand rhand
17 янв. 2017 г. 10:29:01
0

У меня нет достаточной репутации для комментирования, поэтому напишу здесь. Расширяя пример Will. Я заменил LIKE на "=" и указал оба условия на WHERE post_type

UPDATE `wp_posts`
    SET `guid` = REPLACE(`guid`,'old_post_type','new_post_type')
    WHERE `post_type` = 'old_post_type'    

UPDATE `wp_posts`
    SET `post_type` = REPLACE(`post_type`,'old_post_type','new_post_type')
    WHERE `post_type` = 'old_post_type'

Также не забудьте зайти в Админку > Настройки > Постоянные ссылки и нажать "Сохранить изменения". Иначе ваши ссылки могут перестать работать.

Вам также потребуется отредактировать любые имена шаблонов 'single-post-type'.

Этого должно быть достаточно.

22 окт. 2014 г. 17:31:40