Как добавить таксономию в структуру URL произвольного типа записи?

Прежде всего я хочу поздравить всех своих читателей с Новым Годом! Не ожидал, что дата публикации поста выпадет на 1-е января 🙂

А теперь вернёмся к WordPress и глянем на простой пример интернет-магазина.

Допустим у магазина есть отдельный тип записей под товары — tovar и таксономия для их организации tovar_kat. По умолчанию URL товара будет следующего вида /tovar/ЯРЛЫК ТОВАРА/.

Мы же хотим привести его к такому виду: /ЯРЛЫК КАТЕГОРИИ ТОВАРА/ЯРЛЫК ТОВАРА/. Если смотреть по конкретному примеру, то будет произведена замена /tovar/burton-cartel/ на /snowboard-bindings/burton-cartel/.

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

рекомендуемые настройки постоянных ссылок в WordPress

Перезаписываем ссылки и основной запрос

add_filter('post_link', 'true_post_type_permalink', 20, 3);
add_filter('post_type_link', 'true_post_type_permalink', 20, 3);
 
function true_post_type_permalink( $permalink, $post_id, $leavename ) {
 
    $post_type_name = 'tovar'; // название типа записи, вы можете найти его в админке или в функции register_post_type()
    $post_type_slug = 'tovar'; // часть URL товаров, не всегда совпадает с названием типа записи!
    $tax_name = 'tovar_kat'; // ну это понятно, название таксономии - категории товаров
 
    $post = get_post( $post_id ); // получаем объект поста по его ID
 
    if ( strpos( $permalink, $post_type_slug ) === FALSE || $post->post_type != $post_type_name ) // не делаем никаких изменений, если тип записи не соответствует или если URL не содержит ярлык tovar
        return $permalink;
 
        $termini = wp_get_object_terms( $post->ID, $tax_name ); // получаем все категории, к которым принадлежит данный товар
 
 
        if ( !is_wp_error( $termini ) && !empty( $termini ) && is_object( $termini[0] ) ) // и делаем перезапись ссылки, только, если товар находится хотя бы в одной категории, иначе возвращаем ссылку по умолчанию
            $permalink = str_replace( $post_type_slug, $termini[0]->slug, $permalink );
 
    return $permalink;
}
 
 
add_filter('request', 'true_post_type_request', 1, 1 );
 
function true_post_type_request( $query ){
    global $wpdb; // нам немного придётся поработать с БД
 
    $post_type_name = 'tovar'; // указываем тут название типа записей товара
    $tax_name = 'tovar_kat'; // а также название таксономии - категории товаров
 
    $yarlik = $query['attachment']; // после того, как мы изменили ссылки товаров в предыдущей функции, WordPress начал принимать их за страницы вложений
 
    // а теперь давайте получим ID товара, ярлык которого соответствует запросу на странице
    $post_id = $wpdb->get_var(
        "
        SELECT ID
        FROM $wpdb->posts
        WHERE post_name = '$yarlik'
        AND post_type = '$post_type_name'
        "
    );
 
    $termini = wp_get_object_terms( $post_id, $tax_name ); // товар должен находиться в категории (одной или нескольких)
 
 
    if( isset( $yarlik ) && $post_id && !is_wp_error( $termini ) && !empty( $termini ) ) : // изменяем запрос, если всё ок
 
        unset( $query['attachment'] );
        $query[$post_type_name] = $yarlik;
        $query['post_type'] = $post_type_name;
        $query['name'] = $yarlik;
 
    endif;
 
    return $query; // возвращаем результат
}

Ставим 301 редирект со старых ссылок на новые

Про важность редиректа думаю рассказывать не нужно. Особенно если ваш сайт функционирует уже давно и набрал большое количество товаров. Тогда без редиректа будет большое количество ошибок 404.

add_action('template_redirect', 'true_post_type_redirect');
 
function true_post_type_redirect() {
 
    $post_type_name = 'tovar'; // как и в первом шаге, указываем тут название типа записи
    $post_type_slug = 'tovar'; // тут ярлык, то есть то, что в URL
    $tax_name = 'tovar_kat'; // и название таксономии
 
    if( strpos( $_SERVER['REQUEST_URI'], $post_type_slug ) === FALSE) // выходим из функции ничего не делая, если URL не содержит ярлыка типа записи "tovar"
        return;
 
    if( is_singular( $post_type_name ) ) : // функцию выполняем только на страницах записей данного типа
        global $post, $wp_rewrite;
 
        $termini = wp_get_object_terms( $post->ID, $tax_name ); // опять проверяем товар на наличие категорий
 
        if ( !is_wp_error( $termini ) && !empty( $termini ) && is_object( $termini[0] ) ) :
 
            wp_redirect( site_url() . '/' . $wp_rewrite->front . '/' . $termini[0]->slug . '/' . $post->post_name, 301 );
            // wp_redirect( get_permalink( $post->ID ), 301 ); // можно использовать эту строчку, но строго обязательно должен быть установлен первый хук из этой статьи
 
            exit();
            endif;
    endif;
 
}

Источник: misha.blog

Миша Рудрастых

Путешествует по миру и рассказывает всем о WordPress лично, у себя в блогах и на курсах в Санкт-Петербурге. Умеет просто объяснять сложные вещи, делает это красиво. Организовывает неплохие WordCamp's, но совсем не умеет слушать чужие доклады.

Добавить комментарий

%d такие блоггеры, как: