getting started with zf2 - index-of.esindex-of.es/php/zf2_getting_started.pdf · the zf2 way:...

63
Getting Started with ZF2

Upload: others

Post on 14-Jul-2020

13 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Getting Started with

ZF2

Page 2: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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

Page 3: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Getting Started

Page 4: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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

Page 5: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

AND

Configure a web server, or use the PHP 5.4 built-in web

server:

1 cd public2 php -S localhost:8080

Page 6: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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!)

Page 7: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition
Page 8: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

I don't get it

Page 9: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

What's next?

Page 10: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

You probably want to know…

How to create a controller

How rendering works

How to create routes

Page 11: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

We may get to that

But before I tell you about that stuff…

Page 12: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

What is ZF2?

Page 13: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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

Page 14: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

A new core

The ZF1 way:

Singletons, Registries, Hard-Coded

and Soft Dependencies

The ZF2 way:

Event-Driven Services

Page 15: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Services

Page 16: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Why?

Decoupling.

Contract Oriented Design

Favor composition over inheritance

Encourage Dependency Injection, or, more

specifically Inversion of Control

Page 17: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 }

Page 18: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 }

Page 19: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 }

Page 20: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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.

Page 21: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Zend\ServiceManager

Page 22: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

ServiceManager

Very fast - no magic or discovery

Code — don't configure — your injections

Explicit wiring — it's just code — makes debugging

simpler

Page 23: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Explicit Services

Name => object instance

1 array('services' => array(2 'foo' => new Some\Component\Foo(),3 'bar' => $someObjectInstance,4 ));

Page 24: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Invokables

Name => instantiable class

1 array('invokables' => array(2 'foo' => 'Some\Component\Foo',3 ));

Page 25: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 ));

Page 26: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Aliases

Alias => some service or alias

1 array('aliases' => array(2 'my_foo' => 'foo', // alias a service3 'foo_master' => 'my_foo', // alias an alias4 ));

Page 27: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 }

Page 28: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

(Un)Shared Service

Shared by default; choose not to if you want.

1 array('shared' => array(2 'EventManager' => false, // default is true3 ));

Page 29: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 ));

Page 30: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Plugin Managers

Page 31: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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.

Page 32: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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

Page 33: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 )

Page 34: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

EventManager

Page 35: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

EventManager in a Slide

Trigger events

Listen and react to triggered events

Page 36: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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);

Page 37: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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.

Page 38: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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

Page 39: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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()

Page 40: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Shared Event Manager Usage

1 $shared = $events->getSharedManager();2 $shared = $services->get('SharedEventManager');34 $shared->attach('Zend\Stdlib\DispatchableInterface', 'dispatch',5 $callback, $priority);

Page 41: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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

Page 42: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Recap

Page 43: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

We learned all about Services, and how the

ServiceManager manages them.

We learned about Events, the EventManager, and

shared events.

Page 44: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

MVC

Page 45: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Event driven architecture

Everything is an event

Page 46: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Services

Uses ServiceManager to wire default workflow and

event listeners

Developers provide additional services and service

configuration

Controllers are services!

Page 47: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Modules

“A module provides services for the MVC, and wires

event listeners.”

Page 48: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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

Page 49: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Let's create a module

Page 50: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

A little boilerplate:

1 mkdir -p module/MyMarkdown2 touch module/MyMarkdown/Module.php

Page 51: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 }

Page 52: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 );

Page 53: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Usage:

1 <?php // in a view script: ?>2 <?= $this->markdown($this->someMarkdowntext) ?>

Page 54: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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.

Page 55: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

What about

controllers?

Page 56: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Controllers are services

Page 57: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Controllers are boring

Page 58: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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 }

Page 59: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

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.

Page 60: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Resources

Page 61: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

The user guide: http://bit.ly/zf2userguide

Download info: http://bit.ly/zf2downloads

Participate! http://bit.ly/zf2giveback

Page 62: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition

Thank You

Feedback?

@weierophinney on twitter

#zftalk.dev on Freenode IRC

http://framework.zend.com/

Page 63: Getting Started with ZF2 - index-of.esindex-of.es/PHP/ZF2_Getting_Started.pdf · The ZF2 way: Event-Driven Services. Services. Why? Decoupling. Contract Oriented Design Favor composition