PHALCON MVC structure and start-up process (partial source analysis)

Source: Internet
Author: User
Tags crypt

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
    • forwardMaximum 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\ResponseInterfaceType

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\ResponseInterfaceType

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 Eventapplication: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 Eventapplication:beforeStartModule
      • Call the module initialization method (module.php) registerAutoloaders() andregisterServices()
      • E Trigger Eventapplication: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 Eventapplication:beforeHandleRequest
      • Start Distribution (ETC/DISPATCHER.C)Dispatcher->dispatch()
        • E Trigger Eventdispatch:beforeDispatchLoop
        • Cycle Start single distribution
          • E Trigger Eventdispatch: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 Eventdispatch:beforeExecuteRoute
          • CallController->beforeExecuteRoute()
          • CallController->initialize()
          • E Trigger Eventdispatch:afterInitialize
          • Call the action method
          • E Trigger Eventdispatch:afterExecuteRoute
          • E Trigger Eventdispatch:afterDispatch
        • If there is a forward () within the action, start the next distribution
      • E all distribution ends, triggering eventsdispatch: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 Eventapplication: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:bootApp Launch
  • Routing phase
    • Module start
    • application:beforeStartModuleBefore the module starts
    • application:afterStartModuleAfter the module is started
  • Distribution phase
    • application:beforeHandleRequestBefore entering the dispenser
    • Start distribution
      • dispatch:beforeDispatchLoopBefore the distribution cycle begins
      • dispatch:beforeDispatchBefore a single distribution starts
      • dispatch:beforeExecuteRouteBefore action executes
      • dispatch:afterExecuteRouteAfter action executes
      • dispatch:beforeNotFoundActionAction not found
      • dispatch:beforeExceptionBefore throwing an exception
      • dispatch:afterDispatchOne-time distribution ends
      • dispatch:afterDispatchLoopEnd of distribution cycle
    • application:afterHandleRequestEnd of distribution
  • Rendering phase
    • application:viewRenderBefore rendering begins
  • Send response
    • application:beforeSendResponseBefore the final response is sent

PHALCON MVC structure and start-up process (partial source analysis)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.