Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Класс для разбора URL. Или ещё раз о ЧПУ c mod_rewrite (papa_bear)
Author Message
papa_bear
Заглянувший



Joined: 11 Mar 2017
Posts: 2
Карма: 0
   поощрить/наказать


PostPosted: Sat Mar 11, 2017 10:00 pm (написано за 55 минут 53 секунды)
   Post subject: Класс для разбора URL. Или ещё раз о ЧПУ c mod_rewrite
Reply with quote

Вариант создания человекопонятных УРЛов:
Есть файл контроллер (он же index.php). Все запросы адресуются к нему. Задача контроллера разобрать введенный урл и подгрузить нужный шаблон страницы.
В одной директории с контроллером находится файл .htaccess

Сначала приведу код, потом будет описание что и как.

Файл .htaccess
Code (any language): скопировать код в буфер обмена
AddDefaultCharset utf-8
Options All -Indexes
<FilesMatch ".(htaccess|htm)$">
 Order Allow,Deny
 Deny from all
</FilesMatch>

<IfModule mod_rewrite.c>
RewriteEngine On
Options +FollowSymlinks
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L,QSA]
</IfModule>
Класс для разбора URL
Code (php): скопировать код в буфер обмена
<?
class Url{
  public $root;
  private $arrServer;
  private $delimiter = '/';
 
  function __construct() {
    $this -> arrServer = $_SERVER;
  }
 
  public function urlParce() {
    $this -> root($this -> arrServer[PHP_SELF]);
    return $this -> requestUri($this -> arrServer[REQUEST_URI]);
  }
 
  private function root($str) {
    $str = $this -> strParce($str);
    $str = array_slice (www.php.net/array_slice)($str, 0, count (www.php.net/count)($str)-1);
    $str = $this -> delimiter . implode (www.php.net/implode)($this -> delimiter, $str);
    $this -> root = $str;
  }

  private function requestUri($str) {
    $str = substr (www.php.net/substr)($str, strlen (www.php.net/strlen)($this -> root));
    return $this -> strParce($str);
  }

  private function strParce($str) {
    $str = $this -> changeSymbol($str, '\\', $this -> delimiter);
    $str = explode (www.php.net/explode)($this -> delimiter, $str);
    $res = Array (www.php.net/array)();

    for($i = 0; $i < count (www.php.net/count)($str); $i++) {
      if(!$str[$i]) continue;
      $pos = strpos (www.php.net/strpos)($str[$i], ".");
      if(!$pos) {
        $res[] = $str[$i];
        continue;
      }
      $res[] = substr (www.php.net/substr)($str[$i], 0, $pos);
    }
    return $res;
  }
 
  private function changeSymbol($str='', $oldSymbol = '\\', $newSymbol = '/') {
    for($i = 0; $i < strlen (www.php.net/strlen)($str); $i++) {
      if( $str[$i] == $oldSymbol )  $str[$i] = $newSymbol;
    }
    return $str;
  }
}
?>
Файл index.php
Code (php): скопировать код в буфер обмена
<?
$url = new Url;

$router = $url -> urlParce();
?>
Класс Url имеет одно публичное свойство - root, и один публичный метод - urlParce(). Остальные свойства и методы приватны.

Рассмотрим два варианта. Первый - index.php и .htaccess располагаются в корневой директории сайта. Второй - оба файла располагаются в какой-то внутренней директории, пусть будет: /abc/def/

Ещё одна оговорка: для примера сайт будет доступен по доменному имени - mysite.ru

Итак, Вариант 1:
В этом случае свойство root будет содержать '/'.
В переменную $router будет записан массив из всего что напечатано в адресной строке браузера. Т.е. если адресная строка содержит mysite.ru или mysite.ru/ то метод urlParce() вернет пустой массив. Если адресная строка содержит что-то вроде mysite.ru/news или mysite.ru/news/ то метод urlParce() вернет массив, состоящий из одного элемента [news]

Вариант 2:
При использовании второго варианта, когда контроллер лежит во внутренней директории, в файле .htaccess необходимо её указать. В нашем примере когда index.php лежит в директории /abc/def/ в .htaccess нужно прописать: RewriteBase /abc/def/
В этом случае свойство root будет содержать - '/abc/def'. Обратите внимание, в конце нет слеша.
Метод urlParce() работает аналогично с примером выше. Т.е. если идет обращение mysite.ru/abc/def или mysite.ru/abc/def/ вернет пустой массив. Если mysite.ru/abc/def/news/post - вернет массив [news, post].

Также при разборе урл и получении результирующего массива, если указано расширение файла то оно отбрасывается. Т.е. если в адресной строке - mysite.ru/abc/def/news.php то метод urlParce() вернет массив [news] Таким образом если в каком-либо элементе массива будет точка, то все что после точки будет отброшено. Если набрать mysite.ru/abc/def/news.php/post метод urlParce() вернет массив [news, post]

Теперь коротко о том, как все работает. При создании объекта класса Url вызывается конструктор, который записывает в переменную класса arrServer данные из массива $_SERVER.
При вызове метода urlParce() сначала вызывается метод root(). Его задача выделить путь до исполняемого файла и записать его в свойство root. Дальше вызывается метод requestUri() и тут же возвращается результат.

Методу root() передается имя файла, который сейчас выполняется, относительно корня документов. Для этого используется значение $_SERVER[PHP_SELF]. В любом случае это значение будет содержать полный путь до контроллера. Эта строка разбивается на массив по разделителю (в данном случае разделитель '/') с помощью метода strParce(). Дальше отбрасывается последний элемент массива и массив склеивается в строку с использованием всё того же разделителя. К примеру $_SERVER[PHP_SELF] содержит /abc/def/index.php. Тогда strParce()вернет массив [abc, def, index]. Последний элемент отбрасывается, получаем массив [abc, def]. После склеивания получаем строку /abc/def. Это значение и записывается в свойство root.

Метод requestUri() в качестве аргумента получает значение $_SERVER[REQUEST_URI]. Все что он делает, это обрезает строку, удаляя из нее значение свойства root. Дальше полученная строка передается методу strParce() и возвращает результат, т.е. массив.

Метод strParce() работает так: сначала он с помощью метода changeSymbol() меняет все обратные слеши в полученной строке на '/'. Затем разбивает строку в массив. Далее идет цикл в котором пустые элементы отбрасываются, также производится поиск точки в элементах массива. Все что после точки также отбрасывается. Формируется результирующий массив, который возвращается.

Метод changeSymbol() описывать не буду. Там и так всё понятно...

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

Значение свойства root можно использовать в шаблоне страницы для создания абсолютных путей. К примеру для подключения таблицы стилей вот так:
Code (any language): скопировать код в буфер обмена
<link href="<?=$url -> root?>/css/style.css" rel="stylesheet" type="text/css"/>
Значение, которое возвращает urlParce() можно использовать например так:

Файл index.php
Code (php): скопировать код в буфер обмена
<?
$url = new Url;
$router = $url -> urlParce();

if($router[0] == 'admin'){

  include_once("tpl/admin.htm");
 
}else{

  include_once("tpl/news.htm");
 
}
?>
Плюсы: простота использования. Создал объект, вызвал один метод, всё пользуйся.

Минусы: приходится постоянно прописывать нужную директорию в .htaccess

Признаюсь честно, мне не хватает некоторых знаний в области Web программирования. В частности оправдан ли поиск обратного слеша и замена его на '/' при обработке запросов. Если вводить в адресной строке обратный слеш, то браузеры (Chrome, IE...) его автоматически меняют на нормальный. Если этот поиск и замена не нужны, то можно отказаться от этого функционала и код класса станет более лаконичным.

На этом всё. Буду рад конструктивной критике, замечаниям , дополнениям.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML