Вилучіть таксономічний слиз із власної ієрархічної таксономії


21

Я створив «форумну» систематику, використовуючи наступні правила:

register_taxonomy(
  'forum',
  array('topic'),
  array(
    'public' => true,
    'name' => _a('Forums'),
    'singular_name' => _a('Forum'),
    'show_ui' => true,
    'show_in_nav_menus' => true,
    'hierarchical' => true,

    'labels' => array(
      'name' => _a('Forums'),
      'singular_name' => _a('Forum'),
      'search_items' => _a('Search Forums'),
      'popular_items' => _a('Popular Forums'),
      'all_items' => _a('All Forums'),
      'parent_item' => _a('Parent Forum'),
      'parent_item_colon' => _a('Parent Forum:'),
      'edit_item' => _a('Edit Forum'),
      'update_item' => _a('Update Forum'),
      'add_new_item' => _a('Add New Forum'),
      'new_item_name' => _a('New Forum Name'),
    ),
    'query_var' => true,
    'rewrite' => array('slug' => 'forums', 'with_front' => false, 'hierarchical' => true),  
  )
);

На передньому кінці URL-адреси виглядають так:

forums/general-discussion/sub-forum

Як я можу видалити передню слизьку ("форуми")? Тобто, змініть URL-адреси на:

general-discussion/sub-forum

Якщо я передаю порожній аргумент слизу на register_taxonomy (), він працює, але це викликає проблеми з постійними посиланнями типу публікації, пов'язаними з цією систематикою


@One Trick Pony - Ви намагалися замість того, щоб залишати 'slug' => 'forums'порожнім, просто видаливши його і просто маючи 'rewrite' => array('with_front' => false, 'hierarchical' => true)? Я думаю, що раніше працювало для мене. Також переконайтеся, що ви змили постійні посилання.
eileencodes

спробував це, і постійні посилання виглядають однаково. Додавання 'slug' => ''змушує працювати, але потім повідомлення, що використовують цю систематику, генерують
404s

@One Trick Pony - Окрім «загальної дискусії», які ще сегменти шляху верхнього рівня вам потрібні?
MikeSchinkel

будь-який %forum%повинен бути сегментом верхнього рівня
onetrickpony

@One Trick Pony - я просто сподівався, що ти дасть мені ще деякі сегменти шляху верхнього рівня для контексту.
MikeSchinkel

Відповіді:


11

ОНОВЛЕННЯ

З моменту написання цього ядра WordPress додано 'do_parse_request'гачок, що дозволяє обробляти URL-адреси елегантно та без необхідності розширювати WPклас. Я детально висвітлював цю тему у своїй розмові про Atlanta WordCamp 2014 року під назвою " Маршрутизація жорстких URL-адрес " ; слайди доступні за посиланням.

ОРИГІНАЛЬНИЙ ВІДПОВІДЬ

Розробка URL-адреси важлива вже більше десяти років; Я навіть писав про це блог кілька років тому. І хоча WordPress сума - це блискуче біт програмного забезпечення, на жаль , система перезапису URL-адрес не вистачає мозкових мертвих (IMHO, звичайно. :). У будь-якому разі, раді бачити людей, які піклуються про дизайн URL-адрес!

Відповідь, яку я буду надати, - це плагін, який я називаю, WP_Extendedщо є доказом концепції цієї пропозиції про Trac (зауважте, що пропозиція почалася як одне і перетворилася на іншу, тому вам потрібно прочитати всю річ, щоб побачити, де її очолив.)

В основному ідея полягає в підкласі WPкласу, заміні parse_request()методу, а потім присвоєнні глобальної $wpзмінної з екземпляром підкласу. Тоді всередині parse_request()вас фактично оглядають шлях за сегментом шляху, а не використовувати список регулярних виразів, які повинні відповідати URL-адресі в повному обсязі.

Отже, щоб сказати це явно, ця методика вставляє логіку перед parse_request()якою перевіряє відповідність URL-до-RegEx і замість цього спочатку шукає збіги термінів таксономії, але вона ТІЛЬКИ замінює parse_request()і залишає цілою рештою системи маршрутизації WordPress URL непошкодженою, включаючи і особливо використання $query_varsзмінної.

У вашому випадку використання це лише порівняння сегментів шляху URL з умовами таксономії, оскільки це все, що вам потрібно. Ця реалізація інспектує таксономії термінів поважаючи батько-дитина тривалі відносини , і коли він знаходить збіг, привласнює URL - шлях (мінус передній і задній косою риси) , щоб $wp->query_vars['category_name'], $wp->query_vars['tag']чи $wp->query_vars['taxonomy']& $wp->query_vars['term']і обходить parse_request()метод WPкласу.

З іншого боку, якщо шлях URL не відповідає терміну з вказаної вами таксономії, він делегує логіку маршрутизації URL в систему перезапису WordPress, викликаючи parse_request()метод WPкласу.

Щоб використовувати WP_Extendedдля свого випадку використання, вам потрібно зателефонувати до register_url_route()функції з functions.phpфайлу вашої теми так:

add_action('init','init_forum_url_route');
function init_forum_url_route() {
  register_url_route(array('taxonomy'=>'forum'));
}

Що тут вихідного коду для плагіна:

<?php
/*
Filename: wp-extended.php
Plugin Name: WP Extended for Taxonomy URL Routes
Author: Mike Schinkel
*/
function register_url_route($args=array()) {
  if (isset($args['taxonomy']))
    WP_Extended::register_taxonomy_url($args['taxonomy']);
}
class WP_Extended extends WP {
  static $taxonomies = array();
  static function on_load() {
    add_action('setup_theme',array(__CLASS__,'setup_theme'));
  }
  static function register_taxonomy_url($taxonomy) {
    self::$taxonomies[$taxonomy] = get_taxonomy($taxonomy);
  }
  static function setup_theme() { // Setup theme is 1st code run after WP is created.
    global $wp;
    $wp = new WP_Extended();  // Replace the global $wp
  }
  function parse_request($extra_query_vars = '') {
    $path = $_SERVER['REQUEST_URI'];
    $domain = str_replace('.','\.',$_SERVER['SERVER_NAME']);
    //$root_path = preg_replace("#^https?://{$domain}(/.*)$#",'$1',WP_SITEURL);
$root_path = $_SERVER['HTTP_HOST'];

    if (substr($path,0,strlen($root_path))==$root_path)
      $path = substr($path,strlen($root_path));
    list($path) = explode('?',$path);
    $path_segments = explode('/',trim($path,'/'));
    $taxonomy_term = array();
    $parent_id = 0;
    foreach(self::$taxonomies as $taxonomy_slug => $taxonomy) {
      $terms = get_terms($taxonomy_slug);
      foreach($path_segments as $segment_index => $path_segment) {
        foreach($terms as $term_index => $term) {
          if ($term->slug==$path_segments[$segment_index]) {
            if ($term->parent!=$parent_id) { // Make sure we test parents
              $taxonomy_term = array();
            } else {
              $parent_id = $term->term_id; // Capture parent ID for verification
              $taxonomy_term[] = $term->slug; // Collect slug as path segment
              unset($terms[$term_index]); // No need to scan it again
            }
            break;
          }
        }
      }
      if (count($taxonomy_term))
        break;
    }
    if (count($taxonomy_term)) {
      $path = implode('/',$taxonomy_term);
      switch ($taxonomy_slug) {
        case 'category':
          $this->query_vars['category_name'] = $path;
          break;
        case 'post_tag':
          $this->query_vars['tag'] = $path;
          break;
        default:
          $this->query_vars['taxonomy'] = $taxonomy_slug;
          $this->query_vars['term'] = $path;
          break;
      }
    } else {
      parent::parse_request($extra_query_vars); // Delegate to WP class
    }
  }
}
WP_Extended::on_load();

PS CAVEAT №1

Хоча для даного сайту я думаю, що ця методика працює чудово, але ця методика НІКОЛИ не повинна використовуватися для плагіна, який розповсюджуватиметься на WordPress.org для інших користувачів . Якщо вона лежить в основі програмного пакету на основі WordPress, то це може бути нормально. В іншому випадку ця методика повинна обмежуватися вдосконаленням маршрутизації URL-адрес для певного сайту .

Чому? Тому що лише один плагін може використовувати цю техніку . Якщо два плагіни спробують використовувати його, вони будуть конфліктувати між собою.

Окрім цього, ця стратегія може бути розширена, щоб загалом обробляти практично кожну модель використання, яка може бути потрібна, і це те, що я маю намір застосувати, як тільки знайду вільний час або клієнта, який зможе спонсорувати час, який знадобиться будувати повністю загальні реалізації.

КАВАТИ №2

Я написав це, щоб переосмислити, parse_request()що є дуже великою функцією, і цілком можливо, що я пропустив властивість або два глобального $wpоб'єкта, який я мав би встановити .. Тож якщо щось діятиме непросто, дайте мені знати, і я буду радий досліджуйте його і переглядайте відповідь, якщо це буде потрібно.

Все одно ...


Написавши це, я зрозумів, що я перевірив категорії, а не терміни таксономії взагалі, тому вищезгадане не спрацює для 'forum'систематики, але я перегляну його, щоб він працював пізніше сьогодні ...
MikeSchinkel

Тому я оновив код, щоб вирішити проблему, про яку я згадував у попередньому коментарі.
MikeSchinkel

не вдається отримати цю роботу ... мені потрібно змінити правила переписування?
onetrickpony

@One Trick Pony - допоможе трохи більше діагностичної інформації. :) Що ти спробував? Що відбувається, коли ви вводите URL-адреси у свій браузер? Ви випадково називали свою таксономію, 'forums'а не 'forum'? Очікуєте, що URL-адреси, які посилаються на ці сторінки, зміняться (якщо так, не дивно, мій код не стосується друку URL-адрес, а лише маршрутизації URL-адрес.)
MikeSchinkel,

ні, я можу змінити URL-адреси (я думаю, що це функція term_link, яку мені потрібно підключити для цього). site/rootforum/працює, але site/rootforum/subforum/не (помилка 404) ...
onetrickpony

7

Просто, справді.

Крок 1. Зупиніть використовувати параметр перезапису взагалі. Ми збираємося власноруч переписувати.

'rewrite'=>false;

Крок 2: Встановіть правила багатослівної сторінки. Це змушує звичайні Сторінки мати свої власні правила, а не загальноприйняті внизу сторінки.

Крок 3: Створіть кілька правил перезапису для обробки ваших випадків використання.

Крок 4: Вручну змушуйте виконувати правила флеш. Найпростіший спосіб: перейти до налаштувань-> постійна посилання та натиснути кнопку збереження. Я вважаю за краще це над способом активації плагінів для власного використання, оскільки я можу змусити правила спалахувати, коли я змінюю речі.

Отже, код часу:

function test_init() {
    // create a new taxonomy
    register_taxonomy(
        'forum',
        'post',
        array(
            'query_var' => true,
            'public'=>true,
            'label'=>'Forum',
            'rewrite' => false,
        )
    );

    // force verbose rules.. this makes every Page have its own rule instead of being a 
    // catch-all, which we're going to use for the forum taxo instead
    global $wp_rewrite;
    $wp_rewrite->use_verbose_page_rules = true;

    // two rules to handle feeds
    add_rewrite_rule('(.+)/feed/(feed|rdf|rss|rss2|atom)/?$','index.php?forum=$matches[1]&feed=$matches[2]');
    add_rewrite_rule('(.+)/(feed|rdf|rss|rss2|atom)/?$','index.php?forum=$matches[1]&feed=$matches[2]');

    // one rule to handle paging of posts in the taxo
    add_rewrite_rule('(.+)/page/?([0-9]{1,})/?$','index.php?forum=$matches[1]&paged=$matches[2]');

    // one rule to show the forum taxo normally
    add_rewrite_rule('(.+)/?$', 'index.php?forum=$matches[1]');
}

add_action( 'init', 'test_init' );

Пам’ятайте, що після додавання цього коду потрібно активувати його, коли ви перебираєте правила постійної посилання (Збереження сторінки на Налаштування-> Постійні посилання)!

Після того, як ви виправили правила та зберегли їх до бази даних, тоді / що завгодно має перейти на ваш форум = незалежно від сторінки таксономії.

Переписувати правила насправді не так складно, якщо ви розумієте регулярні вирази. Я використовую цей код, щоб допомогти мені під час налагодження:

function test_foot() {
    global $wp_rewrite;
    echo '<pre>';
    var_dump($wp_rewrite->rules);
    echo '</pre>';
}
add_action('wp_footer','test_foot');

Таким чином, я бачу поточні правила з першого погляду на своїй сторінці. Просто пам’ятайте, що за будь-якою URL-адресою система починається у верхній частині правил і проходить через них, поки не знайде відповідну. Потім збіг використовується для перезапиту запиту в більш нормальний вигляд? Ключ = набір значень. Ці клавіші розбираються в те, що йде в об'єкт WP_Query. Простий.

Редагувати: Бічна примітка, цей метод, ймовірно, працює лише в тому випадку, якщо ваша звичайна спеціальна структура пошти починається з чогось, що не є catchall, наприклад% категорія% або щось подібне. Почати його потрібно зі статичного рядка чи числового, наприклад,% year%. Це потрібно для того, щоб він не потрапляв до вашої URL-адреси до того, як дійшов до ваших правил.


Якщо ви хочете полегшити налагодження своїх правил перезапису, я (знову ж таки) рекомендую свій плагін аналізатора переписати , який дозволяє випробувати правила та побачити змінні запиту на льоту.
Ян Фабрі

На жаль, поточна система перезапису URL-адрес змушує згладжувати всі потенційні шаблони URL-адрес у великому списку порівняно з притаманною структурою дерева дерев URL-шляхів. Поточна установка не може зручно відповідати масиву літералів, таких як категорії або назви форуму ; як ви знаєте, це змушує спочатку оцінити всі URL-адреси "Сторінки" . Зіставлення за сегментом шляху та узгодження кількома способами (масив літералів, категорій, тегів, податкових термінів, імен користувачів, типів публікацій, імен публікацій, зворотних викликів, гачок фільтрів та, нарешті, RegEx) покращить складність і стане простішим зрозуміти.
MikeSchinkel

Майк: Насправді це зовсім не простіше зрозуміти, бо я не маю першої підказки WTF, про яку ти там говориш. Ваші ідеї маршрутизації URL є заплутаними і складними, і, як ви, напевно, знаєте, я не згоден з ними. Плоский пошук має більше сенсу і є більш гнучким, ніж ви схильні надавати йому кредит. Більшість людей не хочуть, щоб у цих URL-адресах була вся така непотрібність, і майже нікому це не потрібно.
Отто

Дякую, але я думаю, я вже пробував це раніше ( wordpress.stackexchange.com/questions/9455/… )
onetrickpony

До щастя WordPress Відповіді тепер дозволяє людям , які роблять управління брак їх URL - адрес , щоб , нарешті, голос, і вони , здається, багато (100+). Але я поважаю, що ви, можливо, не зможете наслідувати мій приклад до повної реалізації. Я прогнозую, що після того, як підхід, який я підтримую, буде повністю реалізований у плагіні, і приблизно через 6-12 місяців він стане кращим способом для CMS-сайтів, що базуються на WordPress, маршрутизувати свої URL-адреси. Тож давайте продовжимо цю дискусію приблизно через 9 місяців.
MikeSchinkel

4

Ви не зможете зробити це за допомогою WP_Rewrite поодинці, оскільки він не може розрізнити термін "слизи" та "пост".

Ви також повинні підключитися до "запиту" і запобігти 404, встановивши var запит після замість таксономії.

Щось на зразок цього:

function fix_post_request( $request ) {
    $tax_qv = 'forum';
    $cpt_name = 'post';

    if ( !empty( $request[ $tax_qv ] ) ) {
        $slug = basename( $request[ $tax_qv ] );

        // if this would generate a 404
        if ( !get_term_by( 'slug', $slug, $tax_qv ) ) {
            // set the correct query vars
            $request[ 'name' ] = $slug;
            $request[ 'post_type' ] = $cpt_name;
            unset( $request[$tax_qv] );
        }
    }

    return $request;
}
add_filter( 'request', 'fix_post_request' );

Зауважте, що таксономія повинна бути визначена перед типом публікації.

Це був би вдалий час, щоб зауважити, що наявність таксономії та типу публікації з однаковою var запитом - це погана ідея.

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


Погодилися, що існування таксономії та типу публікації з однаковим варіантом запитів - це погана ідея, але це може означати, що люди, які мають систематику та тип публікації з тим самим іменем, є поганою ідеєю, що це не так. Якщо ви використовуєте те саме ім'я, то лише один з двох повинен мати змінну запиту.
MikeSchinkel

2

Я погляну на код плагіна котів верхнього рівня:

http://fortes.com/projects/wordpress/top-level-cats/

Ви можете легко адаптувати це, щоб він шукав ваш користувальницький таксономічний кулик, змінивши

$category_base = get_option('category_base');

по лінії 74 щось подібне:

$category_base = 'forums';

Можливо, працюю за категоріями, але це не для користувацьких таксономій (принаймні в wp 3.1) ... Мені вдалося змінити URL-адреси, але я отримую 404 помилки
onetrickpony

2

Я б запропонував переглянути плагін користувальницьких посилань . Зараз у мене немає часу на тестування, але це може допомогти у вашій ситуації.


це не так, він обробляє лише повідомлення, а не таксономії, і навіть якщо б це було, я повинен був би додати якийсь префікс раніше %forum%, чого саме я намагаюся уникати ...
onetrickpony

2

Оскільки я знайомий з вашим іншим питанням , я відповім на це на увазі.

Я взагалі не перевіряв це, але це може спрацювати, якщо ви виконаєте це один раз відразу після того, як зареєструєте всі необхідні вам пермаструктури.

class RRSwitcher {
  var $rules;
  function RRSwitcher(){
    add_filter( 'topic_rewrite_rules', array( $this, 'topics' ) );
    add_filter( 'rewrite_rules_array', array( $this, 'rules' ) );
  }
  function topics( $array ){
    $this->rules = $array;
    return array();
  }
  function rules( $array ){
    return array_merge( (array)$array, (array)$this->rules );
  }
}
$RRSwitcher = new RRSwitcher();
global $wp_rewrite;
$wp_rewrite->use_verbose_rules = true;
$wp_rewrite->flush_rules();

Що це робить: він видаляє правила перезапису, згенеровані з тематики, що постійно посилаються, із звичайного потоку масивів правил і повторно об'єднує їх у кінці масиву. Це запобігає втручанню цих правил у будь-які інші правила перезапису. Далі він змушує докладно переписати правила (кожна сторінка отримує індивідуальне правило з певним регулярним виразом). Це запобігає втручанню сторінок у правила вашої теми. Нарешті, він виконує жорсткий флеш (переконайтеся, що ваш .htaccess файл записаний, інакше це не працюватиме) та зберігає дуже великий дуже складний масив правил перезапису.


спробував, нічого не змінюється
onetrickpony


2

Не впевнений, чи це буде працювати для таксономій, але це працювало для користувацьких типів публікацій

Хоча він не оновлювався протягом 2 років, плагін нижче працював для мене: http://wordpress.org/plugins/remove-slug-from-custom-post-type/

FYI Я запускаю WP 3.9.1з типами WP1.5.7


2

Використовуйте косу рису як значення для кулі ... 100% працює

'rewrite' => array(
    'slug'       => '/', 
    'with_front' => FALSE
 ),

2
не зовсім, це призводить до того, що всі pageпосади становлять 404.
Майло,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.