Перезапись URL-адреса Apache не работает должным образом

Я пытаюсь использовать правило apache-rewrite для преобразования приведенного ниже URL:

http://localhost/foo/bar/news.php?id=24

в следующем формате:

http://localhost/foo/bar/news/foo-bar

количество 24 это id случайной строки из таблицы MySQL, которая также содержит title и content поля.

MariaDB [blog]> select * from articles;
+----+---------+----------+ 
| id | title   | content  |
+----+---------+----------+ 
|  1 | foo-bar | bla bla  | 
+----+---------+----------+ 
1 row in set (0.00 sec)

у меня есть следующее правило в моем .htaccess:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
^news/([A_Za_z0_9_]+)$ DIRECTORY/AID/news.php?id= [QSA,L]

у меня также есть php-код, который генерирует такую ссылку:

$link = "<a href='news.php?id={$row['id']}'></a>";
echo $link;  

однако я не могу заставить правило перезаписи изменить путь в качестве желаемого конечного результата.

12 ответов


прежде всего, вам нужно будет изменить href в html, чтобы дать новый формат url

function news_preview() {
$query = "SELECT * FROM news ORDER BY id DESC LIMIT 5  ";
$result = mysql_query($query) or die(mysql_error());
while($row=mysql_fetch_array($result)) 
{   
  echo "<a href=\"/news/$row[id]\">  ". substr($row['title'], 0,26)."...</a><br/>".; }
}

будет генерировать URL-адреса, как http://localhost/news/24

обратите внимание, что я убрал /DIRECTORY/AID из url, поскольку htaccess предполагает, что вы хотите, чтобы это был url, в отличие от того, что вы указали в тексте.

но теперь добраться до http://localhost/news/this_is_article_title тип url. Потому что нет никакой корреляции между this_is_article_title и id 24, единственный способ достичь этого-либо добавление идентификатора в url-адрес тоже или поиск php в новостной статье с этим заголовком В базе данных.

это последнее решение, однако, имеет некоторые проблемы, так как вы не можете просто нам заголовок в url. Вы должны избегать персонажей. Также вам нужно будет добавить индекс для строки заголовка в БД для повышения производительности.

Итак, я пойду с первым решением. Мы будем генерировать URL-адреса, как это

http://localhost/news/24/this_is_article_title

сначала php часть

function news_preview() {
$query = "SELECT * FROM news ORDER BY id DESC LIMIT 5  ";
$result = mysql_query($query) or die(mysql_error());
while($row=mysql_fetch_array($result)) 
{ 
  $url = "/news/$row[id]/".preg_replace('/[^a-zA-Z0-9-_]/', '_', $row['title']);  
  echo "<a href=\"$url\">  ". substr($row['title'], 0,26)."...</a><br/>".; }
}

Далее идет часть htaccess.

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^news/([0-9]+)/([A-Za-z0-9_-]+)$ DIRECTORY/AID/news.php?id= [QSA,L]

это должно сделать это, я думаю.


подстановочный (реальный) URL имеет номер-код-для идентификации ссылки (согласно вашему описанию):http://localhost/DIRECTORY/AID/news.РНР?новости=42

код 42 в этом случае, но URL, который вы хотите отобразить, не имеет его. Без этого номера мы всегда получим ошибку 404. Это как войти только:http://localhost/DIRECTORY/AID/news.РНР?новости=

придется изменить URL вы хотите отобразить, добавив код после "/", например. Может быть дефис, и т. д. но регулярное выражение должно быть изменено соответствующим образом.

вот пример ввода: http://localhost/news/42/ перейти к http://localhost/DIRECTORY/AID/news.РНР?новости=42:

RewriteEngine On
RewriteRule ^news/([0-9]+)/?$ DIRECTORY/AID/news.php?news= [NC,L]

Это все, что вам нужно. Чтобы проверить этот пример, вставьте этот код только в новости.в PHP at http://localhost/DIRECTORY/AID/

<?php
if ( $_GET[ 'news' ] == '42' ) {
  echo  "HERE I AM<br /><br />";
}
?>

Обновлено в соответствии с описанием OP. Вместо This_is_news:

RewriteEngine On
RewriteRule ^news/([0-9a-zA-Z-_]+)/?$ DIRECTORY/AID/news.php?news= [NC,L]

поместите RewriteBase сразу после RewriteEngine на Он правильно настроит механизм перезаписи, прежде чем вы начнете перенаправлять


к сожалению, я не могу ответить на ваш вопрос в PHP или Apache (хотя я использую ручной конвертер REST для создания URL-адресов в моем текущем проекте), но из того, что я понимаю, вы хотите, чтобы ваш пользователь напечатал http://localhost/DIRECTORY/AID/article.РНР?распределения a_id=24 и адресная строка должна заканчиваться как http://localhost/DIRECTORY/AID/news/this_is_article_title.

Я не совсем уверен, какие преимущества это обеспечивает для вас, и имейте в виду, что мое решение не позволит вашему конечному пользователю ввести URL-адрес RESTful и оказаться на странице с адресом QueryString. Для этого вам понадобится дополнительная работа, и еще больше работы, чтобы синхронизировать ее с БД (я бы рекомендовал сценарий, который десеминирует URL RESTFUL, запрашивает БД для темы, а затем возвращает идентификатор или содержимое страницы ... но это другой вопрос переполнения стека на другой день.

решение Мое предлагаемое решение требует HTML5 doctype и A очень светлая разбрызгивание Javascript.

history.replaceState(null, "history title here", "news/this_is_article_title");

что это делает, это изменяет URL-адрес в адресной строке без запуска перенаправления страницы, перезагрузки или чего-либо еще. Этот javascript может быть динамически написан с вашим PHP, так как страница обслуживается, адрес обновляется. Чем выше в документе, тем быстрее изменения.

вот ссылка jsFiddle: http://jsfiddle.net/uT3RP/1/

к сожалению, они запускают код в iframe, поэтому он не управляет главной адресной строкой, поэтому я включил предупреждение, отображающее, что скажет местоположение адресной строки, для доказательства. Это не самое элегантное решение. Я бы даже не рекомендовал делать то, что вы делаете, без гарантий того, что отображаемый URL-адрес можно использовать для доступа к той же странице. Отказ от ответственности в сторону ... ваша проблема решена с помощью 1 строки js и doctype изменение (если вы не используете HTML5).

вы можете прекратить порку бедного ol ' htaccess и продолжить свой проект:)


это проблема с алгоритмом перезаписи URL и String-to-Id.

прежде всего, пожалуйста, помните, что когда-либо Ваш url изменяется с помощью модуля перезаписи, url в строке браузера всегда содержит post param как id или string(о Ваших новостях).

теперь вопрос. Наша цель - просто переписать Url:

http://localhost/DIRECTORY/AID/news/this_is_article_title

в:

http://localhost/DIRECTORY/AID/news.php?a_id=24

с модулем перезаписи, мы можем только переписать его кому:

http://localhost/DIRECTORY/AID/news.php?title=this_is_article_title

и вот часть htaccess, alrealdy протестирована на htaccess-online-tester

RewriteRule ^DIRECTORY/AID/news/([A-Za-z0-9_]+)$ DIRECTORY/AID/news.php?title= [QSA,L]

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

<?php

//write url reflect to news title.
function build_news_url_by_title(){
    $query = "SELECT * FROM news ORDER BY id DESC LIMIT 5";
    $result = mysql_query($query) or die(mysql_error());
    while($row = mysql_fetch_array($result)){
        echo "<a href=\"news/".strtr(substr($row['title'], 0,26), " ", "_")."\">".substr($row['title'], 0,26)."</a>";
    }   
}

function get_news_by_title($title){
    $real_title = strtr($title, "_", " ");
    $query = "SELECT * FROM news WHERE title LIKE %".$real_title."% LIMIT 1";
    return mysql_query($query) or die(mysql_error());
}

$title = $_POST['title'];

$news = get_news_by_title($title);

//some code return the news
...

Итак, url:

http://localhost/DIRECTORY/AID/news/this_is_article_title

может дать нам Новости.

наконец, от шагов выше, если мы вводим url

http://localhost/DIRECTORY/AID/news/this_is_article_title

в строке браузера, это может быть также дать нам Новости. И это не имеет никакого отношения к глупому ID. И хотя, возможно, есть некоторые ошибки с кодом выше, не ставьте его на свой сервер продуктов.


можете ли вы увидеть, работает ли это?

RewriteEngine On
RewriteBase /DIRECTORY/AID/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
^news/([A-Za-z0-9_]+)$ news.php?id= [QSA,L]

EDIT: исправлены определения классов символов регулярных выражений.


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

<a href="news.php?news_id=$id&title=$url_tile">

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

 1. Make sure .htaccess file is readable and can do some simple thing, preventing directory indexing for instance.
 2. Make sure you can redirect something with simple html code.
 3. Make sure you can run Felipe's example code successfully. From here you can get good picture of what is going on. 

и в качестве примечания:

чаще всего переписывать так:

http://localhost/DIRECTORY/AID/news.php?a_id=24 TO -->
http://localhost/DIRECTORY/AID/news/24_this_is_article_title 

обратите внимание, что идентификатор 24 по-прежнему переносится на переписанный url. Это упростит сопоставление шаблонов и избегайте ненужной обработки дублирования заголовка.


изменить ссылки:

echo "<a href=\"news.php?news=$row[id]\"> ". substr($row['title'], 0,26)."</a>

to

echo "<a href=\"news/$row['title']\">".$row['title']."</a>"

таким образом, ссылка будет идти в news/$row['title'] вместо news.php?id=.... А теперь на странице DIRECOTORY/AID/news.php С id и проверьте, если это число или текст, и в случае текста сопоставьте его с $row['title'] а затем загрузите страницу соответствующим образом.

Примечания:

  1. предполагается, что $row['title'] является уникальным для всех других строк.
  2. название не содержит не HTML-контента, в этом случае вам придется URL-адрес избежать этих символов.

если название не будет уникальным, то вы, вероятно, должны сделать news/{id}/{title} а затем перепишите его на DIRECTORY/AID/news.php?id={id}&title={title} и затем вы можете основывать его на идентификаторе вместо заголовка.

надеюсь, что это поможет.


если вы чувствуете, что ваш .htaccess файл не работает по назначению, то это проблема конфигурации сервера и, скорее всего, сделать с AllowOverride директива в конфигурации Apache.

в своем http.conf файл найдите раздел, который выглядит следующим образом:

<Directory>
    Options FollowSymLinks
    AllowOverride None
</Directory>

изменить AllowOverride директиву, разрешающую All.

<Directory>
    Options FollowSymLinks
    AllowOverride All
</Directory>

следующее, чтобы убедиться, что mod_rewrite модуль включен для вашей установки XAMPP. Поиск следующая строка:

#LoadModule rewrite_module modules/mod_rewrite.so

удалить # так выглядит так:

LoadModule rewrite_module modules/mod_rewrite.so

перезапустите службу Apache после сохранения всех ваших изменений.

также убедитесь, что вы используете


Я не могу комментировать, поэтому я должен ответить.

читая все ответы и ваш вопрос, не ясно, что вы хотите. По крайней мере для меня. Вы говорите, например:

http://localhost/DIRECTORY/AID/article.php?a_id=24 до

http://localhost/DIRECTORY/AID/article/this_is_article_title

но я думаю, что это не совсем так, если вы не хотите

http://localhost/DIRECTORY/AID/article.php?a_id=24

быть URL, введенным в адресной строке браузера, и если да, то какова будет цель перенаправления? Наконец, любому посетителю придется типа именно то, что вы не хотите их тип.

Я предполагаю, что вы хотите, чтобы дружественный URL был введен:

http://localhost/DIRECTORY/AID/article/this_is_article_title , поэтому вопрос должен быть наоборот:

http://localhost/DIRECTORY/AID/article/this_is_article_title до

http://localhost/DIRECTORY/AID/article.php?a_id=24

следующее, что не кажется ясным, это то, что отображается в строке браузера? Единственный ответ: введенный URL. Он не может показать ничего другого.

вкратце: если вы хотите http://localhost/DIRECTORY/AID/article/this_is_article_title чтобы показать в адресной строке, это то, что вы должны ввести. Реальный URL, подстановка (http://localhost/DIRECTORY/AID/article.РНР?распределения a_id=24), никогда не отображается и никогда не печатается. Для этого и существует перенаправление.

С другой стороны, не ясно, как идентификационные номера, предоставляемые новостями.ожидается, что php будет преобразован в строки типа article / this_is_article_title. ¿Где эти строки, сколько номеров идентификаторов, какой алгоритм или Формула должны использоваться для достижения этого преобразования, какие из этих идентификаторов являются" корневыми", как вы упомянули в комментарии, и как их можно идентифицировать и т. д.? Вы должны подробнее остановиться на этом вопросе, потому что он кажется импровизированным и несогласованным с вашими предыдущими комментариями.

Я могу ошибаться, конечно. Я просто догадываюсь, чтобы попытаться помочь с вашим вопросом.

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


Похоже, вы забыли косую черту перед "новостями".РНР."