Have you been working with other frameworks and feel ready to try something new? Why not try Zend Framework? Not only can you use it for the full stack of your application, but you can pull out the individual components into your existing application. Get ready for a course on how to build an ZF2 application from the ground up — from the basics of an MVC app to the more advanced components. When you leave this tutorial, you will have a great grasp on how the framework is structured
5. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
INTRO TO ZEND FRAMEWORK 2
▸ Release in Fall 2012
▸ Updated modules from Zend Framework 1
▸ Collection of Individual components
▸ PSR-0 Compliant
SOME BASICS
5
6. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
INTRO TO ZEND FRAMEWORK 2
GETTING STARTED
▸ Using the skeleton app
cd my/project/dir
git clone git://github.com/zendframework/ZendSkeletonApplication.git
cd ZendSkeletonApplication
php composer.phar install
▸ God Mode (aka Composer):
"require": {
"zendframework/zendframework": "~2.5"
}
6
7. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
FILE STRUCTURE
▸ config - stores global config options
▸ data - cache, logs, session files
▸ module - your custom modules
▸ public - HTML, CSS, JS, Images
▸ test - Integration tests and test bootstrap
INTRO TO ZEND FRAMEWORK 2 7
8. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
INTRO TO ZEND FRAMEWORK 2
APPLICATION BASICS
▸ At its core, ZF2 applications have 6 dependancies:
1. ZendConfig - a Traversable object containing merged config
2. ZendServiceManager - A Service Locator for loading/creating objects
3. ZendEventManager - An Event dispatcher for controlling application flow
4. ZendModuleManager - Used for loading/finding configured modules
5. Request - Helper for managing the incoming request
6. Response - Helper for returning a response
8
14. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
DEPENDENCY INJECTION - FOR THOSE WHO DON'T KNOW
▸ Instead of creating all the objects needed by a class, you "inject" a created
object that the class knows how to interact with it
▸ Makes testing easier (you are writing tests correct?)
▸ Code changes are a breeze
▸ Reduces class coupling
14
16. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
DEPENDENCY INJECTION - __CONSTRUCT
class MapService
{
protected $map;
public function __construct(GoogleMaps $map) {
$this->$map = $map;
}
public function getLatLong($street, $city, $state ) {
return $this->map->getLatLong($street . ' ' . $city .
' ' . $state);
}
}
16
17. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
DEPENDENCY INJECTION - SETTERS
class MapService
{
protected $map;
public function setMap(GoogleMaps $map) {
$this->$map = $map;
}
public function getMap() {
return $this->map;
}
public function getLatLong($street, $city, $state ) {
return $this->getMap()->getLatLong($street . ' ' . $city . ' ' . $state);
}
}
17
18. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
WHAT IS A SERVICE LOCATOR
▸ Purpose - "To implement a loosely coupled architecture in order to get better
testable, maintainable and extendable code. DI pattern and Service Locator
pattern are an implementation of the Inverse of Control pattern." *
▸ Keeps DI Simple and clean
▸ Only has two methods: get() and has()
18
* https://github.com/domnikl/DesignPatternsPHP/tree/master/More/ServiceLocator
19. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
WHAT IS IN THE SERVICE MANAGER
▸ Invokables - Objects that can just be called via "new <class_name>"
▸ Factories - a class that creates another (follows the factory pattern)
▸ Abstract Factories - Factories that create many objects using a config
▸ Initializers - Used to add additional dependancies after the object is created
(ex. adding logging to classes with out having a huge dependency list)
▸ Delegators - wrappers that adds more functionality to existing objects
▸ Aliases - simpler names for services
19
21. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
REGISTERING SERVICES - THE WRONG WAY!
'factories' => [
'MyModuleMyService' => function
($sm) {
// do crazy things to build
// this class and slow down
// your application
return $service;
}
],
21
22. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
REGISTERING SERVICES - THE WRONG WAY!
▸ SERIOUSLY DON'T USE CLOSURES TO REGISTER SERVICES
▸ YOU MIGHT AS WELL USE TABS
▸ LIKE EVER
22
23. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
REGISTERING SERVICES - CONCRETE OBJECT
use ZendServiceManagerServiceManager;
$serviceManager = new ServiceManager();
//sets the created object instead of having the SM buildone
$fooBar = new stdClass();
$serviceManager->setService('FooBar', $fooBar);
23
24. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
REGISTERING SERVICES - IN CODE
use ZendServiceManagerServiceManager;
$serviceManager = new ServiceManager();
$serviceManager->setFactory('MyModuleMyService', 'MyModuleMyServiceFactory');
$serviceManager->setInvokableClass('FooBar', 'stdClass');
$serviceManager->addAbstractFactory('ZendLogLoggerAbstractServiceFactory');
$serviceManager->addDelegator('MyModuleMyService', 'MyModuleMyServiceDelegator');
$serviceManager->setAlias('MyService', 'MyModuleMyService');
24
25. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
FACTORIES
▸ Contains the code to build the object
▸ The ServiceManager is passed in to the create function
▸ can either implement ZendServiceManagerFactoryInterface or just implement
__invoke
25
26. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
ABSTRACT FACTORIES
▸ Allows one factory that builds multiple objects based on a config
▸ Prevents writing multiple factories that do similar functions based on a config
▸ MUST Implement ZendServiceManagerAbstractFactoryInterface
▸ defines canCreateServiceWithName() and createServiceWithName()
26
27. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
ABSTRACT FACTORIES
use ZendDbTableGatewayTableGateway;
use ZendServiceManagerFactoryInterface;
use ZendServiceManagerServiceLocatorInterface;
class ProjectsTableFactory implements FactoryInterface {
public function createService(ServiceLocatorInterface $serviceLocator) {
$adapter = new $serviceLocator->get('ZendDbAdapterAdapter');
return new TableGateway('projects', $adapter);
}
}
class CategoriesTableFactory implements FactoryInterface {
public function createService(ServiceLocatorInterface $serviceLocator) {
$adapter = new $serviceLocator->get('ZendDbAdapterAdapter');
return new TableGateway('categories', $adapter);
}
}
27
28. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
ABSTRACT FACTORIES
use ZendDbTableGatewayTableGateway;
use ZendServiceManagerAbstractFactoryInterface;
use ZendServiceManagerServiceLocatorInterface;
class TableAbstractFactory implements AbstractFactoryInterface {
public function canCreateServiceWithName(ServiceLocatorInterface $sl, $name, $requestedName)
{
return preg_match("/Table$/", $requestedName);
}
public function createServiceWithName(ServiceLocatorInterface $sl, $name, $requestedName) {
$adapter = $sl->get('ZendDbAdapterAdapter');
$tableName = str_replace('Table', '', $requestedName);
$tableName = strtolower($tableName);
return new TableGateway($tableName, $adapter);
}
}
28
29. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
INITIALIZERS
▸ Applied to every object that the ServiceManager created
▸ Useful to inject other dependancies
▸ Do not over use them (50 Initializers with 300 objects means 15,000 calls)
29
30. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
DELEGATORS
▸ Add functionality to a class
▸ Transfers process to another object based on conditions
▸ Technically ZF2 delegators are decorators
▸ https://en.wikipedia.org/wiki/Delegation_pattern
30
31. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
DELEGATORS - HOW THEY WORK
▸ A delegator factory (MUST implement ZendServiceManager
DelegatorFactoryInterface)
▸ FactoryClass MUST BE registered as separate service in the ServiceManager
▸ Note: the delegator will not be passed through initializers
31
32. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
SERVICE MANAGER
OTHER SERVICE MANAGERS
▸ ZF2 builds other service managers that will be injected with the main service
manager
▸ ControllerManager, InputFilterManager, RouterPluginManager, and
FormElementManager are just some
32
34. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
EVENT MANAGER
EVENT MANAGER
▸ Aspect Oriented Programming (AOP)
▸ What it is useful for:
▸ Logging
▸ Caching
▸ Authorization
▸ Sanitizing
▸ Auditing
▸ Notifying the user when something happens (or fails)
34
35. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
EVENT MANAGER
ASPECT ORIENTED PROGRAMMING 101 - TERMS
▸ Aspect - The object being interacted
with
▸ Advice - What should be done with
each method of the aspect
▸ Joinpoint - Places where Advice can be
created
▸ Pointcut - Matches Joinpoint to an
Advice
35
36. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
EVENT MANAGER
ASPECT ORIENTED PROGRAMMING 101 - ADVICE TYPES
▸ Before advice - Applied before the advice is called
▸ After returning advice - Applied after the advice is called
▸ After throwing advice - Applied when an error happens
▸ Around advice - combines the Before and After returning advice*
36
http://www.sitepoint.com/explore-aspect-oriented-programming-with-codeigniter-1/
37. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
EVENT MANAGER
HOW IT WORKS IN ZF2
▸ Events chain until no more listeners are registered or a listener stops
propagation of events
▸ Listeners are called in order of priority. From the higher number to lower
number
▸ Responses from each listener is stored in a collection and returned back to the
calling code
37
38. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
EVENT MANAGER
REGISTERING EVENTS - CALLBACKS
use ZendEventManagerEventManager;
use ZendEventManagerEvent;
use ZendLogLogger;
$log = new Logger(['writers' => [['name' => 'noop']]]);
$events = new EventManager();
$events->attach('my_event', function (Event $event) use ($log) {
$event = $event->getName();
$target = get_class($event->getTarget());
$params = json_encode($event->getParams());
$log->info(sprintf(
'%s called on %s, using params %s',
$event,
$target,
$params
));
});
$target = new stdClass();
$params = ['foo' => 'bar'];
$events->trigger('my_event', $target, $params);
38
39. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
EVENT MANAGER
REGISTERING EVENTS - AGGREGATE
class Listener implements ListenerAggregateInterface, LoggerAwareInterface
{
use LoggerAwareTrait;
protected $listeners = [];
public function attach(EventManagerInterface $events) {
$this->listeners[] = $events->attach('my_event', [$this, 'logEvent'], 1000);
}
public function detach(EventManagerInterface $events) {
foreach ($this->listeners as $index => $callback) {
if ($events->detach($callback)) {
unset($this->listeners[$index]);
}
}
}
}
$events->attach(new Listener());
39
40. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
EVENT MANAGER
REGISTERING EVENTS - OTHER
▸ Register a listener to multiple events using an array
$events->attach(['my_event_1', 'my_event_2'], [$this, 'logEvent']);
▸ Or using a wildcard
$events->attach('*', [$this, 'logEvent']);
40
41. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
EVENT MANAGER
SHARED EVENT MANAGER
▸ Segregates events from other classes that could interfere with the listeners
▸ JIT loading of listeners to keep the event manager lightweight
41
46. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
MODELS
▸ Nothing special they are just classes
46
47. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
MVC_EVENT
▸ Created during application bootstrap
▸ Provides helpers to access the Application, Request, Response, Router, and the
View. (all these are injected during the bootstrap event
47
48. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
MVC_EVENT - EVENTS
▸ MvcEvent::EVENT_BOOTSTRAP - Prepares the application
▸ MvcEvent::EVENT_ROUTE - Matches the request to a controller
▸ MvcEvent::EVENT_DISPATCH - Call the matched controller
▸ MvcEvent::EVENT_DISPATCH_ERROR - Error happens during dispatch
▸ MvcEvent::EVENT_RENDER - Prepares the data to be rendered
▸ MvcEvent::EVENT_RENDER_ERROR - Error during rendering
▸ MvcEvent::EVENT_FINISH - Finial task
48
49. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
ROUTING
▸ Provides a means to match a request to a controller
▸ Matching can be made on any part of the URL
▸ Three router types: ConsoleSimpleRouteStack, HttpSimpleRouterStack and
HttpTreeRouterStack
49
50. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
CONTROLLERS
▸ Controllers are dispatched from a Router
▸ A Controller just needs to implement ZendStdlibDispatchableInterface
▸ Other common interfaces for controllers:
▸ ZendMvcInjectApplicationEventInterface
▸ ZendServiceManagerServiceLocatorAwareInterface
▸ ZendEventManagerEventManagerAwareInterface
50
53. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
CONTROLLER PLUGINS - CUSTOM PLUGINS IN 3 STEPS
▸ Create plugin
▸ Register in config
▸ Call in controller
53
54. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
VIEWS
▸ Views incorporate multiple levels to render a response
▸ By default uses the PHP template system (but can use your templating system
of choice)
▸ Layouts are also possible since ViewModels can be nested
▸ Your controllers do not need to return a ViewModel
54
55. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
VIEW - ONE VIEW MANY LAYERS
▸ Containers - holds variables and or callbacks (typically a model or the array
representation of the model)
▸ View Model - Connects the Container to a template (if applicable)
▸ Renders - Takes the Model and returns the representation of the model (Three are
included by default: PhpRenderer, JsonRenderer, FeedRenderer)
▸ Resolvers - Uses a strategy to resolve a template for the renderer
▸ Rendering Strategies - Decides which renderer to use
▸ Response Strategies - Handles setting the headers responses
55
56. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
VIEWS - HOW TO USE
▸ From controller:
$view = new ViewModel(array(
'message' => 'Hello world',
));
$view->setTemplate('my/template');
return $view;
▸ Or
return array(
'message' => 'Hello world',
);
56
57. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
VIEW - HELPERS
▸ Used with the PhpRenderer
▸ Handles common functions within a view
▸ Check out the manual for complete list visit: http://framework.zend.com/
manual/current/en/modules/zend.view.helpers.html
57
58. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
VIEW - CREATING CUSTOM HELPERS
▸ Have your helper implement ZendViewHelperHelperInterface
▸ or just extend ZendViewHelperAbstractHelper
▸ Register the helper
▸ in the config under 'view_helpers'
▸ in the module by implementing ZendModuleManagerFeature
ViewHelperProviderInterface
58
59. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
MVC
REQUEST AND RESPONSE
▸ Abstracts the HTTP (or console) Request and response
▸ Can also be used with the ZendHttp when you need to make CURL requests
▸ ViewModels can also understand the response based on different PHP
runtimes (console or web requests)
59
64. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
FORMS, VALIDATORS AND INPUTFILTERS
FORMS
▸ Used to bridge Views to Models (epically useful when following DOM)
▸ Takes elements, filters and validators to ensure data integrity.
▸ Creates element objects just-in-time to help keep for classes light
64
65. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
FORMS, VALIDATORS AND INPUTFILTERS
INPUTFILTERS
▸ Filters and validates sets of data by using filters and validators
▸ Can be independent objects, specified in the config or built on the fly in code
▸ Passed by reference, keeps data from being munged elsewhere
65
66. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
FORMS, VALIDATORS AND INPUTFILTERS
FILTERS AND VALIDATORS
▸ Transform data (trim, uppercase, lowercase etc)
▸ Filters are applied before validation
▸ Multiple filters and validators can be applied for each field
▸ Validators get passed the full data set to help validate
66
67. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
FORMS, VALIDATORS AND INPUTFILTERS
RENDERING FORMS
▸ View helpers for each filed type
▸ or simply use the formElement view helper
▸ setting values to the form will display the value by the user
67
69. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
DATABASE
OVERVIEW
▸ ZendDb provides simple abstraction for working with RDBMS
▸ Can be used as an ORM
▸ Can use PDO or basic drivers
69
70. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
DATABASE
STATEMENTS
▸ Used to Programmatically create SQL statements
▸ Agnostic towards different systems
▸ Normalizes out queries (as best they can) to handle the differences between
RDBMS
▸ Returns Results Statements which can create your models using a hydrator
70
71. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
DATABASE
HYDRATORS
▸ Transform an object to an array
▸ Take and array and set those values on the
object (or hydrates an object)
▸ ArraySerializable
▸ ClassMethods
▸ Can also filter values before passing into the
object
71
72. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
DATABASE
TABLE/ROW GATEWAY
▸ Represents a row or table in the database
▸ Does all the heavy lifting for building a SQL query.
▸ A Must have when following the Active Record pattern
▸ Definition of the row and table is defined using the ZendDbMetadata*
classes
72
74. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
LOGGING
BASICS
▸ Allows writing to multiple log locations
▸ Allows filtering out log levels or text
▸ Can be used to log PHP errors and exceptions
▸ Complies with RFC-3164
▸ Not PSR-3 compliant! (but you can use this
module)
74
75. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
LOGGING
HOW IT WORKS
▸ ZendLogLogger is constructed with writers
▸ Writers can get formatters to format the message to your hearts desire
▸ Messages are normally written during shutdown
▸ Logger can also take a filter which messages are logged
▸ Log Level
▸ Regex
▸ Following a Filter or Validator
75
76. Zend Framework Foundations, Chuck Reeves @manchuck PHP[world] 2015
LOGGING
USING LOGS
$logger = new ZendLogLogger;
$writer = new ZendLogWriterStream('php://output');
$logger->addWriter($writer);
$logger->info('This is an info');
76