getting started with zf2 - index-of.esindex-of.es/php/zf2_getting_started.pdf · the zf2 way:...
TRANSCRIPT
Getting Started with
ZF2
About me
Matthew Weier O'Phinney
(@weierophinney)
PHP Developer since 2000
Zend Framework contributor since
January 2006; project lead since April
2009
Passionate open source advocate and
contributor
Getting Started
Zend Skeleton Application
A skeleton application using the new MVC layer and the
module system.
1 cd my/project/dir2 wget -O ZendSkeletonApplication.tgz ↲3 https://github.com/zendframework/ZendSkeletonApplication/↲4 tarball/master5 tar xzf ZendSkeletonApplication.tgz --strip-components=16 php composer.phar install
AND
Configure a web server, or use the PHP 5.4 built-in web
server:
1 cd public2 php -S localhost:8080
OR
Go to https://my.phpcloud.com/
Click the "New Application" button
Select "Empty Zend Framework 2.0 Application", and
then "Deploy Application"
Test it (and then connect via git or your IDE!)
I don't get it
What's next?
You probably want to know…
How to create a controller
How rendering works
How to create routes
We may get to that
But before I tell you about that stuff…
What is ZF2?
PHP >= 5.3.3
More flexibility
Event and service oriented
Install as much or as little as you want, how you want
More secure
Better defaults for SSL connections
Secure defaults for XML processing
Context-specific escaping mechanisms
A new core
The ZF1 way:
Singletons, Registries, Hard-Coded
and Soft Dependencies
The ZF2 way:
Event-Driven Services
Services
Why?
Decoupling.
Contract Oriented Design
Favor composition over inheritance
Encourage Dependency Injection, or, more
specifically Inversion of Control
Instead of this…
1 public function someAction() {2 $front = Zend_Controller_Front::getInstance();3 $bootstrap = $front->getParam('bootstrap');4 $db = $bootstrap->getResource('db');5 $service = new SomeService($db);6 $this->view->results = $service->doSomething();7 }
We do this…
1 public function setService(SomeService $service) {2 $this->service = $service;3 }45 public function someAction() {6 return array(7 'results' => $this->service->doSomething()8 );9 }
And inject when we retrieve the
controller:
1 function ($controllers) {2 $services = $controllers->getServiceLocator();3 $service = $services->get('SomeService');4 $controller = new SomeController();5 $controller->setService($service);6 return $controller;7 }
Isn't that more code?
It's code with benefits:
You can provide replacements easily.
Which means you can test more easily.
The code for construction happens in one, easily
located, easily reviewed place.
And you can do things like provide separate DB
connections for separate services more easily.
Zend\ServiceManager
ServiceManager
Very fast - no magic or discovery
Code — don't configure — your injections
Explicit wiring — it's just code — makes debugging
simpler
Explicit Services
Name => object instance
1 array('services' => array(2 'foo' => new Some\Component\Foo(),3 'bar' => $someObjectInstance,4 ));
Invokables
Name => instantiable class
1 array('invokables' => array(2 'foo' => 'Some\Component\Foo',3 ));
Factories
Name => callable return object
1 array('factories' => array( 2 'foo' => function ($services) { 3 return new Some\Component\Foo( 4 $services->get('bar') 5 ); 6 }, 7 'bar' => 'Some\Static::method', 8 'baz' => 'Some\Class\Implementing\FactoryInterface', 9 'bat' => 'Some\FunctorClass',10 ));
Aliases
Alias => some service or alias
1 array('aliases' => array(2 'my_foo' => 'foo', // alias a service3 'foo_master' => 'my_foo', // alias an alias4 ));
Abstract Factories
Factory that handles multiple services
1 array('abstract_factories' => array( 2 'Class\Implementing\AbstractFactoryInterface', 3 $someAbstractFactoryInstance, 4 ); 5 6 class SampleAbstractFactory implements AbstractFactoryInterface 7 { 8 public function canCreateServiceWithName( 9 ServiceLocatorInterface $services, $name, $requestedName10 ) {/* */ }11 public function createServiceWithName(/* same signature */)12 { /* */ }13 }
(Un)Shared Service
Shared by default; choose not to if you want.
1 array('shared' => array(2 'EventManager' => false, // default is true3 ));
Initializers
Perform operations on new instances.
1 array('initializers' => array(2 function ($instance, $services) {3 if ($instance instanceof EventManagerAwareInterface) {4 $instance->setEventManager(5 $services->get('EventManager')6 );7 }8 },9 ));
Plugin Managers
What?
A specialized form of ServiceManager
Allows retrieving context-specific objects, using short
names
Typically managed by the application ServiceManager
E.g.: view helpers, controllers, controller plugins, etc.
What you need to know…
Configuration is exactly the same as for the
ServiceManager
The ServiceManager is composed in, and retrievable via
getServiceLocator() in factories
Example:
1 'factories' => array(2 // $helpers is the View Helper plugin manager instance3 'something' => function ($helpers) {4 $services = $helpers->getServiceLocator();5 $model = $services->get('SomeModel');6 $helper = new SomethingHelper($model);7 return $helper;8 },9 )
EventManager
EventManager in a Slide
Trigger events
Listen and react to triggered events
Example
1 $events = new EventManager(); 2 $events->attach('do', function ($e) { 3 $event = $e->getName(); 4 $params = $e->getParams(); 5 printf( 6 'Handled event "%s" with parameters "%s"', 7 $event, 8 json_encode($params) 9 );10 });11 $params = array('foo' => 'bar', 'baz' => 'bat');12 $events->trigger('do', null, $params);
Terminology
An Event is a message encapsulating information.
An Event Manager is an object that aggregates listeners
for one or more named events, and which triggers
events.
A Listener is a callback that can react to an event.
Shared Event Listeners
Use cases:
Often you want to attach to objects not yet created
Often you want to attach to a group of objects
Shared Event Manager
EventManager instances are not shared.
All EventManager instances pulled from the
ServiceManager are injected with a shared
SharedEventManager instance
Retrieve that from the ServiceManager, or an
EventManager instance
API is same, except that you provide a "context" or
"identifier" as a preliminary argument to attach()
Shared Event Manager Usage
1 $shared = $events->getSharedManager();2 $shared = $services->get('SharedEventManager');34 $shared->attach('Zend\Stdlib\DispatchableInterface', 'dispatch',5 $callback, $priority);
Topics not covered:
Listener priority (high, positive integers run first;
negative integers run last)
Aggregates (one object, many listeners, attach once)
Short-circuiting (stop execution within a listener, or
based on the result of a listener)
Wildcard events and identifiers when attaching listeners
Recap
We learned all about Services, and how the
ServiceManager manages them.
We learned about Events, the EventManager, and
shared events.
MVC
Event driven architecture
Everything is an event
Services
Uses ServiceManager to wire default workflow and
event listeners
Developers provide additional services and service
configuration
Controllers are services!
Modules
“A module provides services for the MVC, and wires
event listeners.”
Modules for ZF2
Should do one thing, and do it well.
Modules are "Plug and play" technology
Modules are simply:
A namespace
Containing a single classfile: Module.php
Let's create a module
A little boilerplate:
1 mkdir -p module/MyMarkdown2 touch module/MyMarkdown/Module.php
Edit our new Module classfile:
1 namespace MyMarkdown; 2 3 use Zend\View\Helper\AbstractHelper; 4 5 class Module extends AbstractHelper 6 { 7 public function getViewHelperConfig() { 8 return array('services' => array('markdown' => $this)); 9 }1011 public function __invoke($string = null) {12 require_once 'php-markdown/markdown.php';13 return Markdown($string);14 }15 }
Add it to the application:
1 // in config/application.config.php2 return array(3 'modules' => array(4 'Application',5 'MyMarkdown', // add this!6 ),7 /* ... */8 );
Usage:
1 <?php // in a view script: ?>2 <?= $this->markdown($this->someMarkdowntext) ?>
Actually, that one exists already
https://github.com/EvanDotPro/EdpMarkdown
1 git submodule add↲2 https://github.com/EvanDotPro/EdpMarkdown ↲3 vendor/EdpMarkdown
Add EdpMarkdown to your
config/application.config.php, and you're done.
What about
controllers?
Controllers are services
Controllers are boring
IndexController.php
1 namespace Application\Controller; 2 3 use Zend\Mvc\Controller\AbstractActionController; 4 use Zend\View\Model\ViewModel; 5 6 class IndexController extends AbstractActionController 7 { 8 public function indexAction() 9 {10 return new ViewModel();11 }12 }
The key points are:
Know how to configure services
Know how to wire event listeners
Remember that controllers are services, and now return
information
Modules inform the MVC of services (controllers!) and
wire events.
Resources
The user guide: http://bit.ly/zf2userguide
Download info: http://bit.ly/zf2downloads
Participate! http://bit.ly/zf2giveback
Thank You
Feedback?
@weierophinney on twitter
#zftalk.dev on Freenode IRC
http://framework.zend.com/