Сопоставление нескольких URL-адресов с параметрами с использованием Zend_Controller_Router_Route_Regex в Zend Framework
Я разрабатываю Rest Controller с Zend, и меня смущает сопоставление URL-адресов с маршрутизатором.
В основном я читал о Zend Router и не мог планировать свои URL, чтобы удовлетворить упомянутые маршруты.
Вот некоторые из моих URL-адресов, которые должны быть сопоставлены с маршрутизаторами.
http://localhost/api/v1/tags.xml?abc=true (параметр: abc = true)
http://localhost/api/v1/tags/123456.xml (параметр: 123456.xml)
http://localhost/api/v1/tags/123456/pings.xml (параметры: 123456, pings.xml)
http://localhost/api/v1/tags/123456/pings.xml?a=1&b=2 (параметры: 123456, pings.xml, a = 1, b = 2)
http://localhost/api/v1/tags/123456/pings/count.xml (параметры: 123456, pings, count.xml)
Я планирую так, чтобы для шаблонов URL с 1 по 3 "теги" были контроллером, а для шаблонов с 4 по 6 "pings" - контроллером.
Теперь я не уверен, как настроить маршрутизаторы так, чтобы вышеприведенные сценарии работали. Обратите внимание, что я не могу изменить эти URL. Я могу предложить 100 из моей репутации за хороший ответ.
2 ответа
Первые два URL могут быть объединены в один маршрутизатор.
$r = new Zend_Controller_Router_Route_Regex('api/v1/tags.xml',
array('controller' => 'tags', 'action' => 'index'));
$router->addRoute('route1', $r);
Чтобы различать первые два маршрута, проверьте наличие параметра abc в вашем контроллере тегов. Добавьте следующее в ваш контроллер тегов, index action.
if($this->_getParam('abc') == "true")
{
//route 2
} else {
// route 1
}
Точно так же маршруты 4 и 5 могут быть объединены в один маршрут.
Я объяснил для маршрута 6. Для маршрута 3 вы можете использовать ту же логику.
$r = new Zend_Controller_Router_Route_Regex('api/v1/tags/(.*)/pings/(.*)',
array('controller' => 'pings', 'action' => 'index'),
array(1 => 'param1',2=>'param2')
);
$router->addRoute('route6', $r);
Затем к параметрам можно получить доступ, как показано ниже в контроллере pings.
$this->_getParam('param1') and $this->_getParam('param2')
Для маршрута 5:
$r = new Zend_Controller_Router_Route_Regex('api/v1/tags/(.*)/pings.xml',
array('controller' => 'pings', 'action' => 'index'),
array(1 => 'param1')
);
$router->addRoute('route5', $r);
Параметры (часть URL после?) Не будут обрабатываться в маршрутизаторе. По умолчанию они будут переданы вашему контроллеру.
Чтобы получить значение параметра Specc, переданное в вашем URL, используйте следующее в вашем контроллере.
$this->_getParam('a');
Логика заключается в использовании (.*) В вашем маршруте, назначении им имени параметра и доступе к ним в вашем контроллере.
Вот стартовый фрагмент алгоритма, который выделяет контроллер, индексированные параметры и расширение из запроса, который вы можете включить в расширенную версию Zend_Rest_Route::match()
:
public function match( $request )
{
$path = $request->getPathInfo();
// distill extension (if any) and the remaining path
preg_match( '~(?U:(?<path>.*))(?:\.(?<extension>[^\.]*))?$~', $path, $matches );
$this->_values[ '_extension' ] = isset( $matches[ 'extension' ] ) ? $matches[ 'extension' ] : null;
$path = isset( $matches[ 'path' ] ) ? $matches[ 'path' ] : '';
// split the path into segments
$pathSegments = preg_split( '~' . self::URI_DELIMITER . '~', $path, -1, PREG_SPLIT_NO_EMPTY );
// leave if no path segments found? up to you to decide, but I put it in anyway
if( 0 == ( $length = count( $pathSegments ) ) )
{
return false;
}
// initialize some vars
$params = array();
$controller = null;
// start finding the controller
// (presumes controller found at segment 0, 2, 4, etc...)
for( $i = 0; $i < $length; $i += 2 )
{
// you should probably check here if this is a valid REST controller
// (see Zend_Rest_Route::_checkRestfulController() )
$controller = $params[] = $pathSegments[ $i ];
if( isset( $pathSegments[ $i + 1 ] ) )
{
$params[] = $pathSegments[ $i + 1 ];
}
}
// remove the param which is the actual controller
array_splice( $params, $i - 2, 1 );
// set the controller
$this->_values[ 'controller' ] = $controller;
// merge the params and defaults
$this->_values = array_merge( $this->_values, $params, $this->_defaults );
return $this->_values;
}
Это вряд ли проверено, и, следовательно, не производственный материал, конечно. Но это должно помочь вам начать.
Что это дает вам до сих пор:
Контроллер
Расширение
Индексированные параметры
Что это НЕ дает вам:
Действие (опубликовать, положить, удалить и т. Д. Алгоритм для этого уже находится в Zend_Rest_Route::match()
)
Названные параметры (Zend_Controller_Request_Http
об этом уже позаботится)
РЕДАКТИРОВАТЬ
Я понимаю, что этот ответ пока можно считать немного расплывчатым. Дело в том, чтобы объединить этот алгоритм с match()
алгоритм Zend_Rest_Route
, Но этот код все еще требует большого внимания; вы тоже хотите учесть модули (как это делает Zend_Rest_Route
) и, возможно, даже необязательный baseUrl (не уверен, как ZF на самом деле справляется с этим внутри).