• DONATE to NULLED!
    Вы можете помочь Форуму и команде, поддержать финансово.
    starwanderer - модератор этого раздела будет Вам благодарен!

Помощь Создание полной структуры постоянных ссылок для CREATE_POST_TYPE

GiT

Постоялец
Регистрация
28 Июл 2016
Сообщения
160
Реакции
116
Больше нет сил, вторую неделю в поисках решения. Перерыл весь интернет и перепробовал разные фрагменты кода, но так и не нашёл того что мне нужно. Надеюсь на вашу помощь.

Что нужно
Нужно добиться полной структуры URL для произвольного типа записи, чтобы ссылка на страницу записи выглядела так:
сайт.ру / имя-типа-записи / имя-термина-таксономии / имя-вложенного-термина / имя-записи


Что сделано
Создан новый тип записи:
px_product - товары.
px_product_cat - категории товаров ( термины таксономии имеют иерархическую предполагают вложенность от 1 до 3 уровней ).
mysite.com / products / term -1 / child-term -2 / grandchild-term -3 / product-name

Исходник плагина №1
Код работает, только для терма с одним уровнем вложенности.
mysite.com / products / term -1 / product-name
К сожалению, если термины имеют вложенность ( term -1 / child-term -2 / grandchild-term -3 ), в структуре ссылок отображается только последний.
mysite.com / products / grandchild-term -3 / product-name

PHP:
<?php
/*
* Plugin Name: MOD
* Description: DEV
*/

/**
* CPT - Создание произвольного типа записи.
*/

add_action( 'init', 'cpt_product', 0 );
function cpt_product() {

  // Тип записи
  register_post_type( 'px_product', array(
      'labels'             => array( 'name' => __( 'Товары' ) ),
      'public'              => true,
      'show_ui'             => true,
      'capability_type'     => 'post',
      'publicly_queryable'  => true,
      'exclude_from_search' => false,
      'hierarchical'        => true,
      '_builtin'            => false,
      'query_var'           => true,
      'rewrite'             => array( 'slug' => 'products/%px_product_cat%', 'with_front' => true ),
      'supports'            => array( 'title', 'editor', 'author', 'excerpt', 'trackbacks', 'custom-fields' )
  ) );

  // Таксономия
  register_taxonomy( 'px_product_cat', array( 'px_product' ), array(
    'labels'             => array( 'name' => __( 'Категории' ) ),
      'hierarchical'        => true,
      'show_ui'             => true,
      'query_var'           => true,
      'rewrite'             => array( 'slug' => 'products', 'with_front' => true )
  ) );
  flush_rewrite_rules(); // Временно DEL
}

/**
* PermaLink - Внедрение терма таксономии в структуру постоянных ссылок для произвольного типа записи.
*/

// обработчик для %px_product_cat%
add_filter( 'post_type_link', 'permalink_cpt_product', 10, 2 );
function permalink_cpt_product( $link, $post ) {
    if ( $post->post_type === 'px_product' ) {
        if ( $terms = get_the_terms( $post->ID, 'px_product_cat' ) )
            $link = str_replace( '%px_product_cat%', current( $terms )->slug, $link );
    }
    return $link;
}

Возможное решение
В интернете нашёл, одно решение, но оно не совсем подходит и имеет две проблемы.
  1. В постоянной ссылке появляется двойная косая черта " // "
    mysite.com / products / term -1 / child-term -2 / grandchild-term -3 // product-name
  2. Если из product-name перейти на уровень выше, то структура ссылки ломается
    mysite.com / products / grandchild-term -3
Исходник плагина №2

PHP:
<?php
/*
* Plugin Name: MOD
* Description: DEV
*/

/**
* CPT - Создание произвольного типа записи.
*/
add_action( 'init', 'cpt_product', 0 );
function cpt_product() {

  // тип записи
  register_post_type( 'px_product', array(
      'labels'             => array( 'name' => __( 'Товары' ) ),
      'public'              => true,
      'show_ui'             => true,
      'capability_type'     => 'post',
      'publicly_queryable'  => true,
      'exclude_from_search' => false,
      'hierarchical'        => true,
      '_builtin'            => false,
      'query_var'           => true,
      'rewrite'             => array( 'slug' => 'products/%px_product_cat%', 'with_front' => true ),
      'supports'            => array( 'title', 'editor', 'author', 'excerpt', 'trackbacks', 'custom-fields' )
  ) );

  // таксономия
  register_taxonomy( 'px_product_cat', array( 'px_product' ), array(
    'labels'             => array( 'name' => __( 'Категории' ) ),
      'hierarchical'        => true,
      'show_ui'             => true,
      'query_var'           => true,
      'rewrite'             => array( 'slug' => 'products', 'with_front' => true )
  ) );
  flush_rewrite_rules(); // Временно DEL
}

/**
* PermaLink - Внедрение терма таксономии в структуру постоянных ссылок для произвольного типа записи.
*/

// правило перезаписи, где product-name всегда 5-й сегмент
add_filter( 'rewrite_rules_array', 'mmp_rewrite_rules' );
function mmp_rewrite_rules( $rules ) {
    $newRules  = array();
    $newRules['products/(.+)/(.+)/(.+)/(.+)/?$'] = 'index.php?px_product=$matches[4]'; // my custom structure will always have the post name as the 5th uri segment
    $newRules['products/(.+)/?$']                = 'index.php?px_product_cat=$matches[1]';

    return array_merge( $newRules, $rules );
}

// обработчик для %px_product_cat%
add_filter( 'post_type_link', 'filter_post_type_link', 10, 2 );
function filter_post_type_link( $link, $post ) {
    if ($post->post_type != 'px_product')
        return $link;

    if ( $cats = get_the_terms( $post->ID, 'px_product_cat' ) ) {
        $link = str_replace( '%px_product_cat%', get_taxonomy_parents( array_pop( $cats )->term_id, 'px_product_cat', false, '/', true ), $link ); // пользовательская функция для других таксономий
    }
    return $link;
}

// пользовательская функция для других таксономий
function get_taxonomy_parents( $id, $taxonomy, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
    $chain = '';
    $parent = &get_term( $id, $taxonomy );

    if ( is_wp_error( $parent ) ) {
        return $parent;
    }

    if ( $nicename )
        $name = $parent -> slug;    
else
        $name = $parent -> name;

    if ( $parent -> parent && ( $parent -> parent != $parent -> term_id ) && !in_array( $parent -> parent, $visited ) ) {
        $visited[] = $parent -> parent;
        $chain .= get_taxonomy_parents( $parent -> parent, $taxonomy, $link, $separator, $nicename, $visited );

    }

    if ( $link ) {
        // nothing, can't get this working :(
    } else
        $chain .= $name . $separator;
    return $chain;
}

Я не программист, но рад любой помощи. Если у кого есть похожее решение, буду рад исходнику :glob:.
 
Последнее редактирование:
Решение ниже, но есть маленькая Для просмотра ссылки Войди или Зарегистрируйся

PHP:
<?php
/*
* Plugin Name: MOD
* Description: DEV
*/

/**
* Создание произвольного типа записи
* - register_post_types()
*/
add_action('init', 'register_post_types', 0);
function register_post_types()
{
// тип записи
    register_post_type('mod_services', array(
        'labels' => array('name' => __('Товары')),
        'public' => true,
        'show_in_menu' => true,
        'show_in_rest' => null,
        'rest_base' => null,
        'hierarchical' => false,
        'supports' => array('title', 'editor', 'thumbnail'),
        'has_archive' => true,
        'rewrite' => array('slug' => 'catalog', 'with_front' => false),
        'query_var' => true,
    ));
// таксономия
    register_taxonomy('mod_services_catalog', array('mod_services'), array(
        'labels' => array('name' => __('Категории')),
        'public' => true,
        'hierarchical' => true,
        'rewrite' => array('slug' => 'catalog', 'hierarchical' => true, 'with_front' => false),
        'capabilities' => array(),
        'meta_box_cb' => null,
        'show_admin_column' => false,
        'show_in_rest' => null,
        'rest_base' => null,
    ));
}

/**
* Изменяем структуру ссылок записей
* - products_permalink()
*/
add_filter('post_type_link', 'products_permalink', 1, 2);
function products_permalink($permalink, $post)
{
    if (strpos($permalink, 'catalog') === false) return $permalink;
    $terms = get_the_terms($post, 'mod_services_catalog');
    if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) {
        $taxonomy_slug = get_term_parents_list($terms[0]->term_id, 'mod_services_catalog', array(
            'separator' => '/', 'format' => 'slug', 'link' => false, 'inclusive' => true
        ));
        $taxonomy_slug = trim($taxonomy_slug, '/');
    } else {
        $taxonomy_slug = 'categories';
    }
    return str_replace('catalog', 'catalog/' . $taxonomy_slug, $permalink);
}

/**
* Создаём новые правила перезаписи +
* - taxonomy_slug_rewrite()
*/
add_filter('generate_rewrite_rules', 'taxonomy_slug_rewrite');
function taxonomy_slug_rewrite($wp_rewrite)
{
    $rules = array();
    $taxonomies = get_terms(array(
        'taxonomy' => 'mod_services_catalog', 'hide_empty' => false
    ));
    foreach ($taxonomies as $taxonomy) {
        $taxonomy_slug = get_term_parents_list($taxonomy->term_id, 'mod_services_catalog', array(
            'separator' => '/', 'format' => 'slug', 'link' => false, 'inclusive' => true
        ));
        $rules['^catalog/' . $taxonomy_slug . '?$'] = 'index.php?' . $taxonomy->taxonomy . '=' . $taxonomy->slug;
    }
    $rules['^catalog/([^/]*)/?$'] = 'index.php?mod_services_catalog=$matches[1]';
    $rules['^catalog/(.+?)/page/?([0-9]{1,})/?$'] = 'index.php?mod_services_catalog=$matches[1]&paged=$matches[2]';
    $rules['^catalog/(.+?)/([^/]*)/?$'] = 'index.php?mod_services=$matches[2]';
    $wp_rewrite->rules = $rules + $wp_rewrite->rules;
}

/**
* Обновляем правила перезаписи при создании/удалении/изменении таксономий
* - hc_reset_rewrite_rules()
*/
add_action('created_mod_services_catalog', 'hc_reset_rewrite_rules');
add_action('delete_mod_services_catalog', 'hc_reset_rewrite_rules');
add_action('edited_mod_services_catalog', 'hc_reset_rewrite_rules');
add_action('save_mod_services_catalog', 'hc_reset_rewrite_rules');
function hc_reset_rewrite_rules()
{
    flush_rewrite_rules();
}
 
Назад
Сверху