在本文中,我们将比较Magento 1和Magento 2 中的路由。
路线确定从搜索系统中定义的当前路线开始。该过程从这里开始:
/vendor/magento/framework/App/FrontController.php
public function dispatch(RequestInterface $request)
{
\Magento\Framework\Profiler::start('routers_match');
$routingCycleCounter = 0;
$result = null;
while (!$request->isDispatched() && $routingCycleCounter++ < 100) {
/** @var \Magento\Framework\App\RouterInterface $router */
foreach ($this->_routerList as $router) {
try {
$actionInstance = $router->match($request);
if ($actionInstance) {
$request->setDispatched(true);
$this->response->setNoCacheHeaders();
if ($actionInstance instanceof \Magento\Framework\App\Action\AbstractAction) {
$result = $actionInstance->dispatch($request);
} else {
$result = $actionInstance->execute();
}
break;
}
} catch (\Magento\Framework\Exception\NotFoundException $e) {
$request->initForward();
$request->setActionName('noroute');
$request->setDispatched(false);
break;
}
}
}
\Magento\Framework\Profiler::stop('routers_match');
if ($routingCycleCounter > 100) {
throw new \LogicException('Front controller reached 100 router match iterations');
}
return $result;
}
在方法dispatch()以及Magento 1文件app / code / core / Mage / Core / Controller / Varien / Front.php中,存在一些匹配项:
- 检查是调度程序的请求($ request-> isDispatched());
- 搜索匹配项($ router-> match($ request))。
与Magento 1相比,Magento 2仅确定了两个路由:
- /vendor/magento/framework/App/Router/Base.php;
- /vendor/magento/framework/App/Router/DefaultRouter.php。
与Magento 1相同,如果未找到路由器,则经过100次迭代后,将显示一条消息。在这里我们可以找到Magento 1的属性:
if ($routingCycleCounter > 100) {
throw new \LogicException('Front controller reached 100 router match iterations');
}
路由过程的主要步骤与Magento 1中的相同:
- 确定模块
- 确定控制器
- 检测动作
- 用于当前请求检测的数据
Magento 2中的路由器初始化与Magento 1中的不同:
protected function _getRoutes($scope = null)
{
$scope = $scope ?: $this->_configScope->getCurrentScope();
if (isset($this->_routes[$scope])) {
return $this->_routes[$scope];
}
$cacheId = $scope . '::' . $this->_cacheId;
$cachedRoutes = unserialize($this->_cache->load($cacheId));
if (is_array($cachedRoutes)) {
$this->_routes[$scope] = $cachedRoutes;
return $cachedRoutes;
}
$routers = $this->_reader->read($scope);
$routes = $routers[$this->_areaList->getDefaultRouter($scope)]['routes'];
$this->_cache->save(serialize($routes), $cacheId);
$this->_routes[$scope] = $routes;
return $routes;
}
public function read($scope = null)
{
$scope = $scope ?: $this->_defaultScope;
$fileList = $this->_fileResolver->get($this->_fileName, $scope);
if (!count($fileList)) {
return [];
}
$output = $this->_readFiles($fileList);
return $output;
}
搜索适当的路由器时发生初始化:
…
while (!$request->isDispatched() && $routingCycleCounter++ < 100) {
/** @var \Magento\Framework\App\RouterInterface $router */
foreach ($this->_routerList as $router) {
try {
$actionInstance = $router->match($request);
if ($actionInstance) {
…
进一步的路由过程类似于Magento 1:
protected function parseRequest(\Magento\Framework\App\RequestInterface $request)
{
$output = [];
$path = trim($request->getPathInfo(), '/');
$params = explode('/', $path ? $path : $this->pathConfig->getDefaultPath());
foreach ($this->_requiredParams as $paramName) {
$output[$paramName] = array_shift($params);
}
for ($i = 0, $l = sizeof($params); $i < $l; $i += 2) {
$output['variables'][$params[$i]] = isset($params[$i + 1]) ? urldecode($params[$i + 1]) : '';
}
return $output;
}
前三个元素被视为主要元素。它们为当前请求定义模块,控制器和操作。
然后根据其moduleFrontName确定模块:
/**
* Searching router args by module name from route using it as key
*/
$modules = $this→_routeConfig→getModulesByFrontName($moduleFrontName);
然后确定当前请求的控制器和动作:
/**
* Going through modules to find appropriate controller
*/
$currentModuleName = null;
$actionPath = null;
$action = null;
$actionInstance = null;
$actionPath = $this->matchActionPath($request, $params['actionPath']);
$action = $request->getActionName() ?: ($params['actionName'] ?: $this->_defaultPath->getPart('action'));
$this->_checkShouldBeSecure($request, '/' . $moduleFrontName . '/' . $actionPath . '/' . $action);
foreach ($modules as $moduleName) {
$currentModuleName = $moduleName;
$actionClassName = $this->actionList->get($moduleName, $this->pathPrefix, $actionPath, $action);
if (!$actionClassName || !is_subclass_of($actionClassName, $this->actionInterface)) {
continue;
}
$actionInstance = $this->actionFactory->create($actionClassName);
break;
}
if (null == $actionInstance) {
$actionInstance = $this->getNotFoundAction($currentModuleName);
if ($actionInstance === null) {
return null;
}
$action = 'noroute';
}
此外,检查是否存在控制器文件以及先前的实现是否存储连接安全:
$this->_checkShouldBeSecure($request, '/' . $moduleFrontName . '/' . $actionPath . '/' . $action);
这意味着路由已处理。确定模块,控制器和操作。此外,正在处理针对当前请求的操作。
// set values only after all the checks are done
$request->setModuleName($moduleFrontName);
$request->setControllerName($actionPath);
$request->setActionName($action);
$request->setControllerModule($currentModuleName);
$request->setRouteName($this->_routeConfig->getRouteByFrontName($moduleFrontName));
if (isset($params['variables'])) {
$request->setParams($params['variables']);
}
return $actionInstance;
控制元素返回以执行操作:
…
if ($actionInstance) {
$request->setDispatched(true);
$this->response->setNoCacheHeaders();
if ($actionInstance instanceof \Magento\Framework\App\Action\AbstractAction) {
$result = $actionInstance->dispatch($request);
} else {
$result = $actionInstance->execute();
}
break;
}
...
确定当前请求的输出位置。