Пара вопросов о .htaccess и дружественных URL - PullRequest
3 голосов
/ 18 августа 2011

Я всегда плохо относился к apache и использовал очень простые решения.Прямо сейчас я создал программное обеспечение для cms ... но .htaccess начинает сильно сокращаться.

Сначала я объясню, как работают и выглядят мои дружественные URL-адреса.Мой переключатель языка основан на URL и всегда содержит два символа.И это выглядит так: stackoverflow.com / ru / это делает переключение действительно простым и, поскольку оно основано на URL-адресе ..., оно хорошо работает в терминах SEO.Кроме того, если идентификатор языка не установлен, будет использоваться язык по умолчанию (stackoverflow.com/).
. В числах нет идентификаторов страниц.У меня есть уникальные идентификаторы страниц в тексте: stackoverflow.com / services.html и для целей SEO и каталогов папок - для предотвращения конфликтов .html в конце ..
Для подстраниц у меня есть "$Переменные стиля current_page "и" $ parent_page ": stackoverflow.com / services / translationating.html Службы, являющиеся родителями, и переводы, являющиеся текущей страницей.
Некоторый пример кода тоже (я его много использовалВы не думаете, что оно неполное):

RewriteRule ^(et|en|fi)\/(.+)\/(.+)\.html  index.php?language=$1&pagelink=$3&parentlink=$2 [L,NC,QSA]

RewriteRule ^(.+)\/(.+)\.html  index.php?language=0&pagelink=$2&parentlink=$1 [L,NC,QSA]
RewriteRule ^(.+)\.html  index.php?language=0&pagelink=$1&parentlink=0 [L,NC,QSA]

Как сделать часть переключения языка более динамичной?
Этот метод ..^(et|en|fi)\/.. означает, что когда я устанавливаюдо cms, я должен вручную установить список языков.Лучше всего было бы установить его как-то в настройках cms.Потому что, таким образом, нет никаких конфликтов, связанных с папками.Возможна ли глобальная переменная apace через php, а затем отобразить ее в файле .htaccess?Как то так: ..^(LANGUAGELISTS)\/..?Если это невозможно, то лучше всего будет сопоставить 2 символа в этом месте и передать его как $_GET['language'].

Как динамически иметь неограниченное число родителей?
Это означает, что "$ parent_page" не установлен статически, и у меня есть неограниченное количество детей, подобно этому: stackoverflow.com / services / translation / english / somesubpage.html .Если это возможно, то также, как это будет использоваться в php с массивом?

Bounty edit
Первая часть вопроса в основном решена, если кто-то не придетс некоторыми php -> apache-array -> .htaccess.
Однако вторая часть вопроса все еще не решена.Поскольку это было проблемой для всех моих проектов и, возможно, могло бы помочь кому-то еще в будущем, я решил добавить награду к этому вопросу.

Ответы [ 5 ]

2 голосов
/ 18 августа 2011

Чтобы ответить на ваш первый вопрос: вы можете использовать RewriteRule ^([a-zA-Z]{2})([/]?)(.*)$ path/file.php?language=$1 Это ограничивает первую строку двумя символами и передает ее $_GET['language']

Редактировать: , добавляя RewriteCond %{REQUEST_FILENAME} !-f иRewriteCond %{REQUEST_FILENAME} !-d предотвратит конфликты с существующими каталогами / файлами

Второй вопрос гораздо сложнее ..

Обновление:

Что говорят Шад и Тоопайэто хорошее начало, на мой взгляд.Использование explode() для разделения уровней и сравнение его с slug довольно просто.Но это усложняется, когда вы хотите добавить гибкость сценарию.

function get_URL_items() {
$get_URL_items_url = $_SERVER['REQUEST_URI'];
$get_URL_items_vars = explode("/",$get_URL_items_url);
for ($get_URL_items_i = 0; $get_URL_items_i < count($get_URL_items_vars) ; $get_URL_items_i++) {
    if(strlen(trim($get_URL_items_vars[$get_URL_items_i])) == 0) {
        unset($get_URL_items_vars[$get_URL_items_i]);
    }
}
return $get_URL_items_vars;

Допустим, у вас есть сайт с подразделом «Фестиваль» и база данных, заполненная информацией на 100+исполнителя, и вы хотите, чтобы ваши URL выглядели website.com/festival/<artistgenre>/<artistname>/.Вы не хотите создавать более 100 страниц в своей CMS, поэтому <artistgenre> и <artistname> являются своего рода символами подстановки.

Мне было трудно добиться этого без большого количества операторов if / else, таких как:

$item = get_URL_items();    
if(is_user($item[2]) && is_genre($item[1]) && is_festival($item[0])) {
  // do mysql stuff here
}
1 голос
/ 20 августа 2011

Я почему-то думаю, что этот ответ не будет очень популярен, но все равно здесь. :)

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

О некоторых вещах следует помнить:

  • Вам нужно установить директиву блокировки перезаписи, иначе вы получите много сумасшедших результатов.
  • Помните, что скрипт перезаписи - это командная строка PHP скрипт. Он не знает таких вещей, как глобальный $ _SERVER. Это на удивление легко забыть.
  • Этот скрипт загружается при запуске сервера, поэтому любые изменения в нем требуют перезапуска сервера, прежде чем они вступят в силу.
  • Всегда проверяйте это в командной строке, передавая URL-адрес и проверяя вывод перед перезапуском сервера. Если ваш сценарий не работает, перезапуск сервера приведет к чему-либо от неработающей перезаписи на сервер, вообще не запускающейся.

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

Вот единственный урок, который мне удалось найти, как это сделать с помощью PHP ...

Использование MySQL для управления mod_rewrite через PHP

Это далеко от стандартного способа переписывания, поэтому я полагаю, что я собираюсь справиться с этим многократно. Ну что ж. :)

1 голос
/ 20 августа 2011

В ответ на ваш bounty вопрос я бы использовал это:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([A-Z]{2}\/)*(([A-Z]+\/)*)([A-Z]+)\.html$ index.php?lang=$1&parents=$2&pagelink=$4 [NC,QSA,L]

Поскольку вы хотите иметь возможность обрабатывать любое количество поколений / уровней в своем URL, задумывались ли вы о том, как вы хотитепоймать их в своем PHP-скрипте?

Вы определенно не хотите идти и проверять isset($_GET['parent1']);isset($_GET['parent2']) и т. д. и т. д. и т. п.

Как указали некоторые другие ответы, вам действительно нужноанализировать ваш URL внутри скрипта PHP;с этой целью мой RewriteRule передает весь раздел «родительский» URL-адреса, который ваш сценарий может затем explode и проанализировать;но не мешает нормальным URL-адресам без родителей.=)

1 голос
/ 20 августа 2011

На вашем месте я бы использовал что-то вроде этого:

.htaccess:

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !/main.php$
RewriteRule ^([a-zA-Z]{2})?(.*)$ main.php?lang=$1&path=$2 [L,QSA]

main.php:

$langs = array('en','de','ru'); // list of supported languages
$currentLang = isset($_GET['lang'])&&in_array($_GET['lang']) ? $_GET['lang'] : $defaultLang; // current selected language
$path = $_GET['path']; // current path

Затем в main.php вы можете анализировать путь в соответствии с вашими потребностями

0 голосов
/ 23 августа 2011

Ну, для SEO части, я думаю, лучше иметь slug для каждой статьи (ссылка на которую вы используете для CMS).Значит, в вашей базе данных у вас есть какая-то таблица «перевода», которая переводит запрашивающий uri / slug и связывает его с $parent_page.

...