Magento 2 Request Flow
Magento 2 Request Flow#
Request flow - sequence of steps an application takes to process and respond to requests
Required:
index.php -> Bootstrap -> App Class -> Routing
Sometimes:
Controller processing -> Rendering (Container and blocks) -> Output (HTML)
Initiation#
Init phase: Setting u pkey objects: bootstrap object, app object, dependency injection, object manager, log configs etc.
Multiple entry points: index.php
, pub/cron.php
, pub/static.php
and shell commands (bin/magento)
Cron calls go through: ub/cron.php
Calls to satic files go through: pub/static.php
There are 2 index.php
files:
<root>/index.php
<root>/pub/index.php
The Bootstrap.php
file registers the autoloader
Bootstrap creats the ObjectManager
factory: ObjectManager::create()
- di
initialisation happens in the same call
$app = $bootstrap->createApplication('Magento\Framework\App\Http');
create the application
PublicFunction::launch()
are similar to $major->run()
and $app->run()
methods in magento 1.
Routing Phase#
routing - converts a request URL into a style magento can handle and finds class to process it
Goals:
- Defining all available routers
- Converting a URL to Magento style
- Parsing request parameters
- Identifying an action class that will process the URL
Controller - class that contains the execute()
method
Router - class responsible for handling certain types of URL’s
Magento style URL: 3 parts
+ parameters
Eg. catalog/product/view/id/5
Route declaration#
route - declaration of set of pages belonging to a particular module
Defined in routes.xml
Controller Processing#
Controller does not manage data, it manages the parameters and exceptions. It may initiate a main class for category pages.
Launches the rendering process between view and data layers in production.
Steps in rendering and flushing output#
- Front controller (
Magento\Framework\App\FrontController
) dispatches request and gets result object. - The app (
Magento\Framework\App\Http
) in thelaunch()
method copies html to response object. - The bootstrap (
Magento\Framework\App\Bootstrap
) flushes html from response object to browser.
There are multiple result objects that a controller can return.
Best Practice: It is recommended to return a Magento\Framework\Controller\ResultInterface
Request Routing#
Front Controller#
front controllers are used to efficiently handle requests and direct work flows across all pages
responsibilities:
- gathering all routers
- finding matching controller/router
- obtaining generated HTML to the response object
In magento 2, URL rewrites are implemented by a router
High level execution flow#
index.php -> Bootstrap::run() -> App::launch() -> FrontController::dispatch()
Dispatch:
router::match() -> Controler::execute() -> View::loadlayout() -> View->renderLayout() -> Response::sendResponse()
Routing Mechanism#
Router::match()
most useful when looking for the list of routers.
Available routers:
- Base router:
Magento\Framework\App\Router\Base
- Default router:
Magento\Framework\App\Router\DefaultRouter
- CMS router:
Magento\Cms\Controller\Router
- URL rewrite router:
Magento\UrlRewrite\Controller\Router
(new)
The Base router extends RouterInterface
Base router is located lib/internal/Magento/Framework/App/Router/Base.php
(Not in the code)
The router interface is simple in structure; it contains a single method, Router::match()
The default router: Magento/Framework/App/Router/DefaultRouter.php
handles Not Found pages.
Magento 2 allows different handles for “Not Found” pages, eg. Sorry, this product does not exist
or This category does not exist
UrlRewrite Controller#
In magento 1 URL rewrites is implemented in frontController. In magento 2 we have a separate router for processing URL rewrites.
Order of Routing#
frontControler::dispatch()
Base Router
CMS Router
URL Rewrite Router
Default Router
Registering a new router#
- Add it as a parameter to class
Magento\Framework\App\RouterList
by usingetc/frontend/di.xml
of the module
URL Processing#
In magento 2 a single product can have multiple URL’s for SEO and human reading optimization
Structure of URl accepted by base router is:
$baseUrl/$frontName/$controllerName/$actionName/$otherParams
eg: http://magento.dev/catalog/product/view/id/1
CMS Router#
Pertinent code:
$request->setModuleName(‘cms’)
->setControllerName(‘page’)
->setActioName(‘view’)
->setParam(‘page_id’;$pageid);
Exercise: modify the not found page to forward to the home page#
Easiest way is to change /web/default/noroute
Controller Architecture#
Controller is a class specific to a URL or group of URL’s
A Controller can only process a single action. One class per action.
Eg. Magento\Catalog\Controller\Product\View
Action classes / Controllers#
Action classes include:
execute()
method- Constructor (dependencies injected using DI)
- Extra methods and variables
Usually extends Magento\Framework\App\Action\Action
. Which itself extends Magento\Framework\App\Action\AbstractAction
which implements Magento\Framework\App\ActionInterface
ActionInterface
has two methods: dispatch()
and getResponse()
Action\AbstractAction#
- Obtains request and response objects using DI
- Contains the method
getRequest()
andgetResponse()
- must call parent class
Action\Action#
- Implements
dispatch()
method
High Level execution flow#
- Router::match() -> Controller::dispatch() -> Controller::execute()
Action Wrappers#
If controller does not extend Action/Action
but directly implements ActionInterface
, it must implement dispatch()
method with specific logic.
Key result objects#
- Page: Html output
$page = $this->pageFactory->create()
- Json: For JSON database
$result = $this->jsonFactory->create(); return $result->setData($data);
- Forward: internal redirect to another controller
$result = $this->forwardFactory->create(); $result->forward('some/new/route'); return $result;
- Redirect: Physically redirect customers browser to another URL:
$result = $this->redirectFactory->create(); $result->setUrl('some/new/url'); return $result;
Types controllers#
- Frontend
- Backend - must support ACL
Backend AbstractAction#
- Constructor with extra objects injected
- Contains the new
dispatch()
method - Contains the
_isAllowed()
method - own implementation of
redirect()
andforward()
Asigned Modules#
routerConfig
is injected with DI
matchAction()
will perform 2 calls:
Router\Base::matchModuleFrontName()
Router\Config::getModulesByFrontName()
Debugging the matching controller process#
- Check the
frontName
is correct - Check the list of available modules
- Check path name for each module
- Check whether controlled being debugged is listed and whether class exists
Creating controllers#
- Create
routes.xml
- Create the correct action class and implement an
execute()
method - Test
routes.xml:
<?xml version="1.0"?>
<!--
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="catalog" frontName="catalog">
<module name="Magento_Catalog" />
</route>
</router>
</config>
specify the id
of the router, the frontName
and the module
name
standard
means the base
router
Above tells magento it is ready to process URL that starts with catalog
- frontName is connected to the module
- ActionPath is connected to the folder/subfolder of Controller folder of module
- Action is connected to the PHP class
Controller must extend Magento\Framework\App\Action\Action
and must implement execute()
Testing#
Enter the URL: frontName/actionPath/action
Customize existing controllers#
Controllers are same as any other class in Magento 2. So customised in the same way using preferences
or plugins
URL Rewrites#
Making complicated URL’s more user-friendly: shorter, more descriptive and easier to remember
Magento allows you to specify a URL key
Process Flow#
Browser sends request to server which requires Magento\UrlRewrite\Controller\Router
Then it accesses the database: url_rewrite
Url Finder is an instance of Magento\UrlRewrite\Model\Storage\DbStorage
Exercise: Add a rewrite for the ‘Hell World’ Controller#
INSERT INTO url_rewrite SET request_path=’testpage.html’, target_path=’test/action/index’,
redirect_type=0, store_id=1, is_autogenerated=0;