Вопрос или проблема
У меня есть кастомная страница поиска для типа записей (‘program’). Для этого поиска можно настроить 4 параметра: ‘word_search’, ‘archived’, ‘category’ и ‘operating_system’.
Мы можем искать по ‘word_search’ и ‘category’, или ‘operating_system’ и ‘archived’, или только ‘operating_system’ или любой их комбинации. Это генерирует URL типа:
- http://example.com/program/?word_search=$1&operating_system=$2&category=$3&archived=$4
Если параметр не используется для фильтра, он не будет присутствовать в финальном URL. Например, если мы не используем параметры word_search и archived, URL будет выглядеть так:
- http://example.com/program/?operating_system=$1&category=$2
Это работает отлично. Теперь я хотел бы применить правило переписывания, чтобы получать URL вида:
- http://example.com/program/w/$1/os/$2/cat/$3/arch/$4
И все возможные комбинации, учитывая, что некоторые параметры могут не использоваться. То есть:
- http://example.com/program/w/$1/
- http://example.com/program/os/$1/cat/$2/
- http://example.com/program/w/$1/os/$2/arch/$3
- … и так далее
Для этого я могу добавить правило переписывания (add_rewrite_rules), но я не могу понять, как создать ‘универсальный’ URL. Если бы у меня был только параметр ‘category’, я мог бы создать правило переписывания, например:
array('programs/cat/([^/]+)/?' => 'index.php?post_type=program&category=$matches[1]');
Но когда нужно комбинировать 2 или более параметра, это становится сложнее, потому что нужно создавать строку для каждой комбинации. Это значит:
array('programs/cat/([^/]+)/arc/([^/]+)?' => 'index.php?post_type=program&category=$matches[1]&archived=$matches[2]');
array('programs/cat/([^/]+)/os/([^/]+)?' => 'index.php?post_type=program&category=$matches[1]&os=$matches[2]');
array('programs/cat/([^/]+)/w/([^/]+)?' => 'index.php?post_type=program&category=$matches[1]&word_search=$matches[2]');
И то же самое для остальных комбинаций. Что я мог бы сделать, чтобы избежать написания всех комбинаций правил переписывания?
Спасибо!
Ну, я объясняю здесь, что я в итоге сделал, чтобы разобраться с этим. Я не нашел подходящего способа, но:
-
Я создал функцию переписывания, которая извлекает все параметры и генерирует конечный URL с параметрами, упорядоченными определенным образом.
function sc_change_programs_search_url_rewrite() { if(get_query_var( 'post_type' ) == 'program') { if(isset($_GET['word_search']) || isset($_GET['os']) || isset($_GET['category']) || isset($_GET['archived'])) { $available_query_vars = array( 'word_search' => 'p', 'sistema_operatiu' => 'so', 'category' => 'cat', 'archived' => 'archived' ); $params_query = ''; foreach($available_query_vars as $query_var => $key) { if (get_query_var( $query_var )) { if($query_var == 'archived') { $params_query .= $key . "https://wordpress.stackexchange.com/"; } else { $params_query .= $key . "https://wordpress.stackexchange.com/" . get_query_var( $query_var ) . "https://wordpress.stackexchange.com/"; } } } if( ! empty( $params_query ) ) { wp_redirect( home_url( "/programs/" ) . $params_query ); } } } }
-
Я создал все правила переписывания (учитывая, что порядок может быть только один, правил для реализации меньше, но их все равно довольно много):
$aNewRules = array( 'programes/p/([^/]+)/so/([^/]+)/cat/([^/]+)/arxivats/?' => 'index.php?post_type=programa&cerca=$matches[1]&sistema_operatiu=$matches[2]&categoria_programa=$matches[3]&arxivat=1', 'programes/p/([^/]+)/so/([^/]+)/cat/([^/]+)/?' => 'index.php?post_type=programa&cerca=$matches[1]&sistema_operatiu=$matches[2]&categoria_programa=$matches[3]&arxivat=0', 'programes/p/([^/]+)/so/([^/]+)/arxivats/?' => 'index.php?post_type=programa&cerca=$matches[1]&sistema_operatiu=$matches[2]&arxivat=1', 'programes/p/([^/]+)/cat/([^/]+)/arxivats/?' => 'index.php?post_type=programa&cerca=$matches[1]&categoria_programa=$matches[2]&arxivat=1', 'programes/p/([^/]+)/so/([^/]+)/?' => 'index.php?post_type=programa&cerca=$matches[1]&sistema_operatiu=$matches[2]&arxivat=0', 'programes/p/([^/]+)/cat/([^/]+)/?' => 'index.php?post_type=programa&cerca=$matches[1]&categoria_programa=$matches[2]&arxivat=0', 'programes/p/([^/]+)/arxivats/?' => 'index.php?post_type=programa&cerca=$matches[1]&arxivat=1', 'programes/p/([^/]+)/?' => 'index.php?post_type=programa&cerca=$matches[1]&arxivat=0', 'programes/so/([^/]+)/cat/([^/]+)/arxivats/?' => 'index.php?post_type=programa&sistema_operatiu=$matches[1]&categoria_programa=$matches[2]&arxivat=1', 'programes/so/([^/]+)/arxivats/?' => 'index.php?post_type=programa&sistema_operatiu=$matches[1]&arxivat=1', 'programes/so/([^/]+)/cat/([^/]+)/?' => 'index.php?post_type=programa&sistema_operatiu=$matches[1]&categoria_programa=$matches[2]&arxivat=0', 'programes/so/([^/]+)/?' => 'index.php?post_type=programa&sistema_operatiu=$matches[1]', 'programes/cat/([^/]+)/arxivats/?' => 'index.php?post_type=programa&categoria_programa=$matches[1]&arxivat=1', 'programes/cat/([^/]+)/?' => 'index.php?post_type=programa&categoria_programa=$matches[1]', 'programes/arxivats/?' => 'index.php?post_type=programa&arxivat=1', ); $aRules = $aNewRules + $aRules; return $aRules;
Все еще надеюсь, что есть лучшее решение…
.
Ответ или решение
Решение задачи по сочетанию параметров запроса и переписыванию URL
Вашей задачей является настройка системы URL переписывания для поиска по пользовательскому типу записи в WordPress, чтобы создать "дружественные" URL. Вы описали, как внедрили это решение, но ищете более оптимальный способ. Рассмотрим вашу реализацию и возможные улучшения.
Шаги по реализации
-
Создание функции переписывания URL:
Вы уже создали функцию, которая генерирует URL с параметрами в определённом порядке. Эта функция проверяет наличие каждого параметра запроса и строит URL на основе доступных значений. Такой подход позволяет избежать появления пустых параметров в конечной ссылке.
function sc_change_programs_search_url_rewrite() { if(get_query_var('post_type') == 'program') { if(isset($_GET['word_search']) || isset($_GET['os']) || isset($_GET['category']) || isset($_GET['archived'])) { $available_query_vars = array( 'word_search' => 'w', 'os' => 'os', 'category' => 'cat', 'archived' => 'arch' ); $params_query = ''; foreach($available_query_vars as $query_var => $key) { if (get_query_var($query_var)) { $params_query .= $key . '/' . get_query_var($query_var) . '/'; } } if (!empty($params_query)) { wp_redirect(home_url("/program/") . $params_query); exit; } } } }
Этот код проверяет присутствие каждого параметра и формирует соответствующий URL с использованием
wp_redirect
. -
Создание правил переписывания URL:
Вы перечислили правила переписывания URL для всех возможных комбинаций параметров. Это может быть утомительным, но эффективно для вашего случая. Однако, для уменьшения количества кода можно использовать регулярные выражения, чтобы динамически обрабатывать комбинации параметров.
Пример регулярного выражения:
$new_rules = array( 'program/(?:(w)/([^/]+))?/(?:(os)/([^/]+))?/(?:(cat)/([^/]+))?/(?:(arch)/)?' => 'index.php?post_type=program&word_search=$matches[2]&os=$matches[4]&category=$matches[6]&archived=$matches[8]' ); return $new_rules + $aRules;
Данное регулярное выражение покрывает все возможные комбинации, использование
?
делает секции опциональными.
Оптимизация и лучшие практики
-
Использование фильтров и хуков: Обработку и модификацию URL следует выполнять с использованием фильтров и хуков WordPress для обеспечения совместимости и надежности.
-
Проверка на безопасность и валидация: Обязательно выполнять проверку и очистку значений параметров запроса для обеспечения безопасности приложения.
-
Кэширование: Подумайте о реализации кэширования результатов для повышения производительности.
-
Тестирование: Выполняйте тщательное тестирование всех URI на наличие ошибок и проверяйте корректность поведения при различной комбинации параметров.
Заключение
Ваше решение является функциональным и достигает цели, однако использование регулярных выражений и более динамических подходов может уменьшить дублирование кода и облегчить поддержку. Всегда рассматривайте возможности кэширования и следуйте лучшим практикам безопасности.
Если потребуется дальнейшая помощь для улучшения или внедрения самых наилучших практик, можно рассмотреть привлечение эксперта по SEO или WordPress-разработчика.