Позвольте всобачить сюда свой велосипед. Так сказать, самый сок.
Пример разбора параметров $_GET:
<?php
class AppRequest {
protected $_get;
/**
* Normalizes the request data
* This method strips off slashes in request data if get_magic_quotes_gpc() returns true
*/
protected function normalizeRequest() {
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
if(isset($_GET)) {
$_GET = $this->stripSlashes($_GET);
}
}
if(isset($_GET)) {
$this->_get = $_GET;
}
}
/**
* Returns the named GET parameter value
* If the GET parameter does not exist, the second parameter to this method will be returned
* @param string $name the GET parameter name
* @param mixed|null $default the default parameter value if the GET parameter does not exist
* @return mixed|null the GET parameter value
*/
public function getQueryVar($name, $default = null) {
if (isset($this->_get[$name])) {
return $this->_get[$name];
}
return $default;
}
/**
* Returns the request URI portion for the currently requested URL
* @return string the request URI portion for the currently requested URL
*/
public function getRequestUri() {
static $requestUri;
if (!isset($requestUri)) {
if(isset($_SERVER['REQUEST_URI'])) {
$requestUri = $_SERVER['REQUEST_URI'];
if(!empty($_SERVER['HTTP_HOST'])) {
if(strpos($requestUri, $_SERVER['HTTP_HOST']) !== false) {
$requestUri = preg_replace('/^\w+:\/\/[^\/]+/', '', $requestUri); // remove schema and host name "schema://host/"
}
} else {
$requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $requestUri); // remove schema and host name "schema://host/"
}
}
}
return $requestUri;
}
}
весь код класса AppRequest
Вариант логики разбора строки URL:
Если есть какая-нибудь логика для коротких человеко-читаемых URL, то надо привести их к формату
controller/action + все дополнительные параметры из URL перенести в переменные $_GET или завести для них отдельный специальный массив в класса AppRequest. Такое можно сделать путём статического разбора строки или регулярными выражениями.
Пример:
на вход / -> на выход home/index
на вход /my-home-page/ -> на выход home/welcome
на вход /photo/summer.jpg -> на выход gallery/view + $_GET['image-alias'] = 'summer.jpg'
на вход /wiki/path/to/article.html -> на выход wiki/view + $_GET['page-alias'] = 'path/to/article'
После этого преобразовать имя контроллера в имя класса, а имя действия - в метод (как в моём велосипеде).
class HomeController {
function indexAction() {
echo "Welcome!";
}
}
Полный пример разбора
в классе AppRouter +
файл конфигурации с правилами
Пример правил для указанных выше 4х случаев:
// Incoming URL mathing rules
$rules = array(
// if request URI is empty
'' => array('home', 'index'), // -> код контролера + код действия
// if request URI looks like /my-home-page/
'/^my-home-page$/' => array('HomeController', 'indexAction'), // -> имя класса контроллера + имя функции
// if request URI looks like /photo/summer.jpg
'/^/photo/(?<alias>.+)$/' => array('gallery', 'view', array('image-alias' => ':alias')),
// if request URI looks like /wiki/path/to/article.html
'^/wiki/(?<alias>.+)\.html$' => array('wiki', 'view', array('page-alias' => ':alias')),
);
А можно поменять роутинг так, чтобы под каждое действие был отдельный класс
class HomeIndex {
function run() {
return new AppResponse("Welcome!");
}
}
В некоторых микро-фреймворках можно даже функции назначать
function home_index() {
return new AppResponse("Welcome!");
}
$routes = array(
'/my-home-page/' => 'home_index',
);
И даже использовать анонимные функции, тогда у них вся логика приложения вообще в один конфигурационный файл вмещается
$routes = array(
'/my-home-page/' => function() { return new AppResponse("Welcome!"); },
);