SlideShare a Scribd company logo
@asgrim
Kicking off with Zend Expressive
and Doctrine ORM
James Titcumb
SunshinePHP 2017
Who is this guy?
James Titcumb
www.jamestitcumb.com
www.roave.com
www.phphants.co.uk
www.phpsouthcoast.co.uk
@asgrim
@asgrim
What is Zend Expressive?
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Application
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Application
@asgrim
PSR-7
HTTP Message Interfaces
@asgrim
HTTP Request
POST /zendcon2016/foo HTTP/1.1
Host: www.zendcon.com
foo=bar&baz=bat
@asgrim
HTTP Response
HTTP/1.1 200 OK
Content-Type: text/plain
This is the response body
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Application
@asgrim
Zend Diactoros
PSR-7 implementation
@asgrim
Node http.Server using Diactoros
$server = ZendDiactorosServer::createServer(
function ($request, $response, $done) {
return $response->getBody()->write('hello world');
},
$_SERVER,
$_GET,
$_POST,
$_COOKIE,
$_FILES
);
$server->listen();
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Application
@asgrim
Zend Stratigility
Creating & dispatching middleware pipelines
@asgrim
So what is “middleware”?
@asgrim
Middleware in the middle
function(Request $request, DelegateInterface $delegate) : Response
{
// ... some code before ...
$response = $delegate->process($request);
// ... some code after ...
return $response;
}
@asgrim
http-interop/http-middleware
@asgrim
Modifying the response
function(Request $request, DelegateInterface $delegate) : Response
{
$response = $delegate->process($request);
return $response->withHeader(
'X-Clacks-Overhead',
'GNU Terry Pratchett'
);
}
@asgrim
Pipe all the things!
$pipe = new ZendStratigilityMiddlewarePipe();
$pipe->pipe($logUncaughtErrorsMiddleware);
$pipe->pipe($sessionInitialisingMiddleware);
$pipe->pipe($authenticationMiddleware);
$pipe->pipe('/', $indexActionMiddleware);
$pipe->pipe(new NotFoundHandler(...));
@asgrim
LogErrorsCaughtMiddleware
function(Request $request, DelegateInterface $delegate) : Response
{
try {
return $delegate->process($request);
} catch (Throwable $throwable) {
// Log the error, handle it with error page etc.
return new JsonResponse(
[
'message' => $throwable->getMessage(),
],
500
);
}
}
@asgrim
SessionInitialisingMiddleware
function(Request $request, DelegateInterface $delegate) : Response
{
session_start();
return $delegate->process($request);
}
@asgrim
function(Request $request, DelegateInterface $delegate) : Response
{
if (!$this->doSomeOAuthCheck($request)) {
return new JsonResponse(
[
'message' => 'Invalid OAuth token',
],
403
);
}
return $delegate->process($request);
}
AuthenticationMiddleware
@asgrim
IndexActionMiddleware
function(Request $request, DelegateInterface $delegate) : Response
{
// ... some code ...
return new JsonResponse($someData, 200);
}
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Application
@asgrim
Zend Expressive
One Ring to bring them all and in the darkness bind them.
@asgrim
Routing
@asgrim
container-interop
@asgrim
Optionally, templating
@asgrim
Piping and Routing
@asgrim
Zend Framework 2/3
What of them?
@asgrim
Middleware vs MVC
@asgrim
Using ZF components
in Expressive
@asgrim
Module.php
class Module
{
public function getConfig()
{
return include __DIR__ . '/../config/module.config.php';
}
}
@asgrim
ConfigProvider
@asgrim
ConfigProvider
namespace ZendForm;
class ConfigProvider
{
public function __invoke()
{
return [
'dependencies' => $this->getDependencyConfig(),
'view_helpers' => $this->getViewHelperConfig(),
];
}
}
@asgrim
ConfigProvider#getDependencyConfig()
public function getDependencyConfig()
{
return [
'abstract_factories' => [
FormAbstractServiceFactory::class,
],
'aliases' => [
'ZendFormAnnotationFormAnnotationBuilder' => 'FormAnnotationBuilder',
AnnotationAnnotationBuilder::class => 'FormAnnotationBuilder',
FormElementManager::class => 'FormElementManager',
],
'factories' => [
'FormAnnotationBuilder' => AnnotationAnnotationBuilderFactory::class,
'FormElementManager' => FormElementManagerFactory::class,
],
@asgrim
ZendForm’s Module.php
class Module
{
public function getConfig()
{
$provider = new ConfigProvider();
return [
'service_manager' => $provider->getDependencyConfig(),
'view_helpers' => $provider->getViewHelperConfig(),
];
}
}
@asgrim
config/autoload/zend-form.global.php
<?php
return (new ZendFormConfigProvider())->__invoke();
@asgrim
Layers of an Expressive application
Expressive
Stratigility
Diactoros
PSR-7 Interface
DIRouter Template
Your Application
@asgrim
Getting started
with Zend Expressive
@asgrim
https://github.com/asgrim/book-library
@asgrim
Expressive Skeleton
@asgrim
Expressive installer - start
$ composer create-project zendframework/zend-expressive-skeleton book-library
Installing zendframework/zend-expressive-skeleton (1.0.3)
- Installing zendframework/zend-expressive-skeleton (1.0.3)
Downloading: 100%
Created project in book-library
> ExpressiveInstallerOptionalPackages::install
Setup data and cache dir
Setting up optional packages
@asgrim
Expressive installer - minimal?
Minimal skeleton? (no default middleware, templates, or assets; configuration only)
[y] Yes (minimal)
[n] No (full; recommended)
Make your selection (No): n
@asgrim
Expressive installer - router?
Which router do you want to use?
[1] Aura.Router
[2] FastRoute
[3] Zend Router
Make your selection or type a composer package name and version (FastRoute): 2
@asgrim
Expressive installer - container?
Which container do you want to use for dependency injection?
[1] Aura.Di
[2] Pimple
[3] Zend ServiceManager
Make your selection or type a composer package name and version (Zend ServiceManager): 3
@asgrim
Expressive installer - template?
Which template engine do you want to use?
[1] Plates
[2] Twig
[3] Zend View installs Zend ServiceManager
[n] None of the above
Make your selection or type a composer package name and version (n): n
@asgrim
Expressive installer - whoops?
Which error handler do you want to use during development?
[1] Whoops
[n] None of the above
Make your selection or type a composer package name and version (Whoops): n
@asgrim
Expressive installer - run it!
$ composer serve
> php -S 0.0.0.0:8080 -t public/ public/index.php
[Thu Sep 1 20:29:33 2016] 127.0.0.1:48670 [200]: /favicon.ico
{
"welcome": "Congratulations! You have installed the zend-expressive skeleton application.",
"docsUrl": "zend-expressive.readthedocs.org"
}
@asgrim
Create the endpoints
@asgrim
Book entity
class Book
{
/**
* @var string
*/
private $id;
/**
* @var bool
*/
private $inStock = true;
public function __construct()
{
$this->id = (string)Uuid::uuid4();
}
@asgrim
Book entity
class Book
{
/**
* @return void
* @throws AppEntityExceptionBookNotAvailable
*/
public function checkOut()
{
if (!$this->inStock) {
throw ExceptionBookNotAvailable::fromBook($this);
}
$this->inStock = false;
}
@asgrim
Book entity
class Book
{
/**
* @return void
* @throws AppEntityExceptionBookAlreadyStocked
*/
public function checkIn()
{
if ($this->inStock) {
throw ExceptionBookAlreadyStocked::fromBook($this);
}
$this->inStock = true;
}
@asgrim
FindBookByUuidInterface
interface FindBookByUuidInterface
{
/**
* @param UuidInterface $slug
* @return Book
* @throws ExceptionBookNotFound
*/
public function __invoke(UuidInterface $slug): Book;
}
@asgrim
CheckOutAction
public function process(ServerRequestInterface $request, DelegateInterface $delegate): JsonResponse
{
try {
$book = $this->findBookByUuid->__invoke(Uuid::fromString($request->getAttribute('id')));
} catch (BookNotFound $bookNotFound) {
return new JsonResponse(['info' => $bookNotFound->getMessage()], 404);
}
try {
$book->checkOut();
} catch (BookNotAvailable $bookNotAvailable) {
return new JsonResponse(['info' => $bookNotAvailable->getMessage()], 423);
}
return new JsonResponse([
'info' => sprintf('You have checked out %s', $book->getId()),
]);
}
@asgrim
Adding some ORM
@asgrim
Your application
Doctrine quick overview
DB
DBAL
ORM
(EntityManager)
Entities
Finders,
Services,
...
@asgrim
DoctrineORMModule
@asgrim
DoctrineORMModule + Expressive?
@asgrim
config/autoload/doctrine-modules.global.php
$vendorPath = __DIR__ . '/../../vendor';
$doctrineModuleConfig = require_once $vendorPath . '/doctrine/doctrine-module/config/module.config.php';
$doctrineModuleConfig['dependencies'] = $doctrineModuleConfig['service_manager'];
unset($doctrineModuleConfig['service_manager']);
$ormModuleConfig = require_once $vendorPath . '/doctrine/doctrine-orm-module/config/module.config.php';
$ormModuleConfig['dependencies'] = $ormModuleConfig['service_manager'];
unset($ormModuleConfig['service_manager']);
return ArrayUtils::merge($doctrineModuleConfig, $ormModuleConfig);
@asgrim
But wait!
@asgrim
container-interop-doctrine
saves the day!!!
@asgrim
Installation
$ composer require dasprid/container-interop-doctrine
Using version ^0.2.2 for dasprid/container-interop-doctrine
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing dasprid/container-interop-doctrine (0.2.2)
Loading from cache
Writing lock file
Generating autoload files
$
@asgrim
config/autoload/doctrine.global.php
<?php
declare(strict_types = 1);
use DoctrineORMEntityManagerInterface;
use ContainerInteropDoctrineEntityManagerFactory;
return [
'dependencies' => [
'factories' => [
EntityManagerInterface::class => EntityManagerFactory::class,
],
],
];
@asgrim
'doctrine' => [
'connection' => [
'orm_default' => [
'driver_class' => PDOPgSqlDriver::class,
'params' => [
'url' => 'postgres://user:pass@localhost/book_library',
],
],
],
'driver' => [
'orm_default' => [
'class' => MappingDriverChain::class,
'drivers' => [
// ... and so on ...
config/autoload/doctrine.global.php
@asgrim
'doctrine' => [
'connection' => [
'orm_default' => [
'driver_class' => PDOPgSqlDriver::class,
'params' => [
'url' => 'postgres://user:pass@localhost/book_library',
],
],
],
'driver' => [
'orm_default' => [
'class' => MappingDriverChain::class,
'drivers' => [
// ... and so on ...
config/autoload/doctrine.global.php
@asgrim
<?php
declare(strict_types = 1);
use DoctrineORMEntityManagerInterface;
use DoctrineORMToolsConsoleHelperEntityManagerHelper;
use SymfonyComponentConsoleHelperHelperSet;
$container = require __DIR__ . '/container.php';
return new HelperSet([
'em' => new EntityManagerHelper(
$container->get(EntityManagerInterface::class)
),
]);
config/cli-config.php
@asgrim
Annotating the Entities
@asgrim
/**
* @ORMEntity
* @ORMTable(name="book")
*/
class Book
{
/**
* @ORMId
* @ORMColumn(name="id", type="guid")
* @ORMGeneratedValue(strategy="NONE")
* @var string
*/
private $id;
src/App/Entity/Book.php
@asgrim
/**
* @ORMEntity
* @ORMTable(name="book")
*/
class Book
{
/**
* @ORMId
* @ORMColumn(name="id", type="guid")
* @ORMGeneratedValue(strategy="NONE")
* @var string
*/
private $id;
src/App/Entity/Book.php
@asgrim
public function __invoke(UuidInterface $id): Book
{
/** @var Book|null $book */
$book = $this->repository->find((string)$id);
if (null === $book) {
throw ExceptionBookNotFound::fromUuid($id);
}
return $book;
}
src/App/Service/Book/DoctrineFindBookByUuid.php
@asgrim
try {
$this->entityManager->transactional(function () use ($book) {
$book->checkOut();
});
} catch (BookNotAvailable $bookNotAvailable) {
return new JsonResponse(['info' => $bookNotAvailable->getMessage()], 423);
}
src/App/Action/CheckOutAction.php
@asgrim
Generate the schema
$ vendor/bin/doctrine orm:schema-tool:create
ATTENTION: This operation should not be executed in a production
environment.
Creating database schema...
Database schema created successfully!
$
@asgrim
Insert some data
INSERT INTO book (id, name, in_stock) VALUES (
'1c06bec9-adae-47c2-b411-73b1db850e6f',
'The Great Escape',
true
);
@asgrim
/book/1c06bec9-adae-47c2-b411-.../check-out
{"info":"You have checked out The Great Escape"}
@asgrim
/book/1c06bec9-adae-47c2-b411-.../check-in
{"info":"You have checked in The Great Escape"}
@asgrim
Automatic Flushing Middleware
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response
{
if (null === $out) {
throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped');
}
$response = $out($request, $response);
if ($this->entityManager->isOpen()) {
$this->entityManager->flush();
}
return $response;
}
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response
{
if (null === $out) {
throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped');
}
$response = $out($request, $response);
if ($this->entityManager->isOpen()) {
$this->entityManager->flush();
}
return $response;
}
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response
{
if (null === $out) {
throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped');
}
$response = $out($request, $response);
if ($this->entityManager->isOpen()) {
$this->entityManager->flush();
}
return $response;
}
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response
{
if (null === $out) {
throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped');
}
$response = $out($request, $response);
if ($this->entityManager->isOpen()) {
$this->entityManager->flush();
}
return $response;
}
@asgrim
FlushingMiddleware
public function __invoke(Request $request, Response $response, callable $out = null) : Response
{
if (null === $out) {
throw new InvalidArgumentException('Middleware in ' . __CLASS__ . ' must be piped');
}
$response = $out($request, $response);
if ($this->entityManager->isOpen()) {
$this->entityManager->flush();
}
return $response;
}
@asgrim
Doing more with
middleware
@asgrim
Authentication
@asgrim
public function __invoke(
Request $request, Response $response, callable $next = null
) : Response {
$queryParams = $request->getQueryParams();
if (!array_key_exists('authenticated', $queryParams)||$queryParams['authenticated'] !== '1') {
return new JsonResponse(
['error' => 'You are not authenticated.'],
403
);
}
return $next($request, $response);
}
Create the middleware
@asgrim
public function __invoke(
Request $request, Response $response, callable $next = null
) : Response {
$queryParams = $request->getQueryParams();
if (!array_key_exists('authenticated', $queryParams)||$queryParams['authenticated'] !== '1') {
return new JsonResponse(
['error' => 'You are not authenticated.'],
403
);
}
return $next($request, $response);
}
Create the middleware
@asgrim
public function __invoke(
Request $request, Response $response, callable $next = null
) : Response {
$queryParams = $request->getQueryParams();
if (!array_key_exists('authenticated', $queryParams)||$queryParams['authenticated'] !== '1') {
return new JsonResponse(
['error' => 'You are not authenticated.'],
403
);
}
return $next($request, $response);
}
Create the middleware
@asgrim
public function __invoke(
Request $request, Response $response, callable $next = null
) : Response {
$queryParams = $request->getQueryParams();
if (!array_key_exists('authenticated', $queryParams)||$queryParams['authenticated'] !== '1') {
return new JsonResponse(
['error' => 'You are not authenticated.'],
403
);
}
return $next($request, $response);
}
Create the middleware
@asgrim
Helios
composer require dasprid/helios
@asgrim
PSR7-Session
composer require psr7-sessions/storageless
@asgrim
public function __invoke(ContainerInterface $container, $_, array $_ = null)
{
$symmetricKey = 'super-secure-key-you-should-not-store-this-key-in-git-store-it-in-configuration-instead-please';
$expirationTime = 1200; // 20 minutes
return new SessionMiddleware(
new SignerHmacSha256(),
$symmetricKey,
$symmetricKey,
SetCookie::create(SessionMiddleware::DEFAULT_COOKIE)
->withSecure(false) // false on purpose, unless you have https locally
->withHttpOnly(true)
->withPath('/'),
new Parser(),
$expirationTime,
new SystemCurrentTime()
);
}
Factory the middleware
@asgrim
'routing' => [
'middleware' => [
ApplicationFactory::ROUTING_MIDDLEWARE,
HelperUrlHelperMiddleware::class,
PSR7SessionHttpSessionMiddleware::class,
AppMiddlewareAuthenticationMiddleware::class,
ApplicationFactory::DISPATCH_MIDDLEWARE,
],
'priority' => 1,
],
Add middleware to pipe
@asgrim
$session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE);
$session->set('counter', $session->get('counter', 0) + 1);
Session is stored in Request
@asgrim
To summarise...
● PSR-7 is the foundation for this!
● Diactoros is just a PSR-7 implementation
● Stratigility is a middleware pipeline: the main bit
● Expressive is a glue for everything
● DoctrineModule can be used (with some fiddling)
● container-interop-doctrine makes Doctrine work easier
● Middleware all the things!
Any questions?
https://joind.in/talk/3bf19
James Titcumb @asgrim

More Related Content

What's hot (20)

PDF
Zend\Expressive - höher, schneller, weiter
Ralf Eggert
 
PDF
Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)
James Titcumb
 
PDF
Apigility reloaded
Ralf Eggert
 
PDF
TDD with PhpSpec
CiaranMcNulty
 
PPTX
PHP FUNCTIONS
Zeeshan Ahmed
 
PDF
TDD with phpspec2
Anton Serdyuk
 
PDF
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf Conference
 
PDF
Information security programming in ruby
Hiroshi Nakamura
 
PDF
TDD with PhpSpec - Lone Star PHP 2016
CiaranMcNulty
 
PPTX
Php 7 hhvm and co
Pierre Joye
 
PDF
PHP 5.4 New Features
Haim Michael
 
PDF
Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)
James Titcumb
 
PDF
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
Fernando Hamasaki de Amorim
 
PPTX
Zephir - A Wind of Change for writing PHP extensions
Mark Baker
 
PPT
PHP - Introduction to PHP Functions
Vibrant Technologies & Computers
 
PPTX
New in php 7
Vic Metcalfe
 
PPT
Ant
sundar22in
 
PPTX
jQuery from the very beginning
Anis Ahmad
 
PDF
Let's play a game with blackfire player
Marcin Czarnecki
 
PDF
Into the ZF2 Service Manager
Chris Tankersley
 
Zend\Expressive - höher, schneller, weiter
Ralf Eggert
 
Kicking off with Zend Expressive and Doctrine ORM (PHP South Africa 2018)
James Titcumb
 
Apigility reloaded
Ralf Eggert
 
TDD with PhpSpec
CiaranMcNulty
 
PHP FUNCTIONS
Zeeshan Ahmed
 
TDD with phpspec2
Anton Serdyuk
 
ZFConf 2012: Zend Framework 2, a quick start (Enrico Zimuel)
ZFConf Conference
 
Information security programming in ruby
Hiroshi Nakamura
 
TDD with PhpSpec - Lone Star PHP 2016
CiaranMcNulty
 
Php 7 hhvm and co
Pierre Joye
 
PHP 5.4 New Features
Haim Michael
 
Kicking off with Zend Expressive and Doctrine ORM (PHP MiNDS March 2018)
James Titcumb
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
Fernando Hamasaki de Amorim
 
Zephir - A Wind of Change for writing PHP extensions
Mark Baker
 
PHP - Introduction to PHP Functions
Vibrant Technologies & Computers
 
New in php 7
Vic Metcalfe
 
jQuery from the very beginning
Anis Ahmad
 
Let's play a game with blackfire player
Marcin Czarnecki
 
Into the ZF2 Service Manager
Chris Tankersley
 

Viewers also liked (20)

PPTX
Taming the resource tiger
Elizabeth Smith
 
PDF
Php Dependency Management with Composer ZendCon 2016
Clark Everetts
 
PDF
Your First Magento 2 Module
Ben Marks
 
PDF
DB2 and PHP in Depth on IBM i
Alan Seiden
 
PDF
All the Laravel things: up and running to making $$
Joe Ferguson
 
PDF
Zend Framework Foundations
Chuck Reeves
 
PDF
Hack the Future
Jason McCreary
 
PDF
php[world] 2015 Training - Laravel from the Ground Up
Joe Ferguson
 
PDF
Adding 1.21 Gigawatts to Applications with RabbitMQ (Bulgaria PHP 2016 - Tuto...
James Titcumb
 
PPTX
Engineer - Mastering the Art of Software
Cristiano Diniz da Silva
 
PDF
Amp your site an intro to accelerated mobile pages
Robert McFrazier
 
PDF
Create, test, secure, repeat
Michelangelo van Dam
 
PDF
Console Apps: php artisan forthe:win
Joe Ferguson
 
PDF
Dip Your Toes in the Sea of Security
James Titcumb
 
PDF
Git Empowered
Jason McCreary
 
PDF
Code Coverage for Total Security in Application Migrations
Dana Luther
 
PDF
Presentation Bulgaria PHP
Alena Holligan
 
PPTX
Php extensions
Elizabeth Smith
 
PDF
Conscious Coupling
CiaranMcNulty
 
PDF
SunshinePHP 2017 - Making the most out of MySQL
Gabriela Ferrara
 
Taming the resource tiger
Elizabeth Smith
 
Php Dependency Management with Composer ZendCon 2016
Clark Everetts
 
Your First Magento 2 Module
Ben Marks
 
DB2 and PHP in Depth on IBM i
Alan Seiden
 
All the Laravel things: up and running to making $$
Joe Ferguson
 
Zend Framework Foundations
Chuck Reeves
 
Hack the Future
Jason McCreary
 
php[world] 2015 Training - Laravel from the Ground Up
Joe Ferguson
 
Adding 1.21 Gigawatts to Applications with RabbitMQ (Bulgaria PHP 2016 - Tuto...
James Titcumb
 
Engineer - Mastering the Art of Software
Cristiano Diniz da Silva
 
Amp your site an intro to accelerated mobile pages
Robert McFrazier
 
Create, test, secure, repeat
Michelangelo van Dam
 
Console Apps: php artisan forthe:win
Joe Ferguson
 
Dip Your Toes in the Sea of Security
James Titcumb
 
Git Empowered
Jason McCreary
 
Code Coverage for Total Security in Application Migrations
Dana Luther
 
Presentation Bulgaria PHP
Alena Holligan
 
Php extensions
Elizabeth Smith
 
Conscious Coupling
CiaranMcNulty
 
SunshinePHP 2017 - Making the most out of MySQL
Gabriela Ferrara
 
Ad

Similar to Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017) (20)

PDF
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
James Titcumb
 
PDF
Zend Framework 2 quick start
Enrico Zimuel
 
PDF
A quick start on Zend Framework 2
Enrico Zimuel
 
PDF
Make your application expressive
Christian Varela
 
PDF
Ростислав Михайлив "Zend Framework 3 - evolution or revolution"
Fwdays
 
PDF
Zend Framework 2 - Basic Components
Mateusz Tymek
 
PPTX
Adding Dependency Injection to Legacy Applications
Sam Hennessy
 
PDF
ZF2 Presentation @PHP Tour 2011 in Lille
Zend by Rogue Wave Software
 
DOCX
Zend framework 2.0
shrutisgupta
 
ODP
Creating Web Services with Zend Framework - Matthew Turland
Matthew Turland
 
PDF
Quick start on Zend Framework 2
Enrico Zimuel
 
PDF
Zend/Expressive 3 – The Next Generation
Ralf Eggert
 
PDF
Expressive Microservice Framework Blastoff
Adam Culp
 
KEY
Fatc
Wade Arnold
 
PPT
San Francisco PHP Meetup Presentation on Zend Framework
zend
 
PDF
Zend Framework 1 + Doctrine 2
Ralph Schindler
 
PDF
Symfony2 from the Trenches
Jonathan Wage
 
PDF
Symfony2 - from the trenches
Lukas Smith
 
PPT
Demo
bkslide
 
PPT
green
alind tiwari
 
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
James Titcumb
 
Zend Framework 2 quick start
Enrico Zimuel
 
A quick start on Zend Framework 2
Enrico Zimuel
 
Make your application expressive
Christian Varela
 
Ростислав Михайлив "Zend Framework 3 - evolution or revolution"
Fwdays
 
Zend Framework 2 - Basic Components
Mateusz Tymek
 
Adding Dependency Injection to Legacy Applications
Sam Hennessy
 
ZF2 Presentation @PHP Tour 2011 in Lille
Zend by Rogue Wave Software
 
Zend framework 2.0
shrutisgupta
 
Creating Web Services with Zend Framework - Matthew Turland
Matthew Turland
 
Quick start on Zend Framework 2
Enrico Zimuel
 
Zend/Expressive 3 – The Next Generation
Ralf Eggert
 
Expressive Microservice Framework Blastoff
Adam Culp
 
San Francisco PHP Meetup Presentation on Zend Framework
zend
 
Zend Framework 1 + Doctrine 2
Ralph Schindler
 
Symfony2 from the Trenches
Jonathan Wage
 
Symfony2 - from the trenches
Lukas Smith
 
Demo
bkslide
 
Ad

More from James Titcumb (20)

PDF
Living the Best Life on a Legacy Project (phpday 2022).pdf
James Titcumb
 
PDF
Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)
James Titcumb
 
PDF
Climbing the Abstract Syntax Tree (Midwest PHP 2020)
James Titcumb
 
PDF
Best practices for crafting high quality PHP apps (Bulgaria 2019)
James Titcumb
 
PDF
Climbing the Abstract Syntax Tree (php[world] 2019)
James Titcumb
 
PDF
Best practices for crafting high quality PHP apps (php[world] 2019)
James Titcumb
 
PDF
Crafting Quality PHP Applications (PHP Joburg Oct 2019)
James Titcumb
 
PDF
Climbing the Abstract Syntax Tree (PHP Russia 2019)
James Titcumb
 
PDF
Best practices for crafting high quality PHP apps - PHP UK 2019
James Titcumb
 
PDF
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
James Titcumb
 
PDF
Best practices for crafting high quality PHP apps (ScotlandPHP 2018)
James Titcumb
 
PDF
Best practices for crafting high quality PHP apps (PHP South Africa 2018)
James Titcumb
 
PDF
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
James Titcumb
 
PDF
Climbing the Abstract Syntax Tree (Southeast PHP 2018)
James Titcumb
 
PDF
Crafting Quality PHP Applications (PHPkonf 2018)
James Titcumb
 
PDF
Best practices for crafting high quality PHP apps (PHP Yorkshire 2018)
James Titcumb
 
PDF
Crafting Quality PHP Applications: an overview (PHPSW March 2018)
James Titcumb
 
PDF
Climbing the Abstract Syntax Tree (PHP UK 2018)
James Titcumb
 
PDF
Crafting Quality PHP Applications (PHP Benelux 2018)
James Titcumb
 
PDF
Crafting Quality PHP Applications (ConFoo YVR 2017)
James Titcumb
 
Living the Best Life on a Legacy Project (phpday 2022).pdf
James Titcumb
 
Tips for Tackling a Legacy Codebase (ScotlandPHP 2021)
James Titcumb
 
Climbing the Abstract Syntax Tree (Midwest PHP 2020)
James Titcumb
 
Best practices for crafting high quality PHP apps (Bulgaria 2019)
James Titcumb
 
Climbing the Abstract Syntax Tree (php[world] 2019)
James Titcumb
 
Best practices for crafting high quality PHP apps (php[world] 2019)
James Titcumb
 
Crafting Quality PHP Applications (PHP Joburg Oct 2019)
James Titcumb
 
Climbing the Abstract Syntax Tree (PHP Russia 2019)
James Titcumb
 
Best practices for crafting high quality PHP apps - PHP UK 2019
James Titcumb
 
Climbing the Abstract Syntax Tree (ScotlandPHP 2018)
James Titcumb
 
Best practices for crafting high quality PHP apps (ScotlandPHP 2018)
James Titcumb
 
Best practices for crafting high quality PHP apps (PHP South Africa 2018)
James Titcumb
 
Climbing the Abstract Syntax Tree (PHP Developer Days Dresden 2018)
James Titcumb
 
Climbing the Abstract Syntax Tree (Southeast PHP 2018)
James Titcumb
 
Crafting Quality PHP Applications (PHPkonf 2018)
James Titcumb
 
Best practices for crafting high quality PHP apps (PHP Yorkshire 2018)
James Titcumb
 
Crafting Quality PHP Applications: an overview (PHPSW March 2018)
James Titcumb
 
Climbing the Abstract Syntax Tree (PHP UK 2018)
James Titcumb
 
Crafting Quality PHP Applications (PHP Benelux 2018)
James Titcumb
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
James Titcumb
 

Recently uploaded (20)

PDF
Survival Models: Proper Scoring Rule and Stochastic Optimization with Competi...
Paris Women in Machine Learning and Data Science
 
PDF
Modern Decentralized Application Architectures.pdf
Kalema Edgar
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PPTX
Manual Testing for Accessibility Enhancement
Julia Undeutsch
 
PDF
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
PDF
“Voice Interfaces on a Budget: Building Real-time Speech Recognition on Low-c...
Edge AI and Vision Alliance
 
PPTX
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
Linux schedulers for fun and profit with SchedKit
Alessio Biancalana
 
PDF
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PDF
ICONIQ State of AI Report 2025 - The Builder's Playbook
Razin Mustafiz
 
PDF
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
PDF
Bharatiya Antariksh Hackathon 2025 Idea Submission PPT.pdf
ghjghvhjgc
 
PDF
Kit-Works Team Study_20250627_한달만에만든사내서비스키링(양다윗).pdf
Wonjun Hwang
 
PPTX
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
PPTX
Mastering ODC + Okta Configuration - Chennai OSUG
HathiMaryA
 
PDF
Home Cleaning App Development Services.pdf
V3cube
 
PPTX
Talbott's brief History of Computers for CollabDays Hamburg 2025
Talbott Crowell
 
PDF
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
Survival Models: Proper Scoring Rule and Stochastic Optimization with Competi...
Paris Women in Machine Learning and Data Science
 
Modern Decentralized Application Architectures.pdf
Kalema Edgar
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
Manual Testing for Accessibility Enhancement
Julia Undeutsch
 
Peak of Data & AI Encore AI-Enhanced Workflows for the Real World
Safe Software
 
“Voice Interfaces on a Budget: Building Real-time Speech Recognition on Low-c...
Edge AI and Vision Alliance
 
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
Linux schedulers for fun and profit with SchedKit
Alessio Biancalana
 
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
ICONIQ State of AI Report 2025 - The Builder's Playbook
Razin Mustafiz
 
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
Bharatiya Antariksh Hackathon 2025 Idea Submission PPT.pdf
ghjghvhjgc
 
Kit-Works Team Study_20250627_한달만에만든사내서비스키링(양다윗).pdf
Wonjun Hwang
 
MuleSoft MCP Support (Model Context Protocol) and Use Case Demo
shyamraj55
 
Mastering ODC + Okta Configuration - Chennai OSUG
HathiMaryA
 
Home Cleaning App Development Services.pdf
V3cube
 
Talbott's brief History of Computers for CollabDays Hamburg 2025
Talbott Crowell
 
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 

Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)