Динамические URL-адреса в WordPress

Фон

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

  • каталог.
  • курс. Этот тип сообщения содержит заголовок, номер курса и описание курса.
  • раздел. Этот тип сообщения содержит стоимость, дату и время начала и окончания и т. Д. Раздел - это экземпляр курса; например, может быть два раздела «Рисование для начинающих», один в четверг утром и один в понедельник вечером, и преподаются двумя разными преподавателями.

Между курсом и разделом существует связь "один ко многим". При просмотре раздела отображается название родительского курса, номер курса и описание курса. Он также отображает стоимость этого раздела, даты и время начала и окончания и т. Д.

Текущий URL-адрес для раздела следующий:

http://website.org/section/section-slug/

Я бы хотел, чтобы это было так:

http://website.org/class/spring-2019/drawing-for-beginners/01/

... где "класс" - это "виртуальная" папка / синтетический префикс ... где "весна-2019" соответствует настраиваемому типу публикации "каталог" ... где "рисунок для начинающих" соответствует ярлыку для пользовательский тип сообщения родительского "курса" ... где "01" соответствует разделу курса.

WordPress должен отображать тип сообщения раздела, соответствующий этим критериям.

Исследование

Я довольно много читал о Rewrite API и Endpoints API. Лучшая статья, которую я смог найти по теме, наиболее близкой к тому, что я пытаюсь достичь, - это эта . К сожалению, пример кода на странице у меня не сработал, что привело к «ошибке слишком большого количества перенаправлений». При желании я могу предоставить более подробную информацию о том, какая именно часть не сработала. Я также прочитал эту статью о создании плагинов для WordPress но он не охватывает динамический поиск.

Чего я пытаюсь достичь

http://website.org/class/spring-2019/drawing-for-beginners/01/

Когда виртуальный URL-адрес предоставляется WordPress, мне нужно, чтобы система выполнила запрос для поиска раздела с номером «01», который принадлежит каталогу «весна-2019» и чей родительский курс имеет ярлык «рисунок- для начинающих." Этот запрос не является проблемой, это все хуки, которые необходимо вызвать для выполнения этого кода и возврата правильного шаблона (для страницы раздела). Я не уверен, нужно ли мне создавать конечную точку или мне просто удастся добавить правила перезаписи.

Может кто-нибудь дать совет?

--

В качестве «бонуса» я тоже пытаюсь добиться этого:

http://website.org/class/spring-2019/drawing-for-beginners/01/faculty_name

... где "faculty_name" является динамическим и является именем человека, преподающего этот раздел (и соответствует настраиваемому типу сообщения "faculty").

http://website.org/class/spring-2019/drawing-for-beginners/01/gallery

... где "галерея" - статическое имя, показывающее настраиваемый тип сообщения галереи.


person Saul    schedule 04.03.2019    source источник


Ответы (2)


После долгих исследований я нашел ответ на свой вопрос. Вот оно.

Вот как создать действительно динамические URL-адреса / ярлыки в WordPress. URL-адреса не соответствуют странице. Вместо этого части слага используются для поиска идентификатора сообщения, а затем соответствующего отображения этого сообщения.

Шаг 1. Добавьте правило перезаписи

function pce_rewrite_rules ( ) {
  add_rewrite_rule ( '^class/([^/]*)/([^/]*)/([^/]*)/?', 'index.php?post_type=section&catalog_name=$matches[1]&course_name=$matches[2]&section_no=$matches[3]','top' ) ;
add_action ( 'init', 'pce_rewrite_rules', 10, 0 ) ;

Шаг 2. Зарегистрируйте переменные запроса

function pce_register_query_vars ( $vars ) {
    $vars[] = 'course_name';
    $vars[] = 'catalog_name';
    $vars[] = 'section_no';

    return $vars;
}
add_filter ( 'query_vars', 'pce_register_query_vars' );

Шаг 3. Измените запрос WP

Используйте pre_get_posts для изменения основного запроса. Но вы должны принудительно указать некоторые переменные в запросе, чтобы WordPress загрузил нужный вам шаблон. Чтобы найти переменные, которые мне нужно было установить вручную, я использовал плагин WP (Query Monitor) для проверки содержимого запроса WP и использовал var_dump для типа сообщения, которое я хотел «скопировать».

function pce_dynamic_section_lookup ( $wp ) {

    if ( is_admin() || ! $wp->is_main_query() ){
        return;
    }

    if ( $wp->is_main_query() ) {
        // Only defined if we're looking at a "fake" URL.
        // Example: http://pce.local/class/spring-2019/handmade-books/01/
        if ( get_query_var ('course_name' ) ) {
            // These are some of the variables I needed to set manually.
            $wp->query_vars['post_type'] = 'section' ;
            $wp->query_vars['is_single'] = true ;
            $wp->query_vars['is_singular'] = true;
            $wp->query_vars['is_archive'] = false;

            $course_name = get_query_var ('course_name' ) ;
            $catalog_name = get_query_var ('catalog_name' ) ;
            $section_no = get_query_var ('section_no' ) ;

            // More code is here to look up the post ID I need.

            // Set the post ID here. This makes the magic happen.
            $wp->query_vars['p'] = $post_id ;

            // This also makes the magic happen. It forces the template I need to be selected.
            $wp->is_single = true ;
            $wp->is_singular = true ;
            $wp->is_archive = false ;
            $wp->is_post_type_archive = false ;
        }
    }
}
add_action ( 'pre_get_posts', 'pce_dynamic_section_lookup', 0, 2 ) ;

У меня был пост с этим исходным URL:

http://pce.local/section/handmade-books-01/

И теперь я могу загрузить его по этому URL-адресу (и он загружает его, а не пересылает):

http://pce.local/class/spring-2019/handmade-books/01/

Мне нужно было это сделать, потому что в будущие каталоги будут добавлены несколько разделов, и я хотел, чтобы URL-адреса были удобными. Летом, если будет предложено занятие, будет ...

http://pce.local/class/summer-2019/handmade-books/01/

Вместо того...

http: //pce.local/section/handmade-books-01-2/ < / а>

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

person Saul    schedule 05.03.2019

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

function add_rewrite_rules( $wp_rewrite )
{

    $section_rules = array(
        'class/(.+?)/?$' => 'index.php?post_type=post&name='. $wp_rewrite->preg_index(1),
    );

    $wp_rewrite->rules = $section_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_rewrite_rules'); 

function change_section_links($post_link, $id=0){

    $courses = new WP_Query( array(
        'post_type' => 'course',
        'post__in' => get_post_meta( $catalog_id, '_course', true ),
    ) );

    if ( $courses-> have_posts() ) { while ( $courses->have_posts() ) {
          $courses->the_post();
          $catalog_name = get_the_title();  
        }

    $sections = new WP_Query( array(
        'post_type' => 'section',
        'post__in' => get_post_meta( $course_id, '_section', true ),
    ) );

        if ( $sections-> have_posts() ) { while ( $sections->have_posts() ) {
                  $sections->the_post();
                  $course_name = get_the_title();  
            }

    $post = get_post($id);

    if( is_object($post) && $post->post_type == 'section'){
        return home_url('/class/'. $catalog_name. '/'. $course_name. '/'. $post->post_name.'/');
    }

    return $post_link;
}
add_filter('post_link', 'change_section_links', 1, 3);

Я надеюсь, что это поможет вам. Если нет, расскажи, как у тебя завязались отношения.

person erko95    schedule 04.03.2019
comment
Отвечая на ваш первый вопрос, вы правы в своей новой формулировке URL. Что касается того, как я могу отобразить URL-адрес 1 курса, в данном каталоге есть только 1 раздел с одним номером раздела для курса. Например, в весеннем каталоге всего один Рисунок для начинающих (раздел 01). (Также может быть раздел 02 «Рисование для начинающих».) Это ответ на ваш вопрос? - person Saul; 04.03.2019
comment
Если детали в вашем слаге не являются заголовком сообщения, вы можете вызвать другую функцию. Если вы используете ACF, это будет поле .. - person erko95; 04.03.2019
comment
Спасибо за размещение кода. Похоже, этот код пытается изменить постоянную ссылку. Как ни странно, это не совсем то, что мне нужно для выполнения. Я ищу альтернативный URL-адрес или псевдоним для каждой страницы. И этот псевдоним должен отображать страницу, а не перенаправлять на исходную страницу / слаг. Вы спросили, как я создал отношения между сообщениями. Я использую коммерческий плагин под названием Toolset Types (toolset.com). Он позволяет создавать отношения между сообщениями (один к одному, один ко многим, многие ко многим). - person Saul; 05.03.2019
comment
В итоге я нашел решение. Скоро выложу для потомков. - person Saul; 05.03.2019