SlideShare a Scribd company logo
Psst! Check this out:
Soon: Zend Server UI - A ZF2 Case Study
ZendPass solves the above problem
Zend Server UI:
A ZF2 Case Study
ZF2.0 Evolution from a developer perspective
v1.1
Yonni Mendes
Thoughts, feedback: yonni.m@zend.com
ZF2 - Highlights
• Modern, up-to-date, hip and upbeat
• Zend & Community
o GitHub, forums
o Freenode #zftalk
• New and interesting toys
o Events
o Services
o Uniform plugins/helpers
• Tried and True concepts
o MVC pattern
o Customizability
ZF2 - Lighter, stronger
ZS5 ZF1 UI ZS6 ZF2 UI
100,657 lines of php code 78,724 lines of php code
8MB of php & phtml files 4.4MB of php & phtml files
1,161 php & phtml files 758 php & phtml files
518 directories
(read: namespaces)
404 directories
(read: namespaces)
* numbers were taken a week ago from the trunk
Eye catchers in ZF2
• Events
o Promote modularity and encapsulation
o Mitigates tight coupling between components
• Di & ServiceManager
o Move object provisioning out of the application
 but not necessarily into the configuration
o Avoid singletons and promote use of factories
o Avoid static calls
• ModuleManager
o Compartmentalize your application
o Promote reuse across applications
Eye catchers: ZendForm
• Complete rewrite
o Decorators were annihilated
o Validators were extracted and are not part of the
element
o Factory functionality in a separate set of classes
o Factory has annotations' support
• However
o No more <?php echo $form ?> :(
o Not even a view helper!
o Some of the elements are tricky to use
 checkbox
 multiple selection
Eye pokers in ZF2
• Lambdas. Lots of Lambdas
o Like really allot of them
• Avoid inheritance
o ServiceManagers hate inheritance
o Inject dependencies instead
Eye pokers in ZF2, more
• No More Brokers
o No more static brokers
o ServiceManagers are the new brokers
o Uniform configuration formats
o Helpers and plugins are sort of the same thing now
• The Framework really likes itself
o Overriding internal functionality / classes is not
immediately obvious
o Some components suffer from lack of extensibility
options, some enforce arbitrary limitations
Initializing a
ZF2 MVC application
Do, do more and don't
Oooh Spooky:
The Skeleton Application
• MVC implementation based on ZF2
• Basic accepted practices
o Modular structure
o Separation of layers and responsibilities
• Getting used to
o Modules and namespaces alignment
o Views and dependencies are separated
• Unzip. Bam! it works
The Initialization
• Module::init()
o Provided by InitProviderInterface
o Called immediately after instantiation
o Gets the module manager as a parameter
o No Events, services have been started yet!
The Initialization, Cont'd
• LoadModules.post event
o Triggered on the shared eventsManager
o After all Module objects were initialized
o Listeners get a generic ManagerEvent parameter
o Configuration has been merged at this point
o Setup application services like logging,
configuration, caching...
The Initialization, Cont'd
• Module::onBootstrap()
o "Should"
o Provided by BootstrapProviderInterface
o Called when called by MvcApplication
o Gets an MvcEvent parameter (Request, response ...)
o Shared ServiceManagers are available at this point
Initialization fact to fun
• Distributed initialization
o Separate bootstrap and init per module
o Attach listeners to 'LoadModules.post' in init()
o Attach listeners to route/dispatch in
onbootstrap()
o Do not attach anything to 'bootstrap' event
• 'LoadModules.post' execution
o Runs all listeners in-order
o Avoid dependencies between modules' initialization
• Template your onBootstrap()
o Add initializers and Abstract Factories to
ZS6 Module::init() function
public function init(ModuleManagerInterface $manager =
null) {
$manager->getEventManager()->
attach('loadModules.post',
array($this, 'initializeConfig'));
...
$manager->getEventManager()->
attach('loadModules.post',
array($this, 'initializeDebugMode'));
}
ZS6 Module::onBootstrap()
public function onBootstrap(EventInterface $e) {
$app = $this->application;
$this->application = $e->getApplication();
$baseUrl = static::config('baseUrl');
$app->getRequest()->setBaseUrl($baseUrl);
...
$this->initializeLog($e);
$this->initializeRouter($e);
$this->initializeSessionControl($e);
$this->initializeACL($e);
$this->initializeView($e);
$this->initializeWebAPI($e);
$this->initializeViewLayout($e);
...
$this->detectTimezone();
}
Failure is NOT an option
Failure during initialization and bootstrap is
problematic. A few ideas:
• Ignore errors
• Stop event propagation
• Signal failure on the event
• Throw an exception (burn!)
• Trigger a new event (dispatch.error)
The failure option
try {
....
} catch (Exception $ex) {// $e is a MvcEvent, $ex is an exception
$events = $this->application->getEventManager();
$error = $e;
$error->setError(ZendMvcApplication::ERROR_EXCEPTION);
$error->setParam('exception', new Exception('..', null, $ex));
$results = $events->trigger(MvcEvent::EVENT_DISPATCH_ERROR,
$error);
$e->stopPropagation(true);
$e->setResult($results);
...
}
Authentication &
Authorization
The three headed dragon
Authentication
requirements
• Multiple users
• Secure passwords
• Different authentication options (simple,
extended - ldap)
• Must provide for WebAPI authentication
• This is NOT session control!
Simple is as simple does
• At first
o Authentication action plugin
o ZendAuthAuthenticationService
o Digest Adapter
• Not good enough for cluster, moved to
DbTable adapter
• Had to extend DbTable and override
o Credential treatment is hardcoded to be in SQL
o Wanted to return an Identity Object, instead of a
string
Extended Authentication
Essentially similar to Simple
• Extended ZendAuthLdap
o Add support for Identity class
o Add groups membership handling for ACL
• Custom authentication for Zend Server
o Specify a custom "Adapter" class in ui configuration
o Support either groups or simple roles
o Example and start up code in github, fork away!
Permissions' requirements
• System wide ACL: affect all aspects of the UI
• Per-Application access for extended
authentication
• Two user "levels"
o Administrator
o Developer
• Administrator has full access to everything
• Developer has access to read-only actions
MVC ACL integration,
cont'd
• ZendPermissionsAcl
o Initialized with permissions' details from database
o Initialization is performed during bootstrap
o Information Tree is immutable, whatever the user
that's logged in - caching in the future?
• MVC actions and ACL
o Events manager to the rescue!
o Call acl::isAllowed() before every action
 Resource: Controller name
 Privilege: Action name
 User role from Identity object
$app->getEventManager()->attach('route',
array($this, 'allow'));
WebAPI output
requirements
• Change output flow without affecting
functionality
o Controller actions should behave in the same way
o Controller output should be uniform regardless of
view script functionality
• Affect rendering behavior from different
stages of execution
o Different output formats (json, xml)
o Different output view scripts
o Different output functionality - view helpers
WebAPI output planning
public function initializeWebAPI(ManagerEvent $e) {
$app = $e->getParam('application');
if ($this->detectWebAPIRequest($app)) {
$app->getEventManager()->
attach('route', array($this,
'limitedWebapiOutput'));
$app->getEventManager()->
attach('dispatch', array($this,'applyWebAPIVersion'));
$app->getEventManager()->
attach('render', array($this, 'applyWebAPILayout'));
}
}
WebAPI output, error
handling
$events = $app->getEventManager();
/// Remove default error handling
...
$exceptionStrategy =$locator-
>get('ZendMvcViewHttpExceptionStrategy');
$exceptionStrategy->detach($events);
....
/// Introduce webapi error handling
$exceptionStrategy =$locator-
>get('WebAPIMvcViewHttpExceptionStrategy');
$events->attachAggregate($exceptionStrategy);
Dependencing your
injection
Di, SM, Locator and other kinky things
D-Wha?!
class IndexController extends ActionController
{
public function indexAction() {
$monitorUiModel = $this->getLocator()-
>get('MonitorUiModelFilteredMapper');
}
}
Locator == Di == Service manager
It's all different names for the same thing
ZF2 Evolution: Using Di
Dependency injection
• Class name / instance name
• Parameters
o Class names or actual values
o constructor parameters
o getter/setter
• Heavy on reflection
• Very strict behavior
ZF2 Di configuration
'definition' => array (
'class' => array (
'ZsdDbConnector' => array(
'methods' => array('factory' => array('required' => true, 'context' =>
array('required' => true)))
),
'PDO' => array('instantiator' => array('ZsdDbConnector', 'factory'))
)
),
'instance' => array(
'zsdDbPDO' => array('parameters' => array('context' => 'zsd')),
'zsdDbDriver' => array('parameters' => array('connection' => 'zsdDbPDO')),
'zsdDbAdapter' => array('parameters' => array('driver' => 'zsdDbDriver')),
'zsdServers_tg' => array('parameters' => array(
'table' => 'ZSD_NODES',
'adapter' => 'zsdDbAdapter',
))
)
ZF2 ServiceManager
compared
array(
'aliases' => array(
'AuthAdapterSimple' => 'AuthAdapterDbTable',
'AuthAdapterExtended' => 'AuthAdapterLdap',
),
'invokables' => array(
'index' => 'ApplicationControllerIndexController',
'Settings' => 'ApplicationControllerSettingsController',
),
'factories' => array(
'ZendAuthenticationAuthenticationService' => function($sm) {
$service = new AuthenticationService();
$sessionConfig = new SessionConfig();
$sessionConfig->setName('ZS6SESSID');
$manager = new SessionManager($sessionConfig);
$service->setStorage(new Session(null, null, $manager));
$service->setMapper($sm->get('MonitorUiModelFilteredMapper'));
return $service;
}
))
Using Service Manager
• Service manager supplants Di
• Tells a human readable "story"
• Sectioned configuration
o invokables
o factories
o abstractFactories
o aliases
o initializers
• Factories can be
o Lambdas
o method/function names
ZS6 Di Evolution
Started with Di, moved to Service Manager
• Transition from Di to SM is difficult
• Similar systems, similar terms, different
results and implementation
• Lots of functionality resided in Di
• Bridge the gap in onBootstrap:
$di = $this->serviceManager->get('Di');
$this->serviceManager->addAbstractFactory(
new DiAbstractServiceFactory($di));
• Factories caveat: does not lend to inheritance
Common initializers, the lack thereof
• Initializers are callables, usually for injecting
objects into "awareness" interfaces
• Load initializers using
ServiceManager::addInitializer
The problem:
• MVC native objects are produced by
different ServiceManagers
• Only the "global" service manager is
immediately available
• Consistency of SM behavior suggests
Common Initializers, solution
$initializers = array(
function ($instance) use ($serviceManager) {
....
},
....
);
$serviceLocators = array(
$serviceManager,
$serviceManager->get('ControllerLoader'),
$serviceManager->get('ControllerPluginManager'),
$serviceManager->get('ViewHelperManager'),
);
foreach ($serviceLocators as $serviceLocator) {
foreach ($initializers as $initializer) {
$serviceLocator->addInitializer($initializer);
}
}
Identity Awareness
Are YOU aware?
Evolving a solution,
requirements
• A user, in Zend Server 6 may be able to
o see only a particular application
 or a group of applications
o Affect the application itself
o Affect application-related information
"Affect" means filter
• The user may opt to filter by application id
• The application must enforce his
permissions on the filter
Evolving a solution,
complications
• A few different components
o Monitor Events
o Monitor Rules
o JobQueue
o Page Cache
o Codetracing
• Each component has a different filter
structure
• Each component handles applications'
relations differently
Solutions, choices and ZF2
• Controller plugin
• Event driven
• Initializer based
The plugin solution
Create an Action Plugin class that accepts the
full list of applications and the mapper's
output
Problems:
• Diabolically complex
o Difficult to extend and scale to other data types
• Different data structures and arbitrary
differences between components
• Breaks MVC: requires the controller to be
involved in business logic
The event driven solution
• Create an event listener class which modifies
a predefined filter structure
• Cause the mapper to throw out an event
before filtering
• The listener modifies the filter by consulting
an available list of allowed applications
• Mapper continues using the filter object
normally
The event driven solution
• Pros
o Centralized functionality
o Modular behavior - attach a listener or don't
o Modular behavior 2 - adding more, future activities
to the filter will be easier
• Cons
o Filters' varying structure means either a complex
listener
or
o Multiple listeners for multiple classes
o Listener's behavior is difficult to change on the fly
 either its hidden and hard to get at
The initializer solution
Introduce the necessary functionality into the
class that performs the operation
• Introduce a new class which can retrieve
application ids from the identity object
o Inject the user's Identity into this class
• Inject the new class into the data mapper
• Implement the identity filter internally in the
mapper
• Continue normally
The initializer solution
Problems
• This is a complex solution
• Requires integration in each mapper
• It requires introducing new dependencies
However
• MVC separation is preserved
• Mapper encapsulation is preserved
• It is easy to extend in an environment with
multiple authentication methods
Thank you!
Thoughts, feedback: yonni.m@zend.com
$this->trigger('complete', array('Thanks!'));

More Related Content

PDF
Side effects-con-redux
PDF
Sane Async Patterns
PDF
Vuejs testing
PPTX
AngularJS with TypeScript and Windows Azure Mobile Services
PPTX
Django + Vue, JavaScript de 3ª generación para modernizar Django
PDF
GDayX - Advanced Angular.JS
PDF
Boost your angular app with web workers
PDF
Workshop 14: AngularJS Parte III
Side effects-con-redux
Sane Async Patterns
Vuejs testing
AngularJS with TypeScript and Windows Azure Mobile Services
Django + Vue, JavaScript de 3ª generación para modernizar Django
GDayX - Advanced Angular.JS
Boost your angular app with web workers
Workshop 14: AngularJS Parte III

What's hot (20)

PPTX
AngularJS Architecture
PDF
Basic Tutorial of React for Programmers
PDF
Introductionandgreetings
PDF
Bonnes pratiques de développement avec Node js
PPTX
AngularJs $provide API internals & circular dependency problem.
PPT
Creating the interfaces of the future with the APIs of today
PPTX
IndexedDB - Querying and Performance
PDF
Behind the curtain - How Django handles a request
PDF
Dependency Injection in PHP - dwx13
PDF
Real World Dependency Injection - phpugffm13
PDF
Promises are so passé - Tim Perry - Codemotion Milan 2016
PPTX
Owl: The New Odoo UI Framework
PPTX
Testable Javascript
PPTX
Workshop 1: Good practices in JavaScript
ZIP
YUI 3
PPTX
Angularjs Performance
PPTX
Effective C++/WinRT for UWP and Win32
PPTX
AngularJS Internal
PPTX
AngularJs
PDF
Ajax Applications with JSF 2 and new RichFaces 4 - Herbstcampus
AngularJS Architecture
Basic Tutorial of React for Programmers
Introductionandgreetings
Bonnes pratiques de développement avec Node js
AngularJs $provide API internals & circular dependency problem.
Creating the interfaces of the future with the APIs of today
IndexedDB - Querying and Performance
Behind the curtain - How Django handles a request
Dependency Injection in PHP - dwx13
Real World Dependency Injection - phpugffm13
Promises are so passé - Tim Perry - Codemotion Milan 2016
Owl: The New Odoo UI Framework
Testable Javascript
Workshop 1: Good practices in JavaScript
YUI 3
Angularjs Performance
Effective C++/WinRT for UWP and Win32
AngularJS Internal
AngularJs
Ajax Applications with JSF 2 and new RichFaces 4 - Herbstcampus
Ad

Viewers also liked (13)

DOCX
Nitin Singla_28072016
PPTX
Agile & What I know about it
PPTX
Zend server 6 compliance
PPTX
The lollipop candies
PDF
PPTX
Tutorial: extending the zend server ui and web api
PPTX
Automating your php infrastructure with the zend server api
PPTX
Apigility & Restfull APIs
DOCX
Angelina rendang
PPTX
The impact of breaking news on audience
PPTX
Presentation1
PPT
Intercultural Communication and Body Language
PPTX
3905 International
Nitin Singla_28072016
Agile & What I know about it
Zend server 6 compliance
The lollipop candies
Tutorial: extending the zend server ui and web api
Automating your php infrastructure with the zend server api
Apigility & Restfull APIs
Angelina rendang
The impact of breaking news on audience
Presentation1
Intercultural Communication and Body Language
3905 International
Ad

Similar to Zend server 6 using zf2, 2013 webinar (20)

PPTX
Intro To Node.js
PDF
Kogito: cloud native business automation
PDF
Symfony 2 (PHP day 2009)
PDF
Javascript Memory leaks and Performance & Angular
PDF
symfony on action - WebTech 207
PPTX
Getting Reactive with CycleJS and XStream
PDF
WebNet Conference 2012 - Designing complex applications using html5 and knock...
PDF
Osiąganie mądrej architektury z Symfony2
PDF
soft-shake.ch - Hands on Node.js
PDF
Symfony 2 (PHP Quebec 2009)
ODP
AngularJs Crash Course
PDF
[2015/2016] JavaScript
PDF
Javascript essential-pattern
KEY
Dancing with websocket
PPT
Understanding Framework Architecture using Eclipse
PDF
JavaScript
PPTX
Adding a modern twist to legacy web applications
PDF
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
PDF
Intro to Laravel 4
PDF
Symfony 2.0
Intro To Node.js
Kogito: cloud native business automation
Symfony 2 (PHP day 2009)
Javascript Memory leaks and Performance & Angular
symfony on action - WebTech 207
Getting Reactive with CycleJS and XStream
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Osiąganie mądrej architektury z Symfony2
soft-shake.ch - Hands on Node.js
Symfony 2 (PHP Quebec 2009)
AngularJs Crash Course
[2015/2016] JavaScript
Javascript essential-pattern
Dancing with websocket
Understanding Framework Architecture using Eclipse
JavaScript
Adding a modern twist to legacy web applications
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
Intro to Laravel 4
Symfony 2.0

Recently uploaded (20)

PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Spectroscopy.pptx food analysis technology
PPTX
Cloud computing and distributed systems.
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Encapsulation theory and applications.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
KodekX | Application Modernization Development
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
NewMind AI Weekly Chronicles - August'25 Week I
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
“AI and Expert System Decision Support & Business Intelligence Systems”
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
MYSQL Presentation for SQL database connectivity
Unlocking AI with Model Context Protocol (MCP)
Digital-Transformation-Roadmap-for-Companies.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf
Spectroscopy.pptx food analysis technology
Cloud computing and distributed systems.
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Spectral efficient network and resource selection model in 5G networks
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Encapsulation theory and applications.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
KodekX | Application Modernization Development
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Chapter 3 Spatial Domain Image Processing.pdf
NewMind AI Weekly Chronicles - August'25 Week I
The AUB Centre for AI in Media Proposal.docx
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...

Zend server 6 using zf2, 2013 webinar

  • 1. Psst! Check this out: Soon: Zend Server UI - A ZF2 Case Study ZendPass solves the above problem
  • 2. Zend Server UI: A ZF2 Case Study ZF2.0 Evolution from a developer perspective v1.1 Yonni Mendes Thoughts, feedback: yonni.m@zend.com
  • 3. ZF2 - Highlights • Modern, up-to-date, hip and upbeat • Zend & Community o GitHub, forums o Freenode #zftalk • New and interesting toys o Events o Services o Uniform plugins/helpers • Tried and True concepts o MVC pattern o Customizability
  • 4. ZF2 - Lighter, stronger ZS5 ZF1 UI ZS6 ZF2 UI 100,657 lines of php code 78,724 lines of php code 8MB of php & phtml files 4.4MB of php & phtml files 1,161 php & phtml files 758 php & phtml files 518 directories (read: namespaces) 404 directories (read: namespaces) * numbers were taken a week ago from the trunk
  • 5. Eye catchers in ZF2 • Events o Promote modularity and encapsulation o Mitigates tight coupling between components • Di & ServiceManager o Move object provisioning out of the application  but not necessarily into the configuration o Avoid singletons and promote use of factories o Avoid static calls • ModuleManager o Compartmentalize your application o Promote reuse across applications
  • 6. Eye catchers: ZendForm • Complete rewrite o Decorators were annihilated o Validators were extracted and are not part of the element o Factory functionality in a separate set of classes o Factory has annotations' support • However o No more <?php echo $form ?> :( o Not even a view helper! o Some of the elements are tricky to use  checkbox  multiple selection
  • 7. Eye pokers in ZF2 • Lambdas. Lots of Lambdas o Like really allot of them • Avoid inheritance o ServiceManagers hate inheritance o Inject dependencies instead
  • 8. Eye pokers in ZF2, more • No More Brokers o No more static brokers o ServiceManagers are the new brokers o Uniform configuration formats o Helpers and plugins are sort of the same thing now • The Framework really likes itself o Overriding internal functionality / classes is not immediately obvious o Some components suffer from lack of extensibility options, some enforce arbitrary limitations
  • 9. Initializing a ZF2 MVC application Do, do more and don't
  • 10. Oooh Spooky: The Skeleton Application • MVC implementation based on ZF2 • Basic accepted practices o Modular structure o Separation of layers and responsibilities • Getting used to o Modules and namespaces alignment o Views and dependencies are separated • Unzip. Bam! it works
  • 11. The Initialization • Module::init() o Provided by InitProviderInterface o Called immediately after instantiation o Gets the module manager as a parameter o No Events, services have been started yet!
  • 12. The Initialization, Cont'd • LoadModules.post event o Triggered on the shared eventsManager o After all Module objects were initialized o Listeners get a generic ManagerEvent parameter o Configuration has been merged at this point o Setup application services like logging, configuration, caching...
  • 13. The Initialization, Cont'd • Module::onBootstrap() o "Should" o Provided by BootstrapProviderInterface o Called when called by MvcApplication o Gets an MvcEvent parameter (Request, response ...) o Shared ServiceManagers are available at this point
  • 14. Initialization fact to fun • Distributed initialization o Separate bootstrap and init per module o Attach listeners to 'LoadModules.post' in init() o Attach listeners to route/dispatch in onbootstrap() o Do not attach anything to 'bootstrap' event • 'LoadModules.post' execution o Runs all listeners in-order o Avoid dependencies between modules' initialization • Template your onBootstrap() o Add initializers and Abstract Factories to
  • 15. ZS6 Module::init() function public function init(ModuleManagerInterface $manager = null) { $manager->getEventManager()-> attach('loadModules.post', array($this, 'initializeConfig')); ... $manager->getEventManager()-> attach('loadModules.post', array($this, 'initializeDebugMode')); }
  • 16. ZS6 Module::onBootstrap() public function onBootstrap(EventInterface $e) { $app = $this->application; $this->application = $e->getApplication(); $baseUrl = static::config('baseUrl'); $app->getRequest()->setBaseUrl($baseUrl); ... $this->initializeLog($e); $this->initializeRouter($e); $this->initializeSessionControl($e); $this->initializeACL($e); $this->initializeView($e); $this->initializeWebAPI($e); $this->initializeViewLayout($e); ... $this->detectTimezone(); }
  • 17. Failure is NOT an option Failure during initialization and bootstrap is problematic. A few ideas: • Ignore errors • Stop event propagation • Signal failure on the event • Throw an exception (burn!) • Trigger a new event (dispatch.error)
  • 18. The failure option try { .... } catch (Exception $ex) {// $e is a MvcEvent, $ex is an exception $events = $this->application->getEventManager(); $error = $e; $error->setError(ZendMvcApplication::ERROR_EXCEPTION); $error->setParam('exception', new Exception('..', null, $ex)); $results = $events->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $error); $e->stopPropagation(true); $e->setResult($results); ... }
  • 20. Authentication requirements • Multiple users • Secure passwords • Different authentication options (simple, extended - ldap) • Must provide for WebAPI authentication • This is NOT session control!
  • 21. Simple is as simple does • At first o Authentication action plugin o ZendAuthAuthenticationService o Digest Adapter • Not good enough for cluster, moved to DbTable adapter • Had to extend DbTable and override o Credential treatment is hardcoded to be in SQL o Wanted to return an Identity Object, instead of a string
  • 22. Extended Authentication Essentially similar to Simple • Extended ZendAuthLdap o Add support for Identity class o Add groups membership handling for ACL • Custom authentication for Zend Server o Specify a custom "Adapter" class in ui configuration o Support either groups or simple roles o Example and start up code in github, fork away!
  • 23. Permissions' requirements • System wide ACL: affect all aspects of the UI • Per-Application access for extended authentication • Two user "levels" o Administrator o Developer • Administrator has full access to everything • Developer has access to read-only actions
  • 24. MVC ACL integration, cont'd • ZendPermissionsAcl o Initialized with permissions' details from database o Initialization is performed during bootstrap o Information Tree is immutable, whatever the user that's logged in - caching in the future? • MVC actions and ACL o Events manager to the rescue! o Call acl::isAllowed() before every action  Resource: Controller name  Privilege: Action name  User role from Identity object $app->getEventManager()->attach('route', array($this, 'allow'));
  • 25. WebAPI output requirements • Change output flow without affecting functionality o Controller actions should behave in the same way o Controller output should be uniform regardless of view script functionality • Affect rendering behavior from different stages of execution o Different output formats (json, xml) o Different output view scripts o Different output functionality - view helpers
  • 26. WebAPI output planning public function initializeWebAPI(ManagerEvent $e) { $app = $e->getParam('application'); if ($this->detectWebAPIRequest($app)) { $app->getEventManager()-> attach('route', array($this, 'limitedWebapiOutput')); $app->getEventManager()-> attach('dispatch', array($this,'applyWebAPIVersion')); $app->getEventManager()-> attach('render', array($this, 'applyWebAPILayout')); } }
  • 27. WebAPI output, error handling $events = $app->getEventManager(); /// Remove default error handling ... $exceptionStrategy =$locator- >get('ZendMvcViewHttpExceptionStrategy'); $exceptionStrategy->detach($events); .... /// Introduce webapi error handling $exceptionStrategy =$locator- >get('WebAPIMvcViewHttpExceptionStrategy'); $events->attachAggregate($exceptionStrategy);
  • 28. Dependencing your injection Di, SM, Locator and other kinky things
  • 29. D-Wha?! class IndexController extends ActionController { public function indexAction() { $monitorUiModel = $this->getLocator()- >get('MonitorUiModelFilteredMapper'); } } Locator == Di == Service manager It's all different names for the same thing
  • 30. ZF2 Evolution: Using Di Dependency injection • Class name / instance name • Parameters o Class names or actual values o constructor parameters o getter/setter • Heavy on reflection • Very strict behavior
  • 31. ZF2 Di configuration 'definition' => array ( 'class' => array ( 'ZsdDbConnector' => array( 'methods' => array('factory' => array('required' => true, 'context' => array('required' => true))) ), 'PDO' => array('instantiator' => array('ZsdDbConnector', 'factory')) ) ), 'instance' => array( 'zsdDbPDO' => array('parameters' => array('context' => 'zsd')), 'zsdDbDriver' => array('parameters' => array('connection' => 'zsdDbPDO')), 'zsdDbAdapter' => array('parameters' => array('driver' => 'zsdDbDriver')), 'zsdServers_tg' => array('parameters' => array( 'table' => 'ZSD_NODES', 'adapter' => 'zsdDbAdapter', )) )
  • 32. ZF2 ServiceManager compared array( 'aliases' => array( 'AuthAdapterSimple' => 'AuthAdapterDbTable', 'AuthAdapterExtended' => 'AuthAdapterLdap', ), 'invokables' => array( 'index' => 'ApplicationControllerIndexController', 'Settings' => 'ApplicationControllerSettingsController', ), 'factories' => array( 'ZendAuthenticationAuthenticationService' => function($sm) { $service = new AuthenticationService(); $sessionConfig = new SessionConfig(); $sessionConfig->setName('ZS6SESSID'); $manager = new SessionManager($sessionConfig); $service->setStorage(new Session(null, null, $manager)); $service->setMapper($sm->get('MonitorUiModelFilteredMapper')); return $service; } ))
  • 33. Using Service Manager • Service manager supplants Di • Tells a human readable "story" • Sectioned configuration o invokables o factories o abstractFactories o aliases o initializers • Factories can be o Lambdas o method/function names
  • 34. ZS6 Di Evolution Started with Di, moved to Service Manager • Transition from Di to SM is difficult • Similar systems, similar terms, different results and implementation • Lots of functionality resided in Di • Bridge the gap in onBootstrap: $di = $this->serviceManager->get('Di'); $this->serviceManager->addAbstractFactory( new DiAbstractServiceFactory($di)); • Factories caveat: does not lend to inheritance
  • 35. Common initializers, the lack thereof • Initializers are callables, usually for injecting objects into "awareness" interfaces • Load initializers using ServiceManager::addInitializer The problem: • MVC native objects are produced by different ServiceManagers • Only the "global" service manager is immediately available • Consistency of SM behavior suggests
  • 36. Common Initializers, solution $initializers = array( function ($instance) use ($serviceManager) { .... }, .... ); $serviceLocators = array( $serviceManager, $serviceManager->get('ControllerLoader'), $serviceManager->get('ControllerPluginManager'), $serviceManager->get('ViewHelperManager'), ); foreach ($serviceLocators as $serviceLocator) { foreach ($initializers as $initializer) { $serviceLocator->addInitializer($initializer); } }
  • 38. Evolving a solution, requirements • A user, in Zend Server 6 may be able to o see only a particular application  or a group of applications o Affect the application itself o Affect application-related information "Affect" means filter • The user may opt to filter by application id • The application must enforce his permissions on the filter
  • 39. Evolving a solution, complications • A few different components o Monitor Events o Monitor Rules o JobQueue o Page Cache o Codetracing • Each component has a different filter structure • Each component handles applications' relations differently
  • 40. Solutions, choices and ZF2 • Controller plugin • Event driven • Initializer based
  • 41. The plugin solution Create an Action Plugin class that accepts the full list of applications and the mapper's output Problems: • Diabolically complex o Difficult to extend and scale to other data types • Different data structures and arbitrary differences between components • Breaks MVC: requires the controller to be involved in business logic
  • 42. The event driven solution • Create an event listener class which modifies a predefined filter structure • Cause the mapper to throw out an event before filtering • The listener modifies the filter by consulting an available list of allowed applications • Mapper continues using the filter object normally
  • 43. The event driven solution • Pros o Centralized functionality o Modular behavior - attach a listener or don't o Modular behavior 2 - adding more, future activities to the filter will be easier • Cons o Filters' varying structure means either a complex listener or o Multiple listeners for multiple classes o Listener's behavior is difficult to change on the fly  either its hidden and hard to get at
  • 44. The initializer solution Introduce the necessary functionality into the class that performs the operation • Introduce a new class which can retrieve application ids from the identity object o Inject the user's Identity into this class • Inject the new class into the data mapper • Implement the identity filter internally in the mapper • Continue normally
  • 45. The initializer solution Problems • This is a complex solution • Requires integration in each mapper • It requires introducing new dependencies However • MVC separation is preserved • Mapper encapsulation is preserved • It is easy to extend in an environment with multiple authentication methods
  • 46. Thank you! Thoughts, feedback: yonni.m@zend.com $this->trigger('complete', array('Thanks!'));