Удаление родительских страниц из постоянных ссылок

23 мар. 2015 г., 15:25:39
Просмотры: 14.4K
Голосов: 8

Подобные вопросы задавались ранее, но подходящего ответа не нашлось.

У меня есть: site.com/родительская-страница/дочерняя-страница а хотелось бы: site.com/дочерняя-страница

Мне нужно иметь исключительно постоянные ссылки с глубиной 1, не используя кастомное меню, но сохраняя иерархию страниц в админке и атрибуты родителя/порядка в настройках страниц.

Решение должно работать автоматически, без ручного изменения каждой ссылки через плагин "Custom Permalinks".

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

Вот этот код, который, возможно, можно адаптировать для страниц?

add_filter( 'post_link', 'remove_parent_cats_from_link', 10, 3 );
function remove_parent_cats_from_link( $permalink, $post, $leavename ) {
    $cats = get_the_category( $post->ID );
    if ( $cats ) {
        // Убедимся, что используем ту же начальную категорию, что и генератор ссылок
        usort( $cats, '_usort_terms_by_ID' ); // сортировка по ID
        $category = $cats[0]->slug;
        if ( $parent = $cats[0]->parent ) {
            // Если есть родительские категории, соберем их и заменим в ссылке
            $parentcats = get_category_parents( $parent, false, '/', true );
            // str_replace() не лучший вариант при возможных дубликатах:
            // example.com/люксембург/люксембург/ превратится в example.com/
            // Но если такого не ожидается, должно работать
            $permalink = str_replace( $parentcats, '', $permalink );
        }
    }
    return $permalink;
}
0
Все ответы на вопрос 2
1

Быстрый поиск показывает еще одну тему на StackExchange по этому вопросу, где использовался следующий код для очистки постоянных ссылок от родительских/предковых элементов:

function wpse_101072_flatten_hierarchies( $post_link, $post ) {
    if ( 'page' != $post->post_type )
        return $post_link;

    $uri = '';
    foreach ( $post->ancestors as $parent ) {
        $uri = get_post( $parent )->post_name . "/" . $uri;
    }

    return str_replace( $uri, '', $post_link );
}
add_filter( 'post_type_link', 'wpse_101072_flatten_hierarchies', 10, 2 );

Вы можете ознакомиться с обсуждением здесь: Удаление родительского слага из URL в пользовательском типе записи

23 мар. 2015 г. 15:59:42
Комментарии

Это забавно работает :) Те записи, у которых есть родитель, всё ещё отображаются с родителями, но те, у кого родителя нет, ведут на 404 :D И ещё там говорится о пользовательских типах записей, а Себастьян в конце задаёт тот же вопрос, что и я - как заставить это работать для страниц, на что не было ответа. Так что я всё ещё надеюсь, что ответ найдётся.

Sofian Sofian
23 мар. 2015 г. 16:52:22
0

Кратко: Установите бесплатный плагин "Permalinks Customizer". Настройте "PostTypes Settings" для страниц на '%postname%', а затем отредактируйте страницы, чтобы изменить соответствующие постоянные ссылки. Я протестировал это с иерархическими и неиерархическими страницами, и это работает без проблем.


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

Автор вопроса совершенно прав; предложенный Nicu ответ не работает, потому что эта строка строит URI из исходной иерархии.

$uri = get_post( $parent )->post_name . "/" . $uri;

Я (безуспешно) работал над фильтром, который соответствовал бы требованиям автора вопроса. Предлагаю его здесь на случай, если он может быть полезен кому-то еще. Для справки, все мои тесты проводились с настройкой постоянных ссылок "Имя записи", и каждый раз при изменении фильтра я обновлял страницу постоянных ссылок. Я создал четыре страницы: Ancestry (родительская), Parents (родитель = 'Ancestry'), Children (родитель = 'Parents') и Transportation (без родителя).

Я обнаружил, что создание URI — это простая часть, или, по крайней мере, кажется таковой. Этот вариант (в functions.php) работает:

function wpse_182006_pages_permalink( $link, $post_id) {

    // получаем post_type и проверяем
    $posttype = get_post_field( 'post_type', $post_id, 'display' );
    if ($posttype !== 'page'){
        return link;
    }

    // строим URI из слага
    $slugname = get_post_field( 'post_name', $post_id, 'display' );
    $slugname = $slugname."/";
    $link = home_url($slugname);
    return $link;

}

add_filter( 'page_link', 'wpse_182006_pages_permalink', 10, 3 );

Страницы "Ancestry" и "Transportation" открываются нормально.
Страницы "Parents" и "Children" (каждая с родительской страницей) открываются с ошибкой 404.
Если посмотреть на запрос (см. ниже), видно, что ошибка 404 возникает потому, что WordPress интерпретирует "страницу" как "запись", и такой записи не существует. Обратите внимание, что ID записи не используется в неудачных запросах. Возможно, это ключ к успешной перезаписи, но это было за пределами моих возможностей.

Для справки, вот детали запроса для "Ancestry":
Совпавший запрос = 'pagename=ancestory&page='
Совпавшее правило = '(.?.+?)(?:/([0-9]+))?/?$'
Основной запрос = SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND (wp_posts.ID = '46') AND wp_posts.post_type = 'page' ORDER BY wp_posts.post_date DESC

Для сравнения, вот детали запроса для "Children":
Совпавший запрос = 'name=children&page='
Совпавшее правило = '([^/]+)(?:/([0-9]+))?/?$'
Основной запрос = SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = 'parents' AND wp_posts.post_type = 'post' ORDER BY wp_posts.post_date DESC


К слову, при таком способе настройки постоянная ссылка становится нередактируемой. До:
Изображение до изменения

После:
Изображение после изменения

4 сент. 2018 г. 08:02:02