Phalcon itself supports the creation of multiple forms of Web application projects to address different scenarios, including mini-applications, single-module standard applications, and more complex multi-module applications
Create a project
Phalcon environment configuration after installation, a standard Phalcon multi-module application can be generated from the command line
--type modules
The entry file is public/index.php
, simplified after a total of 5 lines, including the entire Phalcon start-up process, the following will be described in order
require __DIR__ . ‘/../config/services.php‘;$application = new Phalcon\Mvc\Application();$application->setDI($di);require __DIR__ . ‘/../config/modules.php‘;echo $application->handle()->getContent();
di registration Phase
All Component Services of Phalcon are organized through DI (Dependency injection), which is the approach used by most mainstream frameworks today. With Di, you have the flexibility to control the services in the framework: which needs to be enabled, what is not enabled, the internals of the component, and so on, so Phalcon is a loosely coupled, replaceable framework that completely replaces any of the components in MVC with Di.
require __DIR__ . ‘/../config/services.php‘;
This file is registered by default Phalcon\Mvc\Router
(routing), Phalcon\Mvc\Url
(URL), Phalcon\Session\Adapter\Files
(Session) three most basic components. At the same time, when MVC starts, there are many services that are registered by default in Di, and all currently registered services can be obtained through DI:
$services = $application->getDI()->getServices();foreach($services as $key => $service) { var_dump($key); var_dump(get_class($application->getDI()->get($key)));}
Print See Phalcon also registered with the following services:
dispatcher
: Phalcon\Mvc\Dispatcher
distribution Service, distributing the results of a route hit to the corresponding controller
modelsManager
: Phalcon\Mvc\Model\Manager
Model Management
modelsMetadata
: Phalcon\Mvc\Model\MetaData\Memory
ORM Table Structure
response
: Phalcon\Http\Response
Response
cookies
: Phalcon\Http\Response\Cookies
Cookies
request
: Phalcon\Http\Request
Request
filter
: Phalcon\Filter
user-submitted data can be filtered
escaper
: Phalcon\Escaper
Escape Tool
security
: Phalcon\Security
password hash, prevent CSRF, etc.
crypt
: Phalcon\Crypt
Encryption algorithm
annotations
: Phalcon\Annotations\Adapter\Memory
Annotation Analysis
flash
: Phalcon\Flash\Direct
Prompt Information output
flashSession
: Phalcon\Flash\Session
prompt message to delay output via session
tag
: Phalcon\Tag
Common Helper for view
Each of these services can be replaced by DI. Next, instantiate a standard MVC application and inject our defined di in
$application = new Phalcon\mvc\application ();
$application->setdi ($di);
Module Registration Phase
Like Di, Phalcon recommends registering all the required modules by introducing a separate file:
require __DIR__ . ‘/../config/modules.php‘;
The contents of this file are as follows
$application->registermodules (Array (
' base ' = = Array (
' ClassName ' = ' cn\liuxue\site\base\module ',
' Path ' = __dir__. ‘/.. /apps/base/module.php '
),
Front desk
' Front ' = Array (
' ClassName ' = ' cn\liuxue\site\front\module ',
' Path ' = __dir__. ‘/.. /apps/www/module.php '
),
Background
' Backend ' = Array (
' ClassName ' = ' cn\liuxue\site\backend\module ',
' Path ' = __dir__. ‘/.. /apps/admin/module.php '
),
Cms
' cms ' = = Array (
' ClassName ' = ' cn\liuxue\site\cms\module ',
' Path ' = __dir__. ‘/.. /apps/cms/module.php '
),
));
You can see that the Phalcon so-called module registration, in fact, just tell the framework of the MVC module where the boot file Module.php
and the class name is.
MVC phase
$application->handle()
是整个MVC的核心,这个函数中处理了路由、模块、分发等MVC的全部流程,处理过程中在关键位置会通过事件驱动触发一系列application:
事件,方便外部注入逻辑,最终返回一个Phalcon\Http\Response
。整个handle
方法的过程并不复杂,下面按顺序介绍:
Basic Checksfirst, the DI is checked, and if there is no di injection, an error is thrown
A Dependency Injection object is required to access internal services
Then start Eventsmanager from Di and trigger the event via Eventsmanagerapplication:boot
Routing phase
Next, go to the routing stage, get the routing service from Di router
, pass the URI in to the route, and call the route handle()
method.
The handle method of routing is responsible for converting a URI to the corresponding module, Controller, action, etc. according to the routing configuration, which next checks whether the route hit a module and Router->getModuleName()
obtains the module name.
If the module is present, it enters the module start-up phase or goes directly to the distribution stage.
Notice that, in Phalcon, the module starts up behind the routing , which means that the Phalcon module function is weak, we cannot register the global service in one of the modules that are not started, or even simply call another non-starter module in the current module. This is probably the biggest problem in the design of Phalcon module function, the solution is not in the scope of this article, and will be introduced in another article.
Module start
The event is triggered first when the module is started application:beforeStartModule
. After the event is triggered to check the correctness of the module, according to the modules.php
definition of, and className
so on, the path
module boot file loaded in, and invoke the module boot file must exist methods
Phalcon\Mvc\ModuleDefinitionInterface->registerAutoloaders ()
Phalcon\Mvc\ModuleDefinitionInterface->registerServices (Phalcon\DiInterface $dependencyInjector)
registerAutoloaders()
Used to register namespaces within the module for automatic loading. registerServices ()
for registering in-module services, registerServices ()
registering and defining the view
path to the service and template in the official sample, and registering the database connection service db
and setting the database connection information.
Trigger event after module start application:afterStartModule
, enter distribution phase
Distribution phase (Dispatch)
The distribution process Phalcon\Mvc\Dispatcher
is done by (the dispatcher), so-called distribution, in Phalcon is essentially the dispatcher based on the result of the route hit, call the corresponding controller/action, and finally get the result of the Action return.
The view is first prepared before distribution, although the view is theoretically in the last part of MVC, but if any problems occur during the distribution process, it is usually necessary to display the problem, so the view must be started early in this session. Phalcon does not prepare the default view service and needs to be injected externally, in the multi-module demo, the official recommendation of view injection is done during the module startup phase. If it is a single-module application, it can be injected in the first di phase.
If there is always no view injection, an error is thrown
Service ' View ' is not found in the dependency injection container
Causes the distribution process to break directly.
Distribution needs to be Dispatcher,dispatcher also obtained from Di. The parameters (Namespacename/modulename/controllername/actionname/params) obtained in router are then copied to dispatcher.
The method of the view is called before the distribution begins start()
. Refer to the view related documents, in fact, Phalcon\Mvc\View->start()
PHP output buffer function is ob_start
a simple package, the distribution process all the output will be staged into the buffer.
Events are also triggered before distribution starts application:beforeHandleRequest
.
The formal start of the distribution is called Phalcon\Mvc\Dispatcher->dispatch()
.
Distribution processing within the dispatcher
When you enter dispatcher, you will find that dispatcher further subdivides the entire distribution process and, in the process of distribution, triggers a very wide number of distribution events that can be more carefully controlled through these distribution events. Some events provide an interruptible mechanism to false
skip the dispatcher distribution process as long as it is returned.
Because the use of the action can be used in distribution Phalcon\Mvc\Dispatcher->forward()
, the distribution is implemented internally through a loop and finished
determines whether to continue distribution by detecting a global tag. Distribution does not end when the following conditions are available:
- Controller throws exception
forward
Maximum number of layers (256 times)
- All action calls are complete
Render Stage View Render
After the distribution is finished, it is triggered and application:afterHandleRequest
then Phalcon\Mvc\Dispatcher->getReturnedValue()
processed by obtaining the results returned by the distribution process.
Because the action's logic is outside the framework, the return value of the action cannot be expected, so this is done by distinguishing whether the return value implements the Phalcon\Http\ResponseInterface
interface.
When the action returns a non-
Phalcon\Http\ResponseInterface
Type
The return value is considered invalid at this point, and the render process is re-dispatched by view itself, triggering the application:viewRender
event while taking Controllername/actionname/params as Phalcon\Mvc\View->render()
the entry parameter from dispatcher.
Phalcon\Mvc\View->finish()
the receive of the end buffer is called after render is complete.
Next, get the Resonse service from Di and place Phalcon\Mvc\View->getContent()
the acquired content into the response.
When the action returns a
Phalcon\Http\ResponseInterface
Type
The response returned by the action will be the final response, and the new response will not be rebuilt.
return response
Through the preceding process, no matter how many branches are experienced in the middle, it will eventually be aggregated into a unique response. This will trigger and application:beforeSendResponse
call the
Phalcon\Http\Response->sendHeaders()
Phalcon\Http\Response->sendCookies()
Sends the header information of the HTTP message in advance. At this point, the Application->handle()
processing of the request is all over and a response is returned to the outside Phalcon\Http\Response
.
Send response
HTTP headers usually send the contents of the response:
echo $application->handle()->getContent();
This is the complete MVC process for the Phalcon framework.
Process Control
Analyzing the start-up process of MVC is no doubt that there are two ways to better grasp and control the process:
Custom Startup
According to the above process, we can actually fully implement $application->handle()->getContent()
this process, here is a simple alternative, the code temporarily does not consider the triggering of the event.
Roter$router =$di [' Router '];$router->handle ();Module handle$modules =$application->getmodules ();$routeModule =$router->getmodulename ();if (Isset$modules [$routeModule])) {$moduleClass =New$modules [$routeModule] [' ClassName '] ();$moduleClass->registerautoloaders ();$moduleClass->registerservices ($DI);}Dispatch$dispatcher =$di [' Dispatcher '];$dispatcher->setmodulename ($router->getmodulename ());$dispatcher->setcontrollername ($router->getcontrollername ());$dispatcher->setactionname ($router->getactionname ());$dispatcher->setparams ($router->getparams ());View$view =$di [' View ']; $view->start (); $controller = $dispatcher->dispatch (); Not able to call render in controller or else would repeat output$view->render ( $dispatcher->getcontrollern Ame (), $dispatcher->getactionname (), $dispatcher->getparams ()); $view->finish (); $response = $di [' response ']; $response->setcontent ($view->getcontent ()); $response->sendheaders (); echo $response->getcontent ();
Process List
To facilitate the search, organize the entire process into a tree list as follows:
- Initialize di (config/services.php)
$di = new FactoryDefault();
- Set up routes
$di[‘router‘] = function () {}
- Set URL
$di[‘url‘] = function () {}
- Set session
$di[‘session‘] = function () {}
- Initialize Application (public/index.php)
- Instantiate an app
$application = new Application();
- Inject di
$application->setDI($di);
- Registration Module (config/modules.php)
$application->registerModules()
- Start Application (EXT/MVC/APPLICATION.C)
$application->handle()
- Check di
- E Trigger Event
application:boot
- Routing start
$di[‘router‘]->handle()
- Gets the module name
$moduleName = $di[‘router‘]->getModuleName()
, if none is obtained from the $application->getDefaultModule
- Module start (if route hit)
- E Trigger Event
application:beforeStartModule
- Call the module initialization method (module.php)
registerAutoloaders()
andregisterServices()
- E Trigger Event
application:afterStartModule
- Distribute
- Initialize view
- Initializes the dispatcher, copying the parameters from the router to the dispatcher
- Call the view
View->start()
open buffer
- E Trigger Event
application:beforeHandleRequest
- Start Distribution (ETC/DISPATCHER.C)
Dispatcher->dispatch()
- E Trigger Event
dispatch:beforeDispatchLoop
- Cycle Start single distribution
- E Trigger Event
dispatch:beforeDispatch
- The complete class and method name is obtained according to the module, Namespace, Controller, and action carried by dispatcher, and if not found, the event E
dispatch:beforeException
is triggered.
- E Trigger Event
dispatch:beforeExecuteRoute
- Call
Controller->beforeExecuteRoute()
- Call
Controller->initialize()
- E Trigger Event
dispatch:afterInitialize
- Call the action method
- E Trigger Event
dispatch:afterExecuteRoute
- E Trigger Event
dispatch:afterDispatch
- If there is a forward () within the action, start the next distribution
- E all distribution ends, triggering events
dispatch:afterDispatchLoop
- Application get the output after distribution
$dispatcher->getReturnedValue()
- E Trigger Event
application:afterHandleRequest
distribution ended
- Render, Appliction if the return of the type is obtained from the distribution
Phalcon\Http\ResponseInterface
, the rendering ends directly
- E Trigger Event
application:viewRender
distribution ended
- Called
Phalcon\Mvc\View->render()
, the entry parameter is dispatcher Controllername/actionname/params
- Call
Phalcon\Mvc\View->finish()
the end buffer for the receive
- Prepare for response
- Will
Phalcon\Mvc\View->getContent()
pass Phalcon\Http\Response->setContent()
into the response
- E Trigger Event
application:beforeSendResponse
- Call
Phalcon\Http\Response->sendHeaders()
Send Header
- Call to
Phalcon\Http\Response->sendCookies()
send a cookie
- Returns the prepared response as
$application->handle()
a return value
- Send response
echo $application->handle()->getContent();
MVC Events
The advantage of Phalcon as a C-extended framework is high performance, although we can implement the entire boot ourselves in the previous way, but the better way is to avoid replacing the contents of the framework itself with event-driven.
The following is a review of the entire MVC process involved in the listener can be monitored events, according to different needs to choose corresponding events as a starting point:
- DI injection
application:boot
App Launch
- Routing phase
- Module start
application:beforeStartModule
Before the module starts
application:afterStartModule
After the module is started
- Distribution phase
application:beforeHandleRequest
Before entering the dispenser
- Start distribution
dispatch:beforeDispatchLoop
Before the distribution cycle begins
dispatch:beforeDispatch
Before a single distribution starts
dispatch:beforeExecuteRoute
Before action executes
dispatch:afterExecuteRoute
After action executes
dispatch:beforeNotFoundAction
Action not found
dispatch:beforeException
Before throwing an exception
dispatch:afterDispatch
One-time distribution ends
dispatch:afterDispatchLoop
End of distribution cycle
application:afterHandleRequest
End of distribution
- Rendering phase
application:viewRender
Before rendering begins
- Send response
application:beforeSendResponse
Before the final response is sent
PHALCON MVC structure and start-up process (partial source analysis)