3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
12 use Zend\EventManager\EventManagerAwareInterface
;
13 use Zend\EventManager\EventManagerInterface
;
14 use Zend\ServiceManager\ServiceManager
;
15 use Zend\Stdlib\RequestInterface
;
16 use Zend\Stdlib\ResponseInterface
;
19 * Main application class for invoking applications
21 * Expects the user will provide a configured ServiceManager, configured with
22 * the following services:
31 * - MiddlewareListener
34 * The most common workflow is:
36 * $services = new Zend\ServiceManager\ServiceManager($servicesConfig);
37 * $app = new Application($appConfig, $services);
39 * $response = $app->run();
43 * bootstrap() opts in to the default route, dispatch, and view listeners,
44 * sets up the MvcEvent, and triggers the bootstrap event. This can be omitted
45 * if you wish to setup your own listeners and/or workflow; alternately, you
46 * can simply extend the class to override such behavior.
48 class Application
implements
50 EventManagerAwareInterface
52 const ERROR_CONTROLLER_CANNOT_DISPATCH
= 'error-controller-cannot-dispatch';
53 const ERROR_CONTROLLER_NOT_FOUND
= 'error-controller-not-found';
54 const ERROR_CONTROLLER_INVALID
= 'error-controller-invalid';
55 const ERROR_EXCEPTION
= 'error-exception';
56 const ERROR_ROUTER_NO_MATCH
= 'error-router-no-match';
57 const ERROR_MIDDLEWARE_CANNOT_DISPATCH
= 'error-middleware-cannot-dispatch';
62 protected $configuration = null;
65 * Default application event listeners
69 protected $defaultListeners = [
75 'SendResponseListener',
85 * @var EventManagerInterface
90 * @var \Zend\Stdlib\RequestInterface
95 * @var ResponseInterface
100 * @var ServiceManager
102 protected $serviceManager = null;
107 * @param mixed $configuration
108 * @param ServiceManager $serviceManager
109 * @param null|EventManagerInterface $events
110 * @param null|RequestInterface $request
111 * @param null|ResponseInterface $response
113 public function __construct(
115 ServiceManager
$serviceManager,
116 EventManagerInterface
$events = null,
117 RequestInterface
$request = null,
118 ResponseInterface
$response = null
120 $this->configuration
= $configuration;
121 $this->serviceManager
= $serviceManager;
122 $this->setEventManager($events ?
: $serviceManager->get('EventManager'));
123 $this->request
= $request ?
: $serviceManager->get('Request');
124 $this->response
= $response ?
: $serviceManager->get('Response');
128 * Retrieve the application configuration
130 * @return array|object
132 public function getConfig()
134 return $this->serviceManager
->get('config');
138 * Bootstrap the application
140 * Defines and binds the MvcEvent, and passes it the request, response, and
141 * router. Attaches the ViewManager as a listener. Triggers the bootstrap
144 * @param array $listeners List of listeners to attach.
145 * @return Application
147 public function bootstrap(array $listeners = [])
149 $serviceManager = $this->serviceManager
;
150 $events = $this->events
;
152 // Setup default listeners
153 $listeners = array_unique(array_merge($this->defaultListeners
, $listeners));
155 foreach ($listeners as $listener) {
156 $serviceManager->get($listener)->attach($events);
160 $this->event
= $event = new MvcEvent();
161 $event->setName(MvcEvent
::EVENT_BOOTSTRAP
);
162 $event->setTarget($this);
163 $event->setApplication($this);
164 $event->setRequest($this->request
);
165 $event->setResponse($this->response
);
166 $event->setRouter($serviceManager->get('Router'));
168 // Trigger bootstrap events
169 $events->triggerEvent($event);
175 * Retrieve the service manager
177 * @return ServiceManager
179 public function getServiceManager()
181 return $this->serviceManager
;
185 * Get the request object
187 * @return \Zend\Stdlib\RequestInterface
189 public function getRequest()
191 return $this->request
;
195 * Get the response object
197 * @return ResponseInterface
199 public function getResponse()
201 return $this->response
;
205 * Get the MVC event instance
209 public function getMvcEvent()
215 * Set the event manager instance
217 * @param EventManagerInterface $eventManager
218 * @return Application
220 public function setEventManager(EventManagerInterface
$eventManager)
222 $eventManager->setIdentifiers([
226 $this->events
= $eventManager;
231 * Retrieve the event manager
233 * Lazy-loads an EventManager instance if none registered.
235 * @return EventManagerInterface
237 public function getEventManager()
239 return $this->events
;
243 * Static method for quick and easy initialization of the Application.
245 * If you use this init() method, you cannot specify a service with the
246 * name of 'ApplicationConfig' in your service manager config. This name is
247 * reserved to hold the array from application.config.php.
249 * The following services can only be overridden from application.config.php:
252 * - SharedEventManager
253 * - EventManager & Zend\EventManager\EventManagerInterface
255 * All other services are configured after module loading, thus can be
256 * overridden by modules.
258 * @param array $configuration
259 * @return Application
261 public static function init($configuration = [])
263 // Prepare the service manager
264 $smConfig = isset($configuration['service_manager']) ?
$configuration['service_manager'] : [];
265 $smConfig = new Service\
ServiceManagerConfig($smConfig);
267 $serviceManager = new ServiceManager();
268 $smConfig->configureServiceManager($serviceManager);
269 $serviceManager->setService('ApplicationConfig', $configuration);
272 $serviceManager->get('ModuleManager')->loadModules();
274 // Prepare list of listeners to bootstrap
275 $listenersFromAppConfig = isset($configuration['listeners']) ?
$configuration['listeners'] : [];
276 $config = $serviceManager->get('config');
277 $listenersFromConfigService = isset($config['listeners']) ?
$config['listeners'] : [];
279 $listeners = array_unique(array_merge($listenersFromConfigService, $listenersFromAppConfig));
281 return $serviceManager->get('Application')->bootstrap($listeners);
285 * Run the application
287 * @triggers route(MvcEvent)
288 * Routes the request, and sets the RouteMatch object in the event.
289 * @triggers dispatch(MvcEvent)
290 * Dispatches a request, using the discovered RouteMatch and
292 * @triggers dispatch.error(MvcEvent)
293 * On errors (controller not found, action not supported, etc.),
294 * populates the event with information about the error type,
295 * discovered controller, and controller class (if known).
296 * Typically, a handler should return a populated Response object
297 * that can be returned immediately.
300 public function run()
302 $events = $this->events
;
303 $event = $this->event
;
305 // Define callback used to determine whether or not to short-circuit
306 $shortCircuit = function ($r) use ($event) {
307 if ($r instanceof ResponseInterface
) {
310 if ($event->getError()) {
316 // Trigger route event
317 $event->setName(MvcEvent
::EVENT_ROUTE
);
318 $event->stopPropagation(false); // Clear before triggering
319 $result = $events->triggerEventUntil($shortCircuit, $event);
320 if ($result->stopped()) {
321 $response = $result->last();
322 if ($response instanceof ResponseInterface
) {
323 $event->setName(MvcEvent
::EVENT_FINISH
);
324 $event->setTarget($this);
325 $event->setResponse($response);
326 $event->stopPropagation(false); // Clear before triggering
327 $events->triggerEvent($event);
328 $this->response
= $response;
333 if ($event->getError()) {
334 return $this->completeRequest($event);
337 // Trigger dispatch event
338 $event->setName(MvcEvent
::EVENT_DISPATCH
);
339 $event->stopPropagation(false); // Clear before triggering
340 $result = $events->triggerEventUntil($shortCircuit, $event);
343 $response = $result->last();
344 if ($response instanceof ResponseInterface
) {
345 $event->setName(MvcEvent
::EVENT_FINISH
);
346 $event->setTarget($this);
347 $event->setResponse($response);
348 $event->stopPropagation(false); // Clear before triggering
349 $events->triggerEvent($event);
350 $this->response
= $response;
354 $response = $this->response
;
355 $event->setResponse($response);
356 $this->completeRequest($event);
364 public function send()
369 * Complete the request
371 * Triggers "render" and "finish" events, and returns response from
374 * @param MvcEvent $event
375 * @return Application
377 protected function completeRequest(MvcEvent
$event)
379 $events = $this->events
;
380 $event->setTarget($this);
382 $event->setName(MvcEvent
::EVENT_RENDER
);
383 $event->stopPropagation(false); // Clear before triggering
384 $events->triggerEvent($event);
386 $event->setName(MvcEvent
::EVENT_FINISH
);
387 $event->stopPropagation(false); // Clear before triggering
388 $events->triggerEvent($event);