Rewrite URLs Ideas

Идеи и задумки по ЧПУ
Author
Message

В этой теме будут обсуждаться идеи реализации ЧПУ

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

Итак Ф-ция sed_url()

Нужно убрать лишний параметр alias, оставим только path

// $section - название скрипта, без ".php", например page, list, users.
// $param - список параметров, может быть в виде строки или в виде массива.
// $anchor - якорь вместе со #, например  #comments, #top и т.д.
// $header - ссылка или редирект
// $enableabs - а вот это интересная фишка, при передаче значения false везде заменяется & на & в основном нужно для rss
function sed_url($section, $param = '', $anchor = '', $header = false, $enableabs = true, $path = '')
{
    global $cfg, $sys;
    // Убираем лишний & справа, в основном только для $more в PFS
    $param = preg_replace('/&$/', '', $param); //fix $more in PFS
    // Проверям редирект ли это и врублены ли абсолютные урлы или хак для rss при использовании абсолютных урлов ($enableabs = false), там подставляется значение $cfg['mainurl']
    // т.е. для формировании через sed_url() ссылок в rss ленте, даже при использовании абсолютных урлов на сайте, ф-ция должна выдавать относительные ссылки
    // Для серверного редиректа обязательно нужен абсолютный путь в урле! Сейчас в двигле в редиректах относительные урлы но это не правильно по стандартам
    $section = ($header || ($cfg['absurls'] && $enableabs)) ? $sys['abs_url'].$section : $section;
    // Тут всё просто, если редирект или хак для rss то тока & а вот если ссылка то &
    $param = ($header || !$enableabs) ? $param : str_replace('&', '&', $param);
    if (!empty($param))
        { $res = $section.".php?".$param.$anchor; }
    else
        { $res = $section.".php"; }
    return $res;
} 

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

Дальше нам будет необходима ф-ция разбирающая параметры в ассоциативный массив, ключ — название параметра, значение массива — содержимое параметра

//Разбивка параметров в массив
function sed_parse_str($str)
{
    $res = array();
    foreach (explode('&', $str) as $item)
    {
        if (!empty($item))
        {
            list($key, $val) = explode('=', $item);
            $res[$key] = $val;
        }
    }
    return $res;
}

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

Неплохо бы пустые параметры нахрен отбрасывать у ссылок

такие ссылки: list.php?c=lib&s=count&w=asc&o=&p= меня просто убиваю!

Так что лучше просто уничтожать пустые параметры и преобразовывать урл в list.php?c=lib&s=count&w=asc

//Собираем строку из параметров
function sed_build_str($params)
{
      $res = array();
      foreach ($params as $key => $val)
      {
           $res[] = $key."=".$val;
      }
      return implode("&", $res);
}  
//Проверка пустых параметров
function sed_check_params($params) {
   $res = array();
   foreach ($params as $key => $val)
    {
       if (!empty($val)) { $res[$key] = $val; }
    }
   return $res;
} 

Ну и собственно в sed_url() можно будет так изменить:

function sed_url($section, $param = '', $anchor = '', $header = false, $enableabs = true, $path = '')
{
    global $cfg, $sys;
    // Убираем лишний & справа, в основном только для $more в PFS
    $param = preg_replace('/&$/', '', $param); //fix $more in PFS
    // если в ф-цию передаётся массив параметров, оставляем как есть, а если строка то разбираем
    $param = is_array($param) ? $param : sed_parse_str($param);
    //Проверяем урл на пустые параметры и собираем строку с параметрами из массива
    $param = sed_build_str(sed_check_params($param));
    // Проверям редирект ли это и врублены ли абсолютные урлы или хак для rss при использовании абсолютных урлов ($enableabs = false), там подставляется значение $cfg['mainurl']
    // т.е. для формировании через sed_url() ссылок в rss ленте, даже при использовании абсолютных урлов на сайте, ф-ция должна выдавать относительные ссылки
    // Для серверного редиректа обязательно нужен абсолютный путь в урле! Сейчас в двигле в редиректах относительные урлы но это не правильно по стандартам
    $section = ($header || ($cfg['absurls'] && $enableabs)) ? $sys['abs_url'].$section : $section;
    // Тут всё просто, если редирект или хак для rss то тока & а вот если ссылка то &
    $param = ($header || !$enableabs) ? $param : str_replace('&', '&', $param);
    if (!empty($param))
        { $res = $section.".php?".$param.$anchor; }
    else
        { $res = $section.".php"; }
    return $res;
}
?>

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!


This post was edited by Amro (14-09-13 13:58 GMT, 3847 days ago)

Это всё мысли в слух так сказать были ))

Теперь разбирёмся с параметром $path

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

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

1. Новости news
1.1.Новости науки newscience
1.1.1 Новости физики newsfiz
И типа новость кака нить с алиасом «newsone» или айди равным 1

В идеале пути должны быть такими:

news/
news/newscience
news/newscience/newsfiz
news/newscience/newsfiz/newsone
или news/newscience/newsfiz/1

 

 

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

Отак, откуда нам брать полный путь например для категории newsfiz

Тут два варианта

  • либо написать ф-цию которая будет каждый раз бадяжить массив $sed_cat
  • либо уже в самом $sed_cat сделать путь!!

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

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

/* ------------------ */
function sed_load_structure()
	{
	global $db_structure, $cfg, $L;
	$res = array();
	$sql = sed_sql_query("SELECT * FROM $db_structure ORDER BY structure_path ASC");
	while ($row = sed_sql_fetchassoc($sql))
		{
		if (!empty($row['structure_icon']))
			{ $row['structure_icon'] = "<img src=\"".$row['structure_icon']."\" alt=\"\" />"; }
		$path2 = mb_strrpos($row['structure_path'], '.');
		$row['structure_tpl'] = (empty($row['structure_tpl'])) ? $row['structure_code'] : $row['structure_tpl'];
		if ($path2>0)
			{
			$path1 = mb_substr($row['structure_path'],0,($path2));
			$spath = $path[$path1]; //new sed175
      $path[$row['structure_path']] = $path[$path1].'.'.$row['structure_code'];
			$tpath[$row['structure_path']] = $tpath[$path1].' '.$cfg['separator'].' '.$row['structure_title'];
			$row['structure_tpl'] = ($row['structure_tpl']=='same_as_parent') ? $parent_tpl : $row['structure_tpl'];
			}
		else
			{
			$path[$row['structure_path']] = $row['structure_code'];
			$tpath[$row['structure_path']] = $row['structure_title'];
      $spath = ""; //new sed175
			}
		$order = explode('.',$row['structure_order']);
		$parent_tpl = $row['structure_tpl'];
		$res[$row['structure_code']] = array (
			'path' => $path[$row['structure_path']],
			'tpath' => $tpath[$row['structure_path']],
      'spath' => $spath, //new sed175
			'rpath' => $row['structure_path'],
			'tpl' => $row['structure_tpl'],
			'title' => $row['structure_title'],
			'desc' => $row['structure_desc'],
			'icon' => $row['structure_icon'],
			'group' => $row['structure_group'],
			'allowcomments' => $row['structure_allowcomments'],
			'allowratings' => $row['structure_allowratings'],
			'order' => $order[0],
			'way' => $order[1]
				);
		}
  return($res);
	}

и всё, теперь у нас в $sed_cat есть путь который можно использовать, например для категорий в sed_url так:

  if ($section == "list") {
     $cpath = $sed_cat[$params['c']]['spath'];
     $path = (!empty($cpath)) ? str_replace(".", "/", $cpath).'/' : '';
  }

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!


This post was edited by Amro (14-09-13 14:54 GMT, 3847 days ago)

И вот ещё думка, я не стороннки всякого Г в htaccess по типу

RewriteEngine On
RewriteBase /
RewriteRule (datas|images|js|skins|plugins|system)/(.*)$ $1/$2 [L]
RewriteRule ^admin/([a-z]+)$	 admin.php?m=$1 [NC,NE,QSA,L]
RewriteRule ^login$ users.php?m=auth [NC,NE,QSA,L]
RewriteRule ^logout/(.*)$ users.php?m=logout&x=$1 [NC,NE,QSA,L]
RewriteRule ^users$ users.php [NC,NE,QSA,L]
RewriteRule ^users/group:([0-9]+)$ users.php?gm=$1 [NC,NE,QSA,L]
RewriteRule ^users/maingroup:([0-9]+)$ users.php?g=$1 [NC,NE,QSA,L]
RewriteRule ^users/group:([0-9]+)/sort:([a-z]+)-(asc|desc)$ users.php?gm=$1&s=$2&w=$3 [NC,NE,QSA,L]
RewriteRule ^users/maingroup:([0-9]+)/sort:([a-z]+)-(asc|desc)$ users.php?g=$1&s=$2&w=$3 [NC,NE,QSA,L]
RewriteRule ^users/group:([0-9]+)/filter:(.*)$ users.php?gm=$1&f=$2 [NC,NE,QSA,L]
RewriteRule ^users/maingroup:([0-9]+)/filter:(.*)$ users.php?g=$1&f=$2 [NC,NE,QSA,L]
RewriteRule ^users/group:([0-9]+)/filter:(.*)/sort:([a-z]+)-(asc|desc)$ users.php?gm=$1&f=$2&s=$3&w=$4 [NC,NE,QSA,L]
RewriteRule ^users/maingroup:([0-9]+)/filter:(.*)/sort:([a-z]+)-(asc|desc)$ users.php?g=$1&f=$2&s=$3&w=$4 [NC,NE,QSA,L]
RewriteRule ^users/sort:([a-z]+)-(asc|desc)$ users.php?s=$1&w=$2 [NC,NE,QSA,L] 

по моему это чрезмерно сложно

я бы обратный реврайт предложил сделать так:

AddDefaultCharset UTF-8
Options -Indexes
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ rewriteurl.php

И уже самими средствами PHP в rewriteurl разбирать URL и подрубать index.php, forums.php, list.php

Хотя ХЗ можно ли так

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

Пример правил и их поиск

$params = is_array($params) ? $params : sed_parse_str($params);
// Массив аргументов ссылки
$args = sed_check_params($params);  // без пустых аргументов
$ruler['list'][] = array('part' => 'list',
                 'params' => sed_parse_str('c=*&s=*&w=*&o=*&p=*'),
                 'rewrite' => '{c}/?s={s}&w={w}&o={o}&p={p}');
$ruler['list'][] = array('part' => 'list',
                 'params' => sed_parse_str('c=*&s=*&w=*'),
                 'rewrite' => '{c}/?s={s}&w={w}');
$ruler['list'][] = array('part' => 'list',
                 'params' => sed_parse_str('c=*&s=*'),
                 'rewrite' => '{c}/?s={s}');
$ruler['list'][] = array('part' => 'list',
                 'params' => sed_parse_str('c=*'),
                 'rewrite' => '{c}');
$rule = array();
// Если секция с правилами присутствует
if(!empty($ruler[$section]))
{
    // Извлекаем каждое правило
    foreach($ruler[$section] as $rule)
    {
        // По-умолчанию типа правило найдено
        $matched = true;
        // сравниваем наличие параметров в обоих массивах
        foreach($rule['params'] as $key => $val)
        {
            if(empty($args[$key])
                || (!array_key_exists($key, $args))
                || ($val != '*' && $args[$key] != $val))
            {
                $matched = false;
                break;
            }
        }
        // Если правило найдено и кол-во параметров в сылке и в правиле одинаковое
        if($matched && (count($args) == count($rule['params'])))
        {
            $url = $rule['rewrite'];
            break;
        }
    }
} 

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

Ну и дальше уже прогоняем правило и делаем замены

// ищем в правиле {параметр замены}
if(preg_match_all('#\{(.+?)\}#', $url, $matches, PREG_SET_ORDER))
    {
        // Ну а тут найденное заменяем из массива $args
    }

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

//Собираем строку без пустых параметров
function sed_build_str($params)
{
      $res = array();
      foreach ($params as $key => $val)
      {
           $res[] = $key."=".$val;
      }
      return implode("&", $res);
}
//Проверка пустых параметров
function sed_check_params($params) {
   $res = array();
   foreach ($params as $key => $val)
    {
       if (!empty($val)) { $res[$key] = $val; }
    }
   return $res;
}
/* ------------------ */  // new in 175
function sed_url($section, $params = '', $anchor = '', $header = false, $enableabs = true, $path = '')
	{
  global $cfg, $sys, $sed_cat;
  $params = preg_replace('/&$/', '', $params); //fix $more in PFS
  $params = is_array($params) ? $params : sed_parse_str($params);
  if ($section == "list") {
     $cpath = $sed_cat[$params['c']]['spath'];
     $path = (!empty($cpath)) ? str_replace(".", "/", $cpath).'/' : '';
  }
  $args = sed_check_params($params);  // без пустых аргументов
  $section = ($header || ($cfg['absurls'] && $enableabs)) ? $sys['abs_url'].$section : $section;
 // $params = ($header || !$enableabs) ? $params : str_replace('&', '&amp;', $params);
//$params = is_array($params) ? $params : sed_parse_str($params);
// Массив аргументов ссылки
$args = sed_check_params($params);  // без пустых аргументов
// Правила, думаю нужно будет их вынести в отдельный файл, причеём в этом же массиве можно хранить и правила для обратного преобразования
$ruler['list'][] = array('part' => 'list',
                 'params' => sed_parse_str('c=*&s=*&w=*&o=*&p=*'),
                 'rewrite' => '{c}/?s={s}&w={w}&o={o}&p={p}');
$ruler['list'][] = array('part' => 'list',
                 'params' => sed_parse_str('c=*&s=*&w=*'),
                 'rewrite' => '{c}/?s={s}&w={w}');
$ruler['list'][] = array('part' => 'list',
                 'params' => sed_parse_str('c=*&s=*'),
                 'rewrite' => '{c}/?s={s}');
$ruler['list'][] = array('part' => 'list',
                 'params' => sed_parse_str('c=*'),
                 'rewrite' => '{c}');
$ruler['page'][] = array('part' => 'page',
                 'params' => sed_parse_str('id=*'),
                 'rewrite' => '{id}');
$ruler['page'][] = array('part' => 'page',
                 'params' => sed_parse_str('al=*'),
                 'rewrite' => '{al}');
$ruler['forums'][] = array('part' => 'forums',
                 'params' => sed_parse_str('m=posts&q=*'),
                 'rewrite' => '{m}/{q}');
$ruler['users'][] = array('part' => 'users',
                 'params' => sed_parse_str('m=details&id=*'),
                 'rewrite' => 'users/details/{id}');
$ruler['plug'][] = array('part' => 'plug',
                 'params' => sed_parse_str('plug.php?e=*'),
                 'rewrite' => 'plug/{e}');
$ruler['polls'][] = array('part' => 'polls',
                 'params' => sed_parse_str('id=*'),
                 'rewrite' => 'poll/{id}');
$ruler['*'][] = array('part' => '*',
                 'params' => sed_parse_str('*'),
                 'rewrite' => '*');
$url = $ruler['*'][0]['rewrite']; // default rule
$rule = array();
// Если секция с правилами присутствует
if(!empty($ruler[$section]))
{
    // Извлекаем каждое правило
    foreach($ruler[$section] as $rule)
    {
        // По-умолчанию типа правило найдено
        $matched = true;
        // сравниваем наличие параметров в обоих массивах
        foreach($rule['params'] as $key => $val)
        {
            // тут проверку надо делать как-то по другому
            if(empty($args[$key])
                || (!array_key_exists($key, $args))
                || ($val != '*' && $args[$key] != $val))
            {
                $matched = false;
                break;
            }
        }
        // ?? Проверять на одинаковое кол-во параметров незнаю, тоже наверное не вариант
        // Если правило найдено и кол-во параметров в сылке и в правиле одинаковое
        if($matched && (count($args) == count($rule['params'])))
        {
            $url = $rule['rewrite'];
            break;
        }
    }
}
if(preg_match_all('#\{(.+?)\}#', $url, $matches, PREG_SET_ORDER))
{
        foreach($matches as $m)
        {
        $var = $m[1];
        $url = str_replace($m[0], urlencode($args[$var]), $url);
        unset($args[$var]);
        }
}
if ($url == "*") {
  $params = sed_build_str($args);
  if (!empty($params))
		{ $res = $section.".php?".$params.$anchor; }
	else
		{ $res = $section.".php"; }
    return $res;
}
return($url);

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

Редиректилка вах в конце common.php

if ($cfg['sefurls'])
{
   if ($findphp = mb_strpos($sys['request_uri'], '.php'))
   {
      $params = $_SERVER['QUERY_STRING'];
      $params_arr = sed_parse_str($params);
      $section = mb_substr($sys['request_uri'], 1, $findphp-1);
      if ($section == 'list') { $sys['catcode'] = $params_arr['c']; }
      if ($section == 'page') {
        if (!empty($params_arr['al']))
      	 {
          $pal = $params_arr['al'];
          $sql = sed_sql_query("SELECT page_cat FROM $db_pages WHERE page_alias='$pal' LIMIT 1");
          $pag = sed_sql_fetchassoc($sql);
          $sys['catcode'] = $pag['page_cat'];
         }
        elseif (!empty($params_arr['id']))
      	 {
          $pid = $params_arr['id'];
          $sql = sed_sql_query("SELECT page_cat FROM $db_pages WHERE page_id='$pid'");
          $pag = sed_sql_fetchassoc($sql);
          $sys['catcode'] = $pag['page_cat'];
         }
      }
      $redirect301 = sed_url($section, $params, "", true);
      header("HTTP/1.1 301 Moved Permanently");
      header("Location: ".$redirect301);
      exit;
   }
}

Forever unshaven, red-eyed, detached from reality, with his cockroaches in my head. And let it always will be!

Please write in English

$cfg['sefurls'

system/functions.admin.php On or off? 


This post was edited by Kaan (20-10-13 16:03 GMT, 3811 days ago)