Нужна помощь с add_rewrite_rule

55

РЕШЕНИЕ


Я пошел с обновлением 3 и получил его работать. То, что я неправильно понял, было то, что я полагал, что правило переписывания изменится designers/?designer=some-designer&bid=9на /designers/some-designer. Но это, конечно, наоборот.


Я провел некоторое исследование, но я не совсем понимаю, как использовать add_rewrite_rule () .

Этот пост довольно близок к тому, что мне нужно, но действительно ли мне нужно так много кода?

Моя текущая ссылка такова:
http://www.norwegianfashion.no/designers/?designer=Batlak-og-Selvig&bid=9.
Я хочу вот это
http://www.norwegianfashion.no/designers/Batlak-og-Selvig /

  1. Как я могу использовать add_rewrite_rule()?
  2. Мне нужно передать ID дизайнера (ставку). Как я могу сделать это при использовании правил re.write без отображения в URL?

Обновление 1

Я нашел это немного более объяснительным. Но это не работает

function add_rewrite_rules( $wp_rewrite ) 
{
    $new_rules = array(
        '('.$template_page_name.')/designers/(.*?)/?([0-9]{1,})/?$' => 'designers.php?designer='.
        $wp_rewrite->preg_index(1).'&bid='.
        $wp_rewrite->preg_index(2)
    );
       // Always add your rules to the top, to make sure your rules have priority
    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_rewrite_rules');

function query_vars($public_query_vars) {

    $public_query_vars[] = "designer";
    $public_query_vars[] = "bid";
    return $public_query_vars;
}
add_filter('query_vars', 'query_vars')

Обновление 2

Вот еще одно решение, которое я пробовал, которое предлагает Ян Фабри в другой ветке. Я положил это в мои functions.php, но это не имеет никакого эффекта.

add_action('generate_rewrite_rules', 'add_rewrite_rules');
add_filter('query_vars', 'query_vars');

/* Custom re-write rules for desigenrs
------------------------------------------------------------------------------*/
function add_rewrite_rules( $wp_rewrite ) 
{
    add_rewrite_rule('^designers/([^/]*)/([^/]*)$ /designers/?designer=$1&bid=$2 [L]', 'top');
    flush_rewrite_rules(false);
}


function query_vars($public_query_vars) {

    $public_query_vars[] = "designer";
    $public_query_vars[] = "bid";
    return $public_query_vars;
}

Обновление 3
Я также нашел несколько примеров здесь . Но это тоже не работает :(

add_filter('rewrite_rules_array','wp_insertMyRewriteRules');
add_filter('query_vars','wp_insertMyRewriteQueryVars');
add_filter('init','flushRules');  

// Remember to flush_rules() when adding rules
function flushRules(){
    global $wp_rewrite;
    $wp_rewrite->flush_rules();
}

// Adding a new rule
function wp_insertMyRewriteRules($rules)
{
    $newrules = array();
    $newrules['(designers)/(\d*)$'] = 'index.php?pagename=designers&designer=$matches[1]';
    return $newrules + $rules;
}

// Adding the bid var so that WP recognizes it
function wp_insertMyRewriteQueryVars($vars)
{
    array_push($vars, 'designer');
    return $vars;
}

Обновление 4 Я также пробовал это решение, но все равно не удалось.

add_filter('search_rewrite_rules', 'designers_createRewriteRules');

function designers_createRewriteRules($rewrite) {
global $wp_rewrite;

// add rewrite tokens
$designer_token = '%designers%';
$wp_rewrite->add_rewrite_tag($designer_token, '(.+)', 'designers=');

$bid_token = '%bid%';
$wp_rewrite->add_rewrite_tag($bid_token, '(.+)', 'bid=');

$keywords_structure = $wp_rewrite->root . "designers/$designer_token/$bid_token";
$keywords_rewrite = $wp_rewrite->generate_rewrite_rules($keywords_structure);

return ( $rewrite + $keywords_rewrite );

}

Обновление 5
Кажется, что мои правила перезаписи не добавляются. Выполнение следующих новых правил: print_r($wp_rewrite)не включает в себя мои новые правила переписывания.

Обновление 6
Я проверил решение Яна. Но URL не меняется :(

/* Initiation script for NF template
------------------------------------------------------------------------------*/   
add_action('after_setup_theme','norwegianfashion_setup');

if ( ! function_exists( 'norwegianfashion_setup' ) ):

  function norwegianfashion_setup() { 
    /* Here I do a lot of stuff */

    // SEO friendly URL for desigenrs
    add_action( 'init', 'wpa5413_init' );
    add_filter( 'query_vars', 'wpa5413_query_vars' );
  }

endif;


/* Custom re-write rules for desigenrs
------------------------------------------------------------------------------*/
function wpa5413_init()
{
    // Remember to flush the rules once manually after you added this code!
    add_rewrite_rule(
        'designers/([^/]+)/?',
        'index.php?pagename=designers&designer=$matches[1]',
        'top' );
}

function wpa5413_query_vars( $query_vars )
{
    $query_vars[] = 'designer';
    return $query_vars;
}

Я был бы очень признателен, если бы кто-нибудь смог помочь мне решить эту проблему.

Стивен
источник
Это выглядит очень похоже на первый вопрос, который вы задали здесь, и на который я дал ответ . С тех пор ситуация изменилась, поэтому мой ответ больше не действителен? Если вы не хотите использовать идентификатор дизайнера в своем URL-адресе, вам нужно будет самостоятельно преобразовать «slug» в идентификатор, WordPress не может сделать это за вас. Дизайнеры все еще являются внешним объектом?
Ян Фабри
@Jan Fabry Да, я обнаружил это после того, как опубликовал это (я забыл). Теперь я понимаю ваше предложение лучше. Смотрите мой обновленный код здесь. Мои дизайнеры все еще являются записями в пользовательской БД. Можно ли использовать POST insteed или GET для прохождения bid?
Стивен
Использование запроса POST не помешает, если я скопирую ссылку и отправлю ее кому-то еще. Является ли проблемой сделать слаг уникальным и выполнить поиск данных оттуда?
Ян Фабри
@ Ян Фабри: Что ты имеешь в виду slug? `Получить данные Designer гораздо проще bid, чем использоватьdesigner
Стивен

Ответы:

87

Некоторый фон на правилах переписывания

Система WP Rewrite выглядит сложной, но на самом деле не так сложно понять, как она работает. Он используется для разбора симпатичных URL ( /designers/), как если бы они были не симпатичными ( /index.php?pagename=designers). Основная идея заключается в том, что у вас есть список правил перезаписи , регулярных выражений, которые могут соответствовать входящим URL-адресам, и переписать их в другие URL-адреса, в основном в форме index.phpс некоторыми переменными запроса. Эти переменные устанавливаются в части регулярного выражения, которые соответствуют URL. Правила оцениваются сверху вниз, поэтому, если два правила могут совпадать, первое «выигрывает».

Эти правила перезаписи сохраняются в базе данных посредством вызова flush_rewrite_rules(), но поскольку создание и запись этих правил является дорогостоящей операцией, вам не следует делать это для каждого init. Вместо этого вы делаете это только при изменении правил: возможно, при активации плагина (используя register_activation_hook()) или вручную, посетив страницу настроек Постоянных ссылок ( потому что это трудно сделать автоматически при активации темы ). Если вы не сбросите правила, вызов не add_rewrite_rule()имеет никакого эффекта. Нет проблем звонить add_rewrite_rule()на каждого init, даже после того, как вы сбросили правила.

Есть много способов добавить ваши правила перезаписи, и если вы хотите добавить только одно правило, вы можете сделать это с помощью add_rewrite_rule(). Поскольку правила для сообщений, страниц, таксономии ... результат в нескольких правилах, они созданы с функциями высокого уровня как add_rewrite_tag(), add_permastruct()... Но они не нужны для простого случая мы имеем здесь.

Есть также несколько фильтров, так что вы также можете добавлять свои правила, используя кнопки generate_rewrite_rulesили generate_rewrite_rules_array. Они дают вам очень подробный контроль над полными правилами, но, опять же, этого add_rewrite_rule()достаточно, если вы просто хотите добавить одно правило.

Я создал небольшой плагин, который позволяет вам анализировать текущие правила переписывания , и (конечно) я рекомендую вам использовать его, когда вы пытаетесь что-то изменить.

Получение дополнительной информации с URL

Давайте продолжим на примере, который вы дали. У вас есть дизайнерский бренд Batlak og Selvigс цифровым идентификатором ( bid) 9. Вы не хотите этот идентификатор в URL, а только имя. Мы называем URL-дружественный вариант названия (без пробелов и специальных символов) на слизняка : Batlak-og-Selvig.

В общем, URL должен содержать всю информацию, чтобы идентифицировать контент, который вы хотите показать на странице. Вы можете использовать куки или POST-запросы для хранения фактического идентификатора дизайнера, который вы хотите отобразить, но он сломается, если кто-то поделится ссылкой, отправив ее по почте, Facebook, Twitter или просто прочитав ее вслух по телефону. Если вы не хотите использовать числовой идентификатор в своем URL-адресе, убедитесь, что слаг является уникальным: затем сначала выполните поиск идентификатора на основе слага и продолжите, как вы делали раньше.

Итак, что мы узнали сейчас, так это то, что мы хотим добавить правило перезаписи для шаблона « /designers/после чего-нибудь до следующего /» и сохранить это «что-нибудь» в designer_slugпеременной запроса. В вашем случае я считаю, что вы также хотите использовать страницу со слагом designersв качестве общего содержимого страницы, поэтому мы расскажем об этом и WordPress.

add_action( 'init', 'wpa5413_init' );
function wpa5413_init()
{
    // Remember to flush the rules once manually after you added this code!
    add_rewrite_rule(
        // The regex to match the incoming URL
        'designers/([^/]+)/?',
        // The resulting internal URL: `index.php` because we still use WordPress
        // `pagename` because we use this WordPress page
        // `designer_slug` because we assign the first captured regex part to this variable
        'index.php?pagename=designers&designer_slug=$matches[1]',
        // This is a rather specific URL, so we add it to the top of the list
        // Otherwise, the "catch-all" rules at the bottom (for pages and attachments) will "win"
        'top' );
}

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

add_filter( 'query_vars', 'wpa5413_query_vars' );
function wpa5413_query_vars( $query_vars )
{
    $query_vars[] = 'designer_slug';
    return $query_vars;
}

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

Обсуждение чата

Мы выяснили последние вопросы по этому вопросу в чате . В конце концов, Стивен использовал generate_rewrite_rulesзацепку, потому что эта add_rewrite_rule()функция, похоже, не работала на него.

Ян Фабри
источник
2
@Steven: фрагмент pagenameстраницы WordPress, которую вы хотите отобразить (запись в базе данных). Затем эта страница может указать, что она хочет использовать designers.phpфайл шаблона в административной области WP. Таким образом, вы указываете на слаг страницы, а не на имя шаблона, поскольку один и тот же шаблон может использоваться для нескольких страниц: в этом случае WordPress не знает, что вы хотите сделать.
Ян Фабри
1
@ Стивен: Я думаю, вы слишком усложняете то, как вы устанавливаете крючки. Удалить add_rewrite_rules()функцию и вызвать add_filter()/add_action()напрямую. Если это в файле темы, удалите flush_rewrite_rules()и просто перейдите на страницу настроек постоянных ссылок, чтобы очистить правила (или добавьте их wpse5413_init()и удалите их позже). И мой плагин отображает текущие правила перезаписи. Помните, что это только меняет способ обработки входящих URL-адресов, а не то, как ваш код будет записывать URL-адреса в HTML.
Ян Фабри
1
@ Steven: Я не думаю, что вам даже нужно нажимать кнопку сохранения, просто открыв страницу с постоянными ссылками, вы также очистите ее. И опять же, это только добавит возможность WordPress принимать /designers/designer-slug/URL-адреса, вам нужно изменить места, где вы пишете эти URL-адреса в своем HTML-коде. Проверьте это, перейдя к /designers/Batlak-og-Selvig/себе, если это работает, найдите все места, которые генерируют эти URL-адреса, и измените их, чтобы использовать новую структуру.
Ян Фабри
1
Ах, теперь я думаю, что начинаю удивляться. Я думал, что правила перезаписи изменят способ отображения URL в поле URL браузера. Но это значит, что мне нужно вывести URL-адрес, www.mysite.com/batlat-og-selvig/9а затем его «перевести» на/?designer=Batlak-og-Selvig&bid=9
Стивен
1
@ Steven: Да, действительно: правила перезаписи обрабатывают входящие ссылки и (только в некоторых выбранных случаях) не влияют на сгенерированные ссылки в вашем коде.
Ян Фабри