Удалите краткий заголовок таксономии из пользовательской иерархической постоянной ссылки таксономии

Я создал таксономию 'форума', с помощью этих правил:

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 (), он работает, но это вызывает проблемы с постоянными ссылками типа сообщения, связанного с этой таксономией

21
24.02.2011, 21:53
8 ответов

ОБНОВЛЕНИЕ

Начиная с записи этого ядра WordPress добавил 'do_parse_request' рычаг, который позволяет маршрутизации URL быть обработанной изящно и без потребности расшириться WP класс. Я затронул тему, всестороннюю в моем атлантском разговоре WordCamp 2014 года, наделенном правом "Жесткая Маршрутизация URL"; слайды доступны в ссылке.

ИСХОДНЫЙ ОТВЕТ

Дизайн URL был важен, чтобы быть в течение хорошо более чем десятилетия; я даже записал блог об этом несколько лет назад. И в то время как WordPress является суммой, блестящий бит программного обеспечения, к сожалению, это - URL, переписывают систему, только за исключением глупого (по моему скромному мнению, конечно.:) Так или иначе, довольный видеть, что люди заботятся о дизайне URL!

Ответ, который я собираюсь предоставить, является плагином, который я называю WP_Extended это - подтверждение концепции этого предложения по Trac (Обратите внимание, что предложение запустилось как одна вещь и развитый из другого, таким образом, необходимо считать всю вещь видеть, куда это направилось.)

В основном идея состоит в том, чтобы разделить на подклассы WP класс, переопределите parse_request() метод, и затем присваивает глобальное $wp переменная с экземпляром подкласса. Затем в parse_request() Вы на самом деле осматриваете путь сегментом контура вместо того, чтобы использовать список регулярных выражений, которые должны соответствовать URL в их полноте.

Таким образом для утверждения этого явно эта техника вставляет логику перед parse_request() который проверяет на соответствия URL-to-RegEx и вместо этого сначала ищет соответствия термина таксономии, но это ТОЛЬКО заменяет parse_request() и оставляет весь отдых системы маршрутизации URL WordPress неповрежденным включая и особенно использование $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();

P.S. ПРОТЕСТ № 1

Хотя для данного сайта я думаю, что эта техника работает блестяще, но эта техника никогда не должна использоваться, чтобы плагин был распределен на WordPress.org для других для использования. Если это в ядре пакета программного обеспечения на основе WordPress затем, это могло бы быть хорошо. Иначе эта техника должна быть ограничена улучшением маршрутизации URL для определенного сайта.

Почему? Поскольку только один плагин может использовать эту технику. Если два плагина попытаются использовать его, то они будут конфликтовать друг с другом.

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

ПРОТЕСТ № 2

Я записал это для переопределения parse_request() который является очень большой функцией, и довольно возможно, что я пропустил свойство или два из глобальных $wp возразите, что я должен был установить.. Таким образом, если что-то действует сообщенный мне wonky, и я буду рад исследовать его и пересмотреть ответ в случае необходимости.

Так или иначе...

11
19.02.2020, 21:56
  • 1
    После записи этого я понял, что протестировал на категории вместо для условий таксономии в целом, таким образом, вышеупомянутое не будет работать на 'forum' таксономия однако, я пересмотрю его для работы позже сегодня... @don de lion –  MikeSchinkel 23.02.2011, 14:58
  • 2
    Таким образом, я обновил код для рассмотрения проблемы, я упоминаю в предшествующем комментарии. –  MikeSchinkel 24.02.2011, 01:55
  • 3
    не может получить эту работу... я должен изменить переписать правила? –  onetrickpony 24.02.2011, 12:51
  • 4
    @One - Немного больше диагностической информации помогло бы :) 3X, Что Вы пробовали? Что происходит, когда Вы вводите URL в свой браузер? Вы на шанс называете свою таксономию 'forums' вместо 'forum'? Вы ожидаете URL, которые связываются с этими страницами для изменения (если да, неудивительный, мой код не обращается к печати URL, только маршрутизации URL.) –  MikeSchinkel 24.02.2011, 21:38
  • 5
    не, я могу изменить URL (я думаю, что это - функция term_link, в которую я должен сцепиться для этого). site/rootforum/ работы, но site/rootforum/subforum/ не делает (404 ошибки)... –  onetrickpony 24.02.2011, 21:56

Простой, действительно.

Шаг 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' );

Помните, что после добавления этого кода, у Вас должен быть он активный, когда Вы идете, сбрасывают правила постоянной ссылки (путем Сохранения страницы на Настройках-> Постоянные ссылки)!

После того, как Вы сбросили правила и сохранили к базе данных, затем / независимо от того, что должно перейти к Вашей forum=whatever странице таксономии.

Перепишите правила, действительно не являются настолько трудными, если Вы понимаете регулярные выражения. Я использую этот код для помощи мне при отладке их:

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

Таким образом, я вижу текущие правила сразу на моей странице. Просто помните, что, учитывая любой URL, система запускается наверху правил и понижается через них, пока это не находит тот, который соответствует. Соответствие затем используется для перезаписи запроса в более нормальный взгляд? key=value установлен. Те ключи анализируются в то, что входит в объект WP_Query. Простой.

Править: Примечание стороны, этот метод будет, вероятно, только работать, если Ваша нормальная пользовательская структура сообщения запустится с чего-то, что не является вместилищем, как %category % или некоторая такая подобная вещь. Необходимо запустить его со статической строки или числового, как %year %. Это должно предотвратить его, ловя Ваш URL, прежде чем это доберется до Ваших правил.

7
19.02.2020, 21:56
  • 1
    , Если Вы хотите более легкую отладку Вашего переписывать правила, я (снова) рекомендую моему переписывать плагин анализатора, который позволяет Вам испытывать правила и видеть переменные запроса на лету. –  Jan Fabry 24.02.2011, 14:28
  • 2
    К сожалению, текущий URL переписывает системные силы выравнивание всех потенциальных шаблонов URL в большой список по сравнению со следующим свойственная древовидная структура путей URL. Текущая установка не может удобно соответствовать массиву литералов, таких как категории или имена форума; поскольку Вы знаете, что это вынуждает все URL "Страницы" быть оцененными сначала. Соответствование сегментом контура и соответствием несколькими способами (массив литералов, категорий, тегов, налоговых условий, имен пользователей, типов сообщения, названий сообщения, обратных вызовов, рычагов фильтра и наконец RegEx) масштабировалось бы для сложности лучше и будет легче понять. –  MikeSchinkel 25.02.2011, 06:42
  • 3
    Mike: На самом деле это не легче понять вообще, потому что у меня нет первой подсказки WTF, о котором Вы говорите там. Ваши идеи маршрутизации URL сбивают с толку и являются трудными, и как Вы, вероятно, знаете, я не соглашаюсь с ними. Плоский поиск имеет больше смысла и более гибок, чем Вы склонны давать ему кредит на. Большинство людей не хочет всей этой бесполезной сложности в своих URL, и почти никому не нужна она также. –  Otto 25.02.2011, 19:03
  • 4
    Спасибо, но я думаю, что уже попробовал это прежде (wordpress.stackexchange.com/questions/9455 / …) –  onetrickpony 25.02.2011, 21:00
  • 5
    К счастью, Ответы WordPress теперь позволяют людям, которые действительно хотят, чтобы управление их URL наконец имело речь, и они, кажется, многие (100 +). Но я уважаю это, Вы не можете следовать моему примеру до полного внедрения. Я предсказываю, что, после того как подход, который я защищаю, полностью реализован в плагине и приблизительно после 6-12 месяцев, это станет предпочтительным путем к основанным на WordPress сайтам CMS для маршрутизации их URL. Так позволяет резюме эти дебаты приблизительно за 9 месяцев. –  MikeSchinkel 01.03.2011, 19:38

Вы не сможете сделать это использование один только 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 запроса является Плохой Идеей.

Кроме того, Вы не сможете достигнуть сообщений, которые имеют тот же краткий заголовок как одно из условий.

4
19.02.2020, 21:56
  • 1
    Согласованный то, что наличие таксономии и типа сообщения с тем же var запроса является Плохой Идеей, но это могло бы подразумевать людям, имеющим таксономию и тип сообщения с тем же именем, является плохой идеей, которая не имеет место. При использовании того же имени затем только один из этих двух должен иметь var запроса. –  MikeSchinkel 20.02.2011, 19:51

Я смотрел бы на код высокоуровневого плагина кошек:

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

Вы могли легко адаптировать это так, это ищет Ваш пользовательский краткий заголовок таксономии путем изменения

$category_base = get_option('category_base');

на строке 74 к чему-то как подобный:

$category_base = 'forums';
2
19.02.2020, 21:56
  • 1
    Мог бы работать на категории, но это не делает для пользовательского taxonomies (по крайней мере, в wp 3.1)... Мне удалось изменить URL, но я получаю 404 ошибки –  onetrickpony 15.02.2011, 21:29

Я предложил бы смотреть на Пользовательский плагин Постоянных ссылок Сообщения. У меня нет времени для тестирования прямо сейчас, но оно может помочь с ситуацией.

2
19.02.2020, 21:56
  • 1
    , который это не делает, это только, обрабатывает сообщения, не taxonomies, и даже если бы это было бы, то я должен был бы добавить некоторый префикс прежде %forum%, который является точно, чего я стараюсь избегать... –  onetrickpony 18.02.2011, 00:14

Так как я - знакомое с Вашим другим вопросом, я отвечу этим в памяти.

Я не протестировал это вообще, но это могло бы работать при выполнении этого однажды прямо после регистрации всего permastructs, который Вы хотите.:

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 файл перезаписываем, иначе это не будет работать), и сохраняет очень большой очень сложный массив, переписывают правила.

2
19.02.2020, 21:56
  • 1
    попробовал его, ничто не изменяется –  onetrickpony 18.02.2011, 01:21

Существует плагин для этого.

Это удаляет краткий заголовок типа путем добавления определенного правила для каждой пользовательской полосы набора сообщения.

2
19.02.2020, 21:56

Не уверенный, если это будет работать на taxonomies, но он работал на пользовательские типы сообщения

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

К вашему сведению я выполняю WP 3.9.1 с типами WP 1.5.7

2
19.02.2020, 21:56

Теги

Похожие вопросы