И снова про ЧПУ

_et

Новичок
Искал на форуме, но готовых решений что-то не нашел

Есть ли у кого-то готовая реализация ЧПУ с постраничной навигацией и разными вариантами УРЛ'ов?

т.е.

в index.php что-то типа

PHP:
switch ($url)
{
	case 'news':
		include "news.php";
	break;

	default:
		include "index.php";
}
$url - $_SERVER['REQUEST_URI'] с регуляркой+деление через / с помощью explode


В news.php два вывода
1 - вывод отдельно новости
2 - вывод списка с постраничностью

В .htaccess что-то типа
PHP:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule ^(.*)$ index.php [L,QSA]
Теперь про сами УРЛ'ы
news - все
news/nazvanie-novosti - название новости. "nazvanie-novosti" тянется из базы
news/page/1 - постраничность
без слешей в конце

Не хочется при добавлении какого-то материала, например статей, постоянно вносить в .htaccess правила. Так сделать проще всего. Интересно именно по такой системе как выше.

Может есть готовое решение уже, а то не могу найти.
Заранее спасибо.
 

AmdY

Пью пиво
Команда форума
_et
постраничная навигация никакого отношения к ЧПУ не имеет
 

_et

Новичок
Не могу понять как сделать с постраничностью и как подставлять туда УРЛ для новости из БД.
Я совсем профан в этом. По этому и прошу готовый пример.
 

Духовность™

Продвинутый новичок
Не могу понять как сделать с постраничностью и как подставлять туда УРЛ для новости из БД.
_etпостраничная навигация никакого отношения к ЧПУ не имеет
Что бы создать систему с ЧПУ, ты должен создать механизм, обладающий умением и пониманием парсть того, что приходит тебе в $_SERVER['REQUEST_URI'] (единая точка входа, что ты выше описал в htaccess)

Существует 2 основные системы парсинга URL:

1. Автоматическая. Парсим URL по слэшу: /news/list/page/1/othervar/foo
news - всегда имя модуля
list - имя контроллера
page - переменная со значением 1
othervar - переменная со значением foo

2. Парсим URL на основе правил, написанных на регулярных выражениях. У меня так это выглядит:
PHP:
    array( 'pattern' => '~^/admin/category/motion/(up|down)/([0-9]+)/([0-9]+)/?$~',
           'module' => 'category',
           'controller' => 'backend-motion',
           'aliases' => array('tomotion', 'id', 'pid'),
         ),
    array( 'pattern' => '~^/admin/category/edit/([0-9]+)?/?([0-9]+)?/?$~',
           'module' => 'category',
           'controller' => 'backend-edit',
           'aliases' => array('id', 'pid'),
         ),
    array( 'pattern' => '~^/admin/category/delete/?$~',
           'module' => 'category',
           'controller' => 'backend-delete'
         ),
 

_et

Новичок
Спасибо за подсказки.

Я видимо не точно выразился. Я не могу понять следующее

PHP:
$url = preg_replace("/\/+/",'/',$_SERVER['REQUEST_URI']);
$url = preg_replace("/^\/(.*)\/?$/U",'\\1',$url);
$url = preg_replace("/^(.*)\?.*$/U",'\\1',$url);
$url = explode("/", $url);

switch ($url[0])
{
    case 'news':
        include "news.php";
    break;

    default:
        include "index.php";
}
Это index.php

Вот news.php как я сделал
PHP:
<?php

switch ($url[1])
{
	case 'item':

		$query = mysql_query("SELECT * FROM ".TABLE_NEWS." WHERE ??? ");
		$row = mysql_fetch_array($query);
		
		$navigation->new_item($row['title'], null, null, 'parent');

		$smarty->assign('AUTHOR',	$row['author']);
		$smarty->assign('TITLE',	$row['title']);
		$smarty->assign('DATA',		$row['data']);
		$smarty->assign('ID',		$row['id']);
		$smarty->assign('TEXT',		$row['text']);
		$smarty->assign('URL',		$row['url']);

		$main_content=$smarty->fetch(MODULES.'news/news.tpl');
		break;

	default:

		$res = newsAll();
		$total_pages = mysql_result($res, 0, 0);

		if (isset($_GET['page']))
		{
			$page = (int)$_GET['page'];
			if ($page < 1) $page = 1;
		}
		else
		{
			$page = 1;
		}

		$cnt_pages = ceil( $total_pages / NUM_NEWS);

		if ($page > $cnt_pages) $page = $cnt_pages;

		$start = ( $page - 1 ) * NUM_NEWS;

		$query = "SELECT * FROM ".TABLE_NEWS." WHERE 1 ORDER BY id DESC LIMIT ".$start.", ".NUM_NEWS;
		$res = mysql_query( $query );

		$module_content = array();

		while($row = mysql_fetch_array($res))
		{
			$module_content[] = array
			(
				'AUTHOR'	=> $row['author'],
				'TITLE'		=> $row['title'],
				'DATA'		=> $row['data'],
				'ID'		=> $row['id'],
				'TEXT'		=> $row['text'],
				'URL'		=> $row['url']
			);
		}

		if ($cnt_pages > 1)
		{
			if ($page > 3)
				$startpage = '<li><a href="news">Первая</a></li>';
			else
				$startpage = '';

			if ($page < ($cnt_pages - 2))
				$endpage = '<li><a href="/news?page='.$cnt_pages.'">Последняя</a></li>';
			else
				$endpage = '';

			if ($page - 3 > 0)
				$p3l = '<li><a href="/news?page='.($page - 3).'">'.($page - 3).'</a></li>';
			else
				$p3l = '';
			if ($page - 2 > 0)
				$p2l = '<li><a href="/news?page='.($page - 2).'">'.($page - 2).'</a></li>';
			else
				$p2l = '';
			if ($page - 1 > 0)
				$p1l = '<li><a href="/news?page='.($page - 1).'">'.($page - 1).'</a></li>';
			else
				$p1l = '';

			if ($page + 3 <= $cnt_pages)
				$p3r = '<li><a href="/news?page='.($page + 3).'">'.($page + 3).'</a></li>';
			else
				$p3r = '';
			if ($page + 2 <= $cnt_pages)
				$p2r = '<li><a href="/news?page='.($page + 2).'">'.($page + 2).'</a></li>';
			else
				$p2r = '';
			if ($page + 1 <= $cnt_pages)
				$p1r = '<li><a href="/news?page='.($page + 1).'">'.($page + 1).'</a></li>';
			else
				$page1right = '';

			$pagi = $startpage.$p3l.$p2l.$p1l.'<li class="current">'.$page.'</li>'.$p1r.$p2r.$p3r.$endpage."";
		}

		$smarty->assign('PAGINATION',$pagi);

		$smarty->assign('module_content',$module_content);
		$main_content=$smarty->fetch(MODULES.'news/news_list.tpl');

		$smarty->assign('main_content',$main_content);
}

?>
Пока не реализовал вывод полной новости, но вот как мне тут быть?
Сейчас постраничность /news?page=id
Не могу понять как переделать в /news/page/id
и как быть с полной новостью. Как я понимаю там уже будет url[3], но куда и что....
Для меня это пока очень сложно. По этому и искал именно готовое решение.
 

craz

Нестандартное звание
хотя лучше /news/page-1
or
/news/page1
а чем лучше то?

PHP:
1. Автоматическая. Парсим URL по слэшу: /news/list/page/1/othervar/foo
news - всегда имя модуля
list - имя контроллера
page - переменная со значением 1
othervar - переменная со значением foo
почти правильно написано, только

news - модуль если есть если нет контроллер
list - контроллер если news не контроллера, в противном случае экшен
page - экшен, если list не экшен, в противном случае page название переменной
1 - значение переменной если модульная структура
и т.д.
 

craz

Нестандартное звание
news/page2
news/page-2
Это второй уровень вложенности

news/page/2 - третий уровень
???
нет в первом случае это один экшен, во втором это переменная - сделайте нормально потом будете рады, что заморочились.

news/page-2 из этого urla вы что будете грузить какой файл? в нем что будет грузиться из -2 - это айди чего?
 

_et

Новичок
2 - это id второй страницы со списком новостей
page2
page3
etc...
 

craz

Нестандартное звание
news/page/2 - а тут 2 что?

зы - все я дофлудилсо) 1к)
 

Вурдалак

Продвинутый новичок
1. Автоматическая. Парсим URL по слэшу: /news/list/page/1/othervar/foo
2. Парсим URL на основе правил, написанных на регулярных выражениях
— одно является частным случаем другого.

почти правильно написано
— да нет тут никаких «правильно» или «неправильно». Каждый как хочет так и делает. Я, например, считаю странным при одном значении считать его action'ом. Я обычно его считаю именем контроллера, а action дёргаю по умолчанию.
 

craz

Нестандартное звание
— одно является частным случаем другого.
он имел ввиду что не ишет легких путей и у него еще файл роутинга подключен)

подход более чем имеющий право на жизнь но сначала надо написать атомат, а потом уже впрыскивать частные случаи, причем так чтобы они не заменяли а дополняли правила автомата, в таком случае будет искаться автоматически(К ПРИМЕРУ), а если не найдено пойдет по кастомному роутеру.
 

craz

Нестандартное звание
вот на вашем месте пагинатор я бы делал как раз через GET массив не вижу смысла в ЧПУ пагинации.
Вы сделайте сначала чтобы по news показывались все новости по news/id/2 вторая новость в базе

А потом уж к индекс экшину в контроллере news прикрутите пагинаяцию на GET массиве и ничего страшного не будет поверьте будет что-то типа news/?page=1&count=15 - будет даже настриваться кол-во новостей из строки круто же?)

Короче это мое имхо - оно основано на быстроте внедрения решения, на его прозрачности и не предполагает заморочек в реализации, выбирать конечно же вам..

Ну и по сути перестаньте путать две задачи, ЧПУ и пагинация - это разные задачи, плюс ЧПУ + роутинг - это большая задача и не надо в нее еще и пагинацию вмешивать.
 

_et

Новичок
Да. Я реально напутал с пагинацией и ЧПУ!

Вы меня простите, но я совсем нуб в этом.
Вот у меня есть кейс item для вывода отдельной новости.
Допустим я перехожу по ссылке новости news/nazvanie-novosti
тогда надо как-то в запросе рулить по какому УРЛ'у я перешел и какую новость тянуть на вывод? id то нигде не фигурирует
или я не в ту сторону мысль пустил?
 

craz

Нестандартное звание
в ту все тоже самое делаете только теперь у вас не

news/id/4

а

news/title/YourTitleNews

и в своем котролере вы выбераете новость но по id из базы/файла etc, а по полю title пришедшему к вам из url

юадестндми?)
 

_et

Новичок
Вот я и не могу понять как сделать news/id/4
точнее будет news/4
 
Сверху