SlideShare uma empresa Scribd logo
1 de 85
Baixar para ler offline
Make your Application
Expressive
By Christian Varela

@gabriel0702

cvarela@conquerorsoft.com

https://joind.in/talk/b5ac8
1
Slides at:
[link]
2
Christian Varela
• I have a wife and 3 daughters

• I am from Mexico

• Master Degree in Computer Science

• 13 years programming with PHP

• I live in Miami

• I created Conqueror Soft Inc

• I play guitar and piano
3
4
Conqueror Soft will take your business to the next Level!
5
www.conquerorsoft.com
info@conquerorsoft.com
facebook.com/conquerorsoft
What is this session about?
Learn the concepts of PSR-7 middleware with Zend Expressive and how
your application could be developed from scratch adapting those
concepts with a new mindset. You'll see the different approaches,
advantages and disadvantages, and the contrast of this paradigm and
other more conventional paradigms.
6
Expressive
Expressive it is a framework by Zend that allows you to
write PSR-7 middleware applications for the web.
7
PSR-7
1. PHP Standard Recommendation 7

2. HTTP message interfaces

3. Describes common interfaces for representing HTTP messages as
described in RFC 7230 and RFC 7231

4. Describes interfaces for representing URIs for use with HTTP messages
as described in RFC 3986.
8
HTTP messages
1. They are messages between servers and clients in the web

1. HTTP request messages

2. HTTP response messages
9
HTTP Request messages
1. Request line

1. Method

2. Target

3. HTTP protocol version

2. One or more headers

3. empty line

4. Message body
10
HTTP Request messages
POST /authors HTTP/1.1
Host: localhost:8081
Content-Type: application/json
Authorization: Basic [replace_with_password]
Cache-Control: no-cache
Postman-Token: 1b196a8d-c32b-be43-5523-d5354e5b5cc5
{
"first_name":"First_name",
"last_name":"Last_name",
"dob":"1900-01-01"
}
11
HTTP Response messages
1. Status line

1. HTTP protocol version Method

2. HTTP status code

3. Reason phrase

2. One or more headers

3. empty line

4. Message body
12
HTTP Response messages
HTTP/1.1 201 Created
host:"localhost:8081"
date:"Sun, 08 Oct 2017 21:07:33 +0000"
connection:"close"
x-powered-by:"PHP/7.1.1"
location:"http://localhost:8081/authors/33"
content-location:"http://localhost:8081/authors/33"
content-type:"application/json"
vary:"Origin"
{
"entity_id": "33",
"first_name": "First_name",
"last_name": "Last_name",
"dob": "1900-01-01",
"created_at": null
}
13
PSR-7 PsrHttpMessage interfaces
1.MessageInterface

1.RequestInterface

1.ServerRequestInterface

2.ResponseInterface
14
PSR-7 other interfaces
1.StreamInterface

2.UploadedFileInterface

3.UriInterface
15
Middleware
Middleware is code that exists between the request and response, and
which can take the incoming request, perform actions based on it, and either
complete the response or pass delegation on to the next middleware in the
queue.
16
Middleware
For example, you could have a collection of middleware like this:

1.reverse string

2.convert string to upper case

3.shuffle string
17
Middleware
1 $app=new Middleware();
2 $app->pipe($errorHandler);
3 $app->pipe($reverseMiddleware);
4 $app->pipe($uppercaseMiddleware);
5 $app->pipe($shuffleMiddleware);
6 $app->pipe($defaultMiddleware);
7 $app->run();
18
Middleware
19
In (request) Out (response)
to delegate from delegate
Middleware
20
In (request) Out (response)
Middleware
21
In (request) Out (response)
Middleware
22
Error handler
Reverse
Uppercase
Shuffle
Default
In Out Middleware
something GSNEHOMIT Error
something GSNEHOMIT Reverse
something TIMOHENSG Uppercase
something timohensg Shuffle
something something Default
How expressive puts all that in
practice?
23
Expressive 1.X middleware
1 <?php
2 function (
3 ServerRequestInterface $request,
4 ResponseInterface $response,
5 callable $next)
6 {
7 $response = $next($request, $response);
8 return $response->withHeader('X-Test', time());
9 }
24
Expressive 2 middleware
1 function (
2 ServerRequestInterface $request,
3 DelegateInterface $delegate)
4 {
5 $response = $delegate->process($request);
6 return $response->withHeader('X-Test', time());
7 }
25
Expressive 2 default middlewares
1. Route middleware: parses and identifies the middleware to handle the
request

2. Dispatching middleware: call the middleware identified by route
26
Expressive implementations
1. psr/http-message (Common interface for HTTP messages) (based on
PSR-7)

1. zend-stratigility (Middleware for PHP)

2. zend-diactoros (PSR HTTP Message implementations)

3. http-interop/http-middleware (Common interface for HTTP server-side
middleware)
27
Zend-Stratigility
1. Routing

2. PSR-11 container (dependency injection)

3. Templating

4. Error handling
28
Routers supported
1. Aura.Router

2. FastRoute

3. zend-mvc Router
29
Containers supported
1. Zend-servicemanager

2. pimple-interop

3. aura.di
30
Templates supported
1. Plates

2. Twig

3. zend-view
31
Error handler supported
1. Whoops: whoops is an error handler framework for PHP. Out-of-the-box,
it provides a pretty error interface that helps you debug your web
projects, but at heart it's a simple yet powerful stacked error handling
system.
32
Zend-Diactoros
zend-diactoros is a PHP package containing implementations of
the accepted PSR-7 HTTP message interfaces, as well as a "server"
implementation similar to node's http.Server.

All the responses will be handled with Diactoros.
33
Interop 0.4.1
1 <?php
2 namespace InteropHttpServerMiddleware;
3
4 use PsrHttpMessageResponseInterface;
5 use PsrHttpMessageServerRequestInterface;
6
7 interface MiddlewareInterface
8 {
9 public function process(
10 ServerRequestInterface $request,
11 DelegateInterface $delegate
12 ) : ResponseInterface;
13 }
14
15 interface DelegateInterface
16 {
17 public function process(
18 ServerRequestInterface $request
19 ) : ResponseInterface;
20 }
34
Creating a Web Application
with expressive
35
Web application
1. It will consume a remote API for authors to be able to do:

1. List of authors

2. Adding authors

3. Editing authors

4. Deleting authors
36
https://bitbucket.org/
gabriel0702/quotesexpressive
37
Authors list
38
Creating the project
composer create-project zendframework/zend-expressive-skeleton
QuotesExpressive
39
Choose application type
What type of installation would you like?

[1] Minimal (no default middleware, templates, or assets; configuration
only)

[2] Flat (flat source code structure; default selection)

[3] Modular (modular source code structure; recommended)

Make your selection (2): 3
40
Choose Container for DI
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):
41
Choose 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):
42
Choose Template engine
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):1
43
Choose Error handler
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):
44
Create module
php vendor/bin/expressive module:create Authors

composer dump-autoload
45
Create module
src/Authors
├── src
│   └── ConfigProvider.php
└── templates
46
Create Authors’ list
1. Configure templates in ConfigProvider

2. Create Authors list action class (ListAction.php)

3. Register class in dependencies in configuration.

4. Configure routes in routes.php

5. Generate factory for ListAction

6. Update the dependencies in dependencies.global.php
47
Create Authors’ list
7. Configure global.php file

8. composer require zendframework/zend-http

9. Configure local.php with credentials

10.composer require zendframework/zend-json

11.Modify list template

12.create AuthorRestCollection

13.php -S 0.0.0.0:8082 -t public
48
routes.php
1 <?php
2 ...
3 $app->get(
4 '/author',
5 AuthorsActionListAction::class,
6 'authors.list'
7 );
8 ...
49
dependencies.global.php
1 <?php
2 ...
3 AuthorsActionListAction::class => AuthorsActionListActionFactory::class,
4 AuthorsModelAuthorRestCollection::class=>function($container) {
5 $httpClient=$container->get(AuthorsModelAuthorHttpClient::class);
6 return new AuthorsModelAuthorRestCollection($httpClient);
7 },
8 AuthorsModelAuthorHttpClient::class => function($container) {
9 $config=$container->get('config');
10 $client=new Client($config['httpclient']['base_uri'].
11 $config['httpclient']['authors']['route']);
12 $client->setHeaders($config['httpclient']['headers']);
13 $client->setAuth(
14 $config['httpclient']['basic_auth']['user'],
15 $config['httpclient']['basic_auth']['password']
16 );
17 return $client;
18 },
19 ...
50
global.php
1 <?php
2 return [
3 'httpclient'=>[
4 'base_uri'=>'http://localhost:8081/',
5 'headers'=>[
6 'Accept'=>'*/*',
7 ],
8 'authors'=>[
9 'route'=>'authors',
10 ],
11 ],
12 ];
51
ListActionFactory.php
1 <?php
2 ...
3 public function __invoke(
4 ContainerInterface $container,
5 $requestedName,
6 array $options = null)
7 {
8 return new ListAction(
9 $container->get(...
TemplateRendererInterface::class),
10 $container->get(...AuthorRestCollection::class)
11 );
12 }
13 ...
52
ListAction.php
1 <?php
2 ...
3 class ListAction implements MiddlewareInterface
4 {
5 ...
6 public function process(
7 ServerRequestInterface $request,
8 DelegateInterface $delegate
9 )
10 {
11 $authors=$this->authorrestcollection->fetchAll();
12 return new HtmlResponse(
13 $this->renderer->render(
14 'author/view::authors-list',
15 ['authors'=>$authors]
16 )
17 );
18 }
19 ...
20 }
53
AuthorRestCollection.php
1 <?php
2 class AuthorRestCollection
3 {
4 ...
5 public function fetchAll()
6 {
7 $res=$this->httpClient->send();
8 $json=new Json();
9 $all=$json->decode($res->getContent());
10 return $all;
11 }
12 ...
13 }
54
55
One class per action?!?
56
Handling multiples routes in a
single class
57
Adding authors
58
Multiple routes in single class
1. Create Abstract page class in App

2. Create AuthorsPage class in Authors/Action

3. Create AuthorsPageFactory class

4. Create indexAction in AuthorsPage

5. Create authors-index.phtml template

6. Configure factories in dependencies.global.php

7. Update routes configuration
59
Multiple routes in single class
8. Test index action

9. Create form

10.Add addAction

11.Create add template

12.Add saveAuthor method to AuthorRestCollection
60
routes.php
1 <?php
2 ...
3 $app->route(
4 '/author[/{action:add|edit}[/{id}]]',
5 AuthorsActionAuthorsPage::class,
6 ['GET','POST'],
7 'author');
8 ...
61
AbstractPage.php
1 <?php
2 ...
3 abstract class AbstractPage
4 implements MiddlewareInterface
5 {
6 public function process(
7 ServerRequestInterface $request,
8 DelegateInterface $delegate
9 )
10 {
11 $action = $request->getAttribute('action', 'index') . 'Action';
12 if (! method_exists($this, $action)) {
13 return new EmptyResponse(StatusCode::STATUS_NOT_FOUND);
14 }
15 return $this->$action($request, $delegate);
16 }
17 }
62
AuthorsPageFactory.php
1 <?php
2 ...
3 class AuthorsPageFactory implements FactoryInterface
4 {
5 public function __invoke(
6 ContainerInterface $container,
7 $requestedName,
8 array $options = null)
9 {
10 return new AuthorsPage(
11 $container->get(...
TemplateRendererInterface::class),
12 $container->get(...AuthorRestCollection::class)
13 );
14 }
15 }
63
AuthorsPage.php
1 <?php
2 ...
3 class AuthorsPage extends AbstractPage
4 {
5 ...
6 public function indexAction(
7 ServerRequestInterface $request,
8 DelegateInterface $delegate)
9 {
10 $authors=$this->authorrestcollection->fetchAll();
11 return new HtmlResponse(
12 $this->renderer->render('author/view::authors-index',
['authors'=>$authors])
13 );
14 }
15 ...
16 }
64
AuthorsPage.php addAction
1 <?php
2 ...
3 public function addAction(
4 ServerRequestInterface $request,
5 DelegateInterface $delegate
6 )
7 {
8 if($request->getMethod()!=='POST')
9 {
10 return new HtmlResponse(
11 $this->renderer->render('author/view::authors-add')
12 );
13 }
14 ...
15 if(!$form->isValid())
16 {
17 return new HtmlResponse(
18 $this->renderer->render('author/view::authors-add')
19 );
20 }
21 $author->exchangeArray($form->getData());
22 $this->authorrestcollection->saveAuthor($author);
23 return new RedirectResponse("/author");
24 }
65
AuthorRestCollection.php
1 <?php
2 ...
3 public function saveAuthor(Author $author)
4 {
5 $data=$author->getData();
6 $entity_id=(int)$data['entity_id'];
7
8 if(empty($entity_id))
9 {
10 $this->httpClient->setMethod('POST');
11 }
12 else
13 {
14 $this->httpClient->setMethod('PUT');
15 }
16 $json=$this->getJson();
17 $body=$json->encode($data);
18
19 $this->httpClient->setRawBody($body);
20 $res=$this->httpClient->send();
21 if($res->getStatusCode()!=201)
22 {
23 throw new RuntimeException("The author could not be saved.");
24 }
25 }
66
67
Editing authors
68
Editing authors
1. Add edit action

2. Add edit template

3. Create getAuthor in RestCollection

4. Change the condition to be 200 or 201 depending on the presence of
entity_id
69
Editing authors
5. Modify factories in order to pass settings later

6. Configure editAction

7. Configure edit template
70
dependencies.global.php
1 <?php
2 ...
3 AuthorsModelAuthorRestCollection::class=>function($container) {
4 $httpClient=$container->get(...AuthorHttpClient::class);
5 $config=$container->get('config');
6 return new ...AuthorRestCollection(
7 $httpClient,
8 $config['httpclient']
9 );
10 },
11 AuthorsModelAuthorHttpClient::class => function() {
12 return new Client();
13 },
14 AuthorsActionAuthorsPage::class =>
AuthorsActionAuthorsPageFactory::class,
15 ...
71
AuthorsPage.php editAction
1 <?php
2 public function editAction(
3 ServerRequestInterface $request,
4 DelegateInterface $delegate
5 )
6 {
7 ...
8 if($entity_id===0)
9 {
10 return $this->redirect()->toRoute('author',['action'=>'add']);
11 }
12 $author=$this->authorrestcollection->getAuthor($entity_id);
13 ...
14 if($request->getMethod()!=='POST')
15 {
16 return new HtmlResponse(
17 $this->renderer->render('author/view::authors-edit', $viewData)
18 );
19 }
20 ...
21 $this->authorrestcollection->saveAuthor($author);
22 return new RedirectResponse("/author");
23 }
72
AuthorRestCollection saveAuthor
1 public function saveAuthor(Author $author)
2 {
3 ...
4 if(empty($entity_id) and $res->getStatusCode()!=201)
5 {
6 throw new RuntimeException("The author could not be saved.");
7 }
8 if(!empty($entity_id) and $res->getStatusCode()!=200)
9 {
10 throw new RuntimeException("The author could not be saved.");
11 }
12 }
73
AuthorRestCollection getAuthor
1 public function getAuthor($id)
2 {
3 $id=(int)$id;
4 $this->httpClient->setMethod('GET');
5 $this->httpClient->setUri($this->httpClientUri."/$id");
6 $res=$this->httpClient->send();
7 if($res->getStatusCode()!=200)
8 {
9 throw new RuntimeException(sprintf("There is no author
with ID %d", $id));
10 }
11 $json=$this->getJson();
12 $all=$json->decode($res->getContent());
13 $author=new Author();
14 $author->exchangeArray(get_object_vars($all));
15 return $author;
16 }
74
75
Deleting authors
76
Deleting authors
1. Create delete action

2. Create template for delete

3. Create deleteAuthor in AuthorRestCollection

4. Modify routes to accept delete action
77
routes.php
1 <?php
2 $app->route(
3 '/author[/{action:add|edit|delete}[/{id}]]',
4 AuthorsActionAuthorsPage::class,['GET','POST'],
5 'author'
6 );
78
AuthorsPage.php deleteAction
1 <?php
2 public function deleteAction(
3 ServerRequestInterface $request,
4 DelegateInterface $delegate
5 )
6 {
7 ...
8 if($entity_id===0)
9 {
10 return $this->redirect()->toRoute('author',['action'=>'add']);
11 }
12 if($request->getMethod()==='POST')
13 {
14 ...
15 if($del==='Yes')
16 {
17 $id=(int) $post['entity_id'];
18 $this->authorrestcollection->deleteAuthor($id);
19 }
20 return new RedirectResponse("/author");
21 }
22 $author=$this->authorrestcollection->getAuthor($entity_id);
23 return new HtmlResponse(
24 $this->renderer->render("author/view::authors-delete", ['entity_id'=>$entity_id,
'author'=>$author])
25 );
79
AuthorRestCollection deleteAuthor
1 <?php
2 public function deleteAuthor($id)
3 {
4 $id=(int)$id;
5 $this->httpClient->setMethod('DELETE');
6 $this->httpClient->setUri($this-
>httpClientUri."/$id");
7 $res=$this->httpClient->send();
8 if($res->getStatusCode()!=204)
9 {
10 throw new RuntimeException(sprintf("The
author with ID %d was not deleted", $id));
11 }
12 }
80
81
Middleware advantages
1. Easy to learn

2. Easy to implement

3. You don’t loose modularity if you are used to MVC

4. Flexibility, you can use other libraries for routing, templating, DI, etc.

5. It adapts to small and big projects.

6. Easy to implement Zend-* libraries if you are used to them
82
Middleware disadvantages
1. It’s a relatively “new” conceptual implementation in PHP, which is subject
to more changes or adjustments and you’ll need to be ready if you want
to catch up with updates

2. since it’s relatively “new” also, there are no too many people with
experience on this.
83
Questions?
84
Thank you
85
https://joind.in/talk/b5ac8

Mais conteúdo relacionado

Mais procurados

Ruby HTTP clients comparison
Ruby HTTP clients comparisonRuby HTTP clients comparison
Ruby HTTP clients comparison
Hiroshi Nakamura
 
Zend Framework 2 - presentation
Zend Framework 2 - presentationZend Framework 2 - presentation
Zend Framework 2 - presentation
yamcsha
 
Migrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain PointsMigrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain Points
Steven Evatt
 
Writing php extensions in golang
Writing php extensions in golangWriting php extensions in golang
Writing php extensions in golang
do_aki
 

Mais procurados (19)

Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)
Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)
Kicking off with Zend Expressive and Doctrine ORM (ZendCon 2016)
 
Deprecated: Foundations of Zend Framework 2
Deprecated: Foundations of Zend Framework 2Deprecated: Foundations of Zend Framework 2
Deprecated: Foundations of Zend Framework 2
 
Php Ppt
Php PptPhp Ppt
Php Ppt
 
G rpc lection1
G rpc lection1G rpc lection1
G rpc lection1
 
PHP from soup to nuts Course Deck
PHP from soup to nuts Course DeckPHP from soup to nuts Course Deck
PHP from soup to nuts Course Deck
 
Entity provider selection confusion attacks in JAX-RS applications
Entity provider selection confusion attacks in JAX-RS applicationsEntity provider selection confusion attacks in JAX-RS applications
Entity provider selection confusion attacks in JAX-RS applications
 
Rails vs Web2py
Rails vs Web2pyRails vs Web2py
Rails vs Web2py
 
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ BehaviourWAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
WAF Bypass Techniques - Using HTTP Standard and Web Servers’ Behaviour
 
Neat tricks to bypass CSRF-protection
Neat tricks to bypass CSRF-protectionNeat tricks to bypass CSRF-protection
Neat tricks to bypass CSRF-protection
 
You suck at Memory Analysis
You suck at Memory AnalysisYou suck at Memory Analysis
You suck at Memory Analysis
 
Hacking Adobe Experience Manager sites
Hacking Adobe Experience Manager sitesHacking Adobe Experience Manager sites
Hacking Adobe Experience Manager sites
 
Zend Framework 2 Components
Zend Framework 2 ComponentsZend Framework 2 Components
Zend Framework 2 Components
 
Information security programming in ruby
Information security programming in rubyInformation security programming in ruby
Information security programming in ruby
 
Frans Rosén Keynote at BSides Ahmedabad
Frans Rosén Keynote at BSides AhmedabadFrans Rosén Keynote at BSides Ahmedabad
Frans Rosén Keynote at BSides Ahmedabad
 
Ruby HTTP clients comparison
Ruby HTTP clients comparisonRuby HTTP clients comparison
Ruby HTTP clients comparison
 
Zend Framework 2 - presentation
Zend Framework 2 - presentationZend Framework 2 - presentation
Zend Framework 2 - presentation
 
Migrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain PointsMigrating PriceChirp to Rails 3.0: The Pain Points
Migrating PriceChirp to Rails 3.0: The Pain Points
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
 
Writing php extensions in golang
Writing php extensions in golangWriting php extensions in golang
Writing php extensions in golang
 

Semelhante a Make your application expressive

Application Deployment with Zend Server 5.5 beta
Application Deployment with Zend Server 5.5 betaApplication Deployment with Zend Server 5.5 beta
Application Deployment with Zend Server 5.5 beta
10n Software, LLC
 
How to create multiprocess server on windows with ruby - rubykaigi2016 Ritta ...
How to create multiprocess server on windows with ruby - rubykaigi2016 Ritta ...How to create multiprocess server on windows with ruby - rubykaigi2016 Ritta ...
How to create multiprocess server on windows with ruby - rubykaigi2016 Ritta ...
Ritta Narita
 
Ein Stall voller Trüffelschweine - (PHP-)Profiling-Tools im Überblick
Ein Stall voller Trüffelschweine - (PHP-)Profiling-Tools im ÜberblickEin Stall voller Trüffelschweine - (PHP-)Profiling-Tools im Überblick
Ein Stall voller Trüffelschweine - (PHP-)Profiling-Tools im Überblick
renebruns
 
PHP
PHPPHP
Nt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language AnalysisNt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language Analysis
Nicole Gomez
 

Semelhante a Make your application expressive (20)

Introduction to web and php mysql
Introduction to web and php mysqlIntroduction to web and php mysql
Introduction to web and php mysql
 
PHP Basics
PHP BasicsPHP Basics
PHP Basics
 
Was faqs
Was faqsWas faqs
Was faqs
 
PHP Unit-1 Introduction to PHP
PHP Unit-1 Introduction to PHPPHP Unit-1 Introduction to PHP
PHP Unit-1 Introduction to PHP
 
My Saminar On Php
My Saminar On PhpMy Saminar On Php
My Saminar On Php
 
Essential Tools for Modern PHP
Essential Tools for Modern PHPEssential Tools for Modern PHP
Essential Tools for Modern PHP
 
Workshop Laravel 5.2
Workshop Laravel 5.2Workshop Laravel 5.2
Workshop Laravel 5.2
 
Application Deployment with Zend Server 5.5 beta
Application Deployment with Zend Server 5.5 betaApplication Deployment with Zend Server 5.5 beta
Application Deployment with Zend Server 5.5 beta
 
Web Server and how we can design app in C#
Web Server and how we can design app  in C#Web Server and how we can design app  in C#
Web Server and how we can design app in C#
 
Networked APIs with swift
Networked APIs with swiftNetworked APIs with swift
Networked APIs with swift
 
PHP QA Tools
PHP QA ToolsPHP QA Tools
PHP QA Tools
 
CocoaConf: The Language of Mobile Software is APIs
CocoaConf: The Language of Mobile Software is APIsCocoaConf: The Language of Mobile Software is APIs
CocoaConf: The Language of Mobile Software is APIs
 
How to create multiprocess server on windows with ruby - rubykaigi2016 Ritta ...
How to create multiprocess server on windows with ruby - rubykaigi2016 Ritta ...How to create multiprocess server on windows with ruby - rubykaigi2016 Ritta ...
How to create multiprocess server on windows with ruby - rubykaigi2016 Ritta ...
 
NodeJS guide for beginners
NodeJS guide for beginnersNodeJS guide for beginners
NodeJS guide for beginners
 
The Veil-Framework
The Veil-FrameworkThe Veil-Framework
The Veil-Framework
 
Serverless forwardjs
Serverless forwardjsServerless forwardjs
Serverless forwardjs
 
Ein Stall voller Trüffelschweine - (PHP-)Profiling-Tools im Überblick
Ein Stall voller Trüffelschweine - (PHP-)Profiling-Tools im ÜberblickEin Stall voller Trüffelschweine - (PHP-)Profiling-Tools im Überblick
Ein Stall voller Trüffelschweine - (PHP-)Profiling-Tools im Überblick
 
PHP
PHPPHP
PHP
 
Advanced Java Topics
Advanced Java TopicsAdvanced Java Topics
Advanced Java Topics
 
Nt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language AnalysisNt1310 Unit 3 Language Analysis
Nt1310 Unit 3 Language Analysis
 

Último

AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
Alluxio, Inc.
 
JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
Max Lee
 

Último (20)

COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
 
10 Essential Software Testing Tools You Need to Know About.pdf
10 Essential Software Testing Tools You Need to Know About.pdf10 Essential Software Testing Tools You Need to Know About.pdf
10 Essential Software Testing Tools You Need to Know About.pdf
 
5 Reasons Driving Warehouse Management Systems Demand
5 Reasons Driving Warehouse Management Systems Demand5 Reasons Driving Warehouse Management Systems Demand
5 Reasons Driving Warehouse Management Systems Demand
 
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdfA Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
 
Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024
 
Secure Software Ecosystem Teqnation 2024
Secure Software Ecosystem Teqnation 2024Secure Software Ecosystem Teqnation 2024
Secure Software Ecosystem Teqnation 2024
 
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdf
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdfImplementing KPIs and Right Metrics for Agile Delivery Teams.pdf
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdf
 
Crafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM IntegrationCrafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM Integration
 
The Impact of PLM Software on Fashion Production
The Impact of PLM Software on Fashion ProductionThe Impact of PLM Software on Fashion Production
The Impact of PLM Software on Fashion Production
 
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
Entropy, Software Quality, and Innovation (presented at Princeton Plasma Phys...
 
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
AI/ML Infra Meetup | Improve Speed and GPU Utilization for Model Training & S...
 
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purityAPVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
 
JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
 
What need to be mastered as AI-Powered Java Developers
What need to be mastered as AI-Powered Java DevelopersWhat need to be mastered as AI-Powered Java Developers
What need to be mastered as AI-Powered Java Developers
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 
INGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by DesignINGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by Design
 
AI Hackathon.pptx
AI                        Hackathon.pptxAI                        Hackathon.pptx
AI Hackathon.pptx
 
IT Software Development Resume, Vaibhav jha 2024
IT Software Development Resume, Vaibhav jha 2024IT Software Development Resume, Vaibhav jha 2024
IT Software Development Resume, Vaibhav jha 2024
 
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
Tree in the Forest - Managing Details in BDD Scenarios (live2test 2024)
 
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product UpdatesGraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
GraphSummit Stockholm - Neo4j - Knowledge Graphs and Product Updates
 

Make your application expressive

  • 1. Make your Application Expressive By Christian Varela @gabriel0702 cvarela@conquerorsoft.com https://joind.in/talk/b5ac8 1
  • 3. Christian Varela • I have a wife and 3 daughters • I am from Mexico • Master Degree in Computer Science • 13 years programming with PHP • I live in Miami • I created Conqueror Soft Inc • I play guitar and piano 3
  • 4. 4
  • 5. Conqueror Soft will take your business to the next Level! 5 www.conquerorsoft.com info@conquerorsoft.com facebook.com/conquerorsoft
  • 6. What is this session about? Learn the concepts of PSR-7 middleware with Zend Expressive and how your application could be developed from scratch adapting those concepts with a new mindset. You'll see the different approaches, advantages and disadvantages, and the contrast of this paradigm and other more conventional paradigms. 6
  • 7. Expressive Expressive it is a framework by Zend that allows you to write PSR-7 middleware applications for the web. 7
  • 8. PSR-7 1. PHP Standard Recommendation 7 2. HTTP message interfaces 3. Describes common interfaces for representing HTTP messages as described in RFC 7230 and RFC 7231 4. Describes interfaces for representing URIs for use with HTTP messages as described in RFC 3986. 8
  • 9. HTTP messages 1. They are messages between servers and clients in the web 1. HTTP request messages 2. HTTP response messages 9
  • 10. HTTP Request messages 1. Request line 1. Method 2. Target 3. HTTP protocol version 2. One or more headers 3. empty line 4. Message body 10
  • 11. HTTP Request messages POST /authors HTTP/1.1 Host: localhost:8081 Content-Type: application/json Authorization: Basic [replace_with_password] Cache-Control: no-cache Postman-Token: 1b196a8d-c32b-be43-5523-d5354e5b5cc5 { "first_name":"First_name", "last_name":"Last_name", "dob":"1900-01-01" } 11
  • 12. HTTP Response messages 1. Status line 1. HTTP protocol version Method 2. HTTP status code 3. Reason phrase 2. One or more headers 3. empty line 4. Message body 12
  • 13. HTTP Response messages HTTP/1.1 201 Created host:"localhost:8081" date:"Sun, 08 Oct 2017 21:07:33 +0000" connection:"close" x-powered-by:"PHP/7.1.1" location:"http://localhost:8081/authors/33" content-location:"http://localhost:8081/authors/33" content-type:"application/json" vary:"Origin" { "entity_id": "33", "first_name": "First_name", "last_name": "Last_name", "dob": "1900-01-01", "created_at": null } 13
  • 16. Middleware Middleware is code that exists between the request and response, and which can take the incoming request, perform actions based on it, and either complete the response or pass delegation on to the next middleware in the queue. 16
  • 17. Middleware For example, you could have a collection of middleware like this: 1.reverse string 2.convert string to upper case 3.shuffle string 17
  • 18. Middleware 1 $app=new Middleware(); 2 $app->pipe($errorHandler); 3 $app->pipe($reverseMiddleware); 4 $app->pipe($uppercaseMiddleware); 5 $app->pipe($shuffleMiddleware); 6 $app->pipe($defaultMiddleware); 7 $app->run(); 18
  • 19. Middleware 19 In (request) Out (response) to delegate from delegate
  • 22. Middleware 22 Error handler Reverse Uppercase Shuffle Default In Out Middleware something GSNEHOMIT Error something GSNEHOMIT Reverse something TIMOHENSG Uppercase something timohensg Shuffle something something Default
  • 23. How expressive puts all that in practice? 23
  • 24. Expressive 1.X middleware 1 <?php 2 function ( 3 ServerRequestInterface $request, 4 ResponseInterface $response, 5 callable $next) 6 { 7 $response = $next($request, $response); 8 return $response->withHeader('X-Test', time()); 9 } 24
  • 25. Expressive 2 middleware 1 function ( 2 ServerRequestInterface $request, 3 DelegateInterface $delegate) 4 { 5 $response = $delegate->process($request); 6 return $response->withHeader('X-Test', time()); 7 } 25
  • 26. Expressive 2 default middlewares 1. Route middleware: parses and identifies the middleware to handle the request 2. Dispatching middleware: call the middleware identified by route 26
  • 27. Expressive implementations 1. psr/http-message (Common interface for HTTP messages) (based on PSR-7) 1. zend-stratigility (Middleware for PHP) 2. zend-diactoros (PSR HTTP Message implementations) 3. http-interop/http-middleware (Common interface for HTTP server-side middleware) 27
  • 28. Zend-Stratigility 1. Routing 2. PSR-11 container (dependency injection) 3. Templating 4. Error handling 28
  • 29. Routers supported 1. Aura.Router 2. FastRoute 3. zend-mvc Router 29
  • 30. Containers supported 1. Zend-servicemanager 2. pimple-interop 3. aura.di 30
  • 31. Templates supported 1. Plates 2. Twig 3. zend-view 31
  • 32. Error handler supported 1. Whoops: whoops is an error handler framework for PHP. Out-of-the-box, it provides a pretty error interface that helps you debug your web projects, but at heart it's a simple yet powerful stacked error handling system. 32
  • 33. Zend-Diactoros zend-diactoros is a PHP package containing implementations of the accepted PSR-7 HTTP message interfaces, as well as a "server" implementation similar to node's http.Server. All the responses will be handled with Diactoros. 33
  • 34. Interop 0.4.1 1 <?php 2 namespace InteropHttpServerMiddleware; 3 4 use PsrHttpMessageResponseInterface; 5 use PsrHttpMessageServerRequestInterface; 6 7 interface MiddlewareInterface 8 { 9 public function process( 10 ServerRequestInterface $request, 11 DelegateInterface $delegate 12 ) : ResponseInterface; 13 } 14 15 interface DelegateInterface 16 { 17 public function process( 18 ServerRequestInterface $request 19 ) : ResponseInterface; 20 } 34
  • 35. Creating a Web Application with expressive 35
  • 36. Web application 1. It will consume a remote API for authors to be able to do: 1. List of authors 2. Adding authors 3. Editing authors 4. Deleting authors 36
  • 39. Creating the project composer create-project zendframework/zend-expressive-skeleton QuotesExpressive 39
  • 40. Choose application type What type of installation would you like? [1] Minimal (no default middleware, templates, or assets; configuration only) [2] Flat (flat source code structure; default selection) [3] Modular (modular source code structure; recommended) Make your selection (2): 3 40
  • 41. Choose Container for DI 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): 41
  • 42. Choose 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): 42
  • 43. Choose Template engine 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):1 43
  • 44. Choose Error handler 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): 44
  • 45. Create module php vendor/bin/expressive module:create Authors composer dump-autoload 45
  • 46. Create module src/Authors ├── src │   └── ConfigProvider.php └── templates 46
  • 47. Create Authors’ list 1. Configure templates in ConfigProvider 2. Create Authors list action class (ListAction.php) 3. Register class in dependencies in configuration. 4. Configure routes in routes.php 5. Generate factory for ListAction 6. Update the dependencies in dependencies.global.php 47
  • 48. Create Authors’ list 7. Configure global.php file 8. composer require zendframework/zend-http 9. Configure local.php with credentials 10.composer require zendframework/zend-json 11.Modify list template 12.create AuthorRestCollection 13.php -S 0.0.0.0:8082 -t public 48
  • 49. routes.php 1 <?php 2 ... 3 $app->get( 4 '/author', 5 AuthorsActionListAction::class, 6 'authors.list' 7 ); 8 ... 49
  • 50. dependencies.global.php 1 <?php 2 ... 3 AuthorsActionListAction::class => AuthorsActionListActionFactory::class, 4 AuthorsModelAuthorRestCollection::class=>function($container) { 5 $httpClient=$container->get(AuthorsModelAuthorHttpClient::class); 6 return new AuthorsModelAuthorRestCollection($httpClient); 7 }, 8 AuthorsModelAuthorHttpClient::class => function($container) { 9 $config=$container->get('config'); 10 $client=new Client($config['httpclient']['base_uri']. 11 $config['httpclient']['authors']['route']); 12 $client->setHeaders($config['httpclient']['headers']); 13 $client->setAuth( 14 $config['httpclient']['basic_auth']['user'], 15 $config['httpclient']['basic_auth']['password'] 16 ); 17 return $client; 18 }, 19 ... 50
  • 51. global.php 1 <?php 2 return [ 3 'httpclient'=>[ 4 'base_uri'=>'http://localhost:8081/', 5 'headers'=>[ 6 'Accept'=>'*/*', 7 ], 8 'authors'=>[ 9 'route'=>'authors', 10 ], 11 ], 12 ]; 51
  • 52. ListActionFactory.php 1 <?php 2 ... 3 public function __invoke( 4 ContainerInterface $container, 5 $requestedName, 6 array $options = null) 7 { 8 return new ListAction( 9 $container->get(... TemplateRendererInterface::class), 10 $container->get(...AuthorRestCollection::class) 11 ); 12 } 13 ... 52
  • 53. ListAction.php 1 <?php 2 ... 3 class ListAction implements MiddlewareInterface 4 { 5 ... 6 public function process( 7 ServerRequestInterface $request, 8 DelegateInterface $delegate 9 ) 10 { 11 $authors=$this->authorrestcollection->fetchAll(); 12 return new HtmlResponse( 13 $this->renderer->render( 14 'author/view::authors-list', 15 ['authors'=>$authors] 16 ) 17 ); 18 } 19 ... 20 } 53
  • 54. AuthorRestCollection.php 1 <?php 2 class AuthorRestCollection 3 { 4 ... 5 public function fetchAll() 6 { 7 $res=$this->httpClient->send(); 8 $json=new Json(); 9 $all=$json->decode($res->getContent()); 10 return $all; 11 } 12 ... 13 } 54
  • 55. 55
  • 56. One class per action?!? 56
  • 57. Handling multiples routes in a single class 57
  • 59. Multiple routes in single class 1. Create Abstract page class in App 2. Create AuthorsPage class in Authors/Action 3. Create AuthorsPageFactory class 4. Create indexAction in AuthorsPage 5. Create authors-index.phtml template 6. Configure factories in dependencies.global.php 7. Update routes configuration 59
  • 60. Multiple routes in single class 8. Test index action 9. Create form 10.Add addAction 11.Create add template 12.Add saveAuthor method to AuthorRestCollection 60
  • 61. routes.php 1 <?php 2 ... 3 $app->route( 4 '/author[/{action:add|edit}[/{id}]]', 5 AuthorsActionAuthorsPage::class, 6 ['GET','POST'], 7 'author'); 8 ... 61
  • 62. AbstractPage.php 1 <?php 2 ... 3 abstract class AbstractPage 4 implements MiddlewareInterface 5 { 6 public function process( 7 ServerRequestInterface $request, 8 DelegateInterface $delegate 9 ) 10 { 11 $action = $request->getAttribute('action', 'index') . 'Action'; 12 if (! method_exists($this, $action)) { 13 return new EmptyResponse(StatusCode::STATUS_NOT_FOUND); 14 } 15 return $this->$action($request, $delegate); 16 } 17 } 62
  • 63. AuthorsPageFactory.php 1 <?php 2 ... 3 class AuthorsPageFactory implements FactoryInterface 4 { 5 public function __invoke( 6 ContainerInterface $container, 7 $requestedName, 8 array $options = null) 9 { 10 return new AuthorsPage( 11 $container->get(... TemplateRendererInterface::class), 12 $container->get(...AuthorRestCollection::class) 13 ); 14 } 15 } 63
  • 64. AuthorsPage.php 1 <?php 2 ... 3 class AuthorsPage extends AbstractPage 4 { 5 ... 6 public function indexAction( 7 ServerRequestInterface $request, 8 DelegateInterface $delegate) 9 { 10 $authors=$this->authorrestcollection->fetchAll(); 11 return new HtmlResponse( 12 $this->renderer->render('author/view::authors-index', ['authors'=>$authors]) 13 ); 14 } 15 ... 16 } 64
  • 65. AuthorsPage.php addAction 1 <?php 2 ... 3 public function addAction( 4 ServerRequestInterface $request, 5 DelegateInterface $delegate 6 ) 7 { 8 if($request->getMethod()!=='POST') 9 { 10 return new HtmlResponse( 11 $this->renderer->render('author/view::authors-add') 12 ); 13 } 14 ... 15 if(!$form->isValid()) 16 { 17 return new HtmlResponse( 18 $this->renderer->render('author/view::authors-add') 19 ); 20 } 21 $author->exchangeArray($form->getData()); 22 $this->authorrestcollection->saveAuthor($author); 23 return new RedirectResponse("/author"); 24 } 65
  • 66. AuthorRestCollection.php 1 <?php 2 ... 3 public function saveAuthor(Author $author) 4 { 5 $data=$author->getData(); 6 $entity_id=(int)$data['entity_id']; 7 8 if(empty($entity_id)) 9 { 10 $this->httpClient->setMethod('POST'); 11 } 12 else 13 { 14 $this->httpClient->setMethod('PUT'); 15 } 16 $json=$this->getJson(); 17 $body=$json->encode($data); 18 19 $this->httpClient->setRawBody($body); 20 $res=$this->httpClient->send(); 21 if($res->getStatusCode()!=201) 22 { 23 throw new RuntimeException("The author could not be saved."); 24 } 25 } 66
  • 67. 67
  • 69. Editing authors 1. Add edit action 2. Add edit template 3. Create getAuthor in RestCollection 4. Change the condition to be 200 or 201 depending on the presence of entity_id 69
  • 70. Editing authors 5. Modify factories in order to pass settings later 6. Configure editAction 7. Configure edit template 70
  • 71. dependencies.global.php 1 <?php 2 ... 3 AuthorsModelAuthorRestCollection::class=>function($container) { 4 $httpClient=$container->get(...AuthorHttpClient::class); 5 $config=$container->get('config'); 6 return new ...AuthorRestCollection( 7 $httpClient, 8 $config['httpclient'] 9 ); 10 }, 11 AuthorsModelAuthorHttpClient::class => function() { 12 return new Client(); 13 }, 14 AuthorsActionAuthorsPage::class => AuthorsActionAuthorsPageFactory::class, 15 ... 71
  • 72. AuthorsPage.php editAction 1 <?php 2 public function editAction( 3 ServerRequestInterface $request, 4 DelegateInterface $delegate 5 ) 6 { 7 ... 8 if($entity_id===0) 9 { 10 return $this->redirect()->toRoute('author',['action'=>'add']); 11 } 12 $author=$this->authorrestcollection->getAuthor($entity_id); 13 ... 14 if($request->getMethod()!=='POST') 15 { 16 return new HtmlResponse( 17 $this->renderer->render('author/view::authors-edit', $viewData) 18 ); 19 } 20 ... 21 $this->authorrestcollection->saveAuthor($author); 22 return new RedirectResponse("/author"); 23 } 72
  • 73. AuthorRestCollection saveAuthor 1 public function saveAuthor(Author $author) 2 { 3 ... 4 if(empty($entity_id) and $res->getStatusCode()!=201) 5 { 6 throw new RuntimeException("The author could not be saved."); 7 } 8 if(!empty($entity_id) and $res->getStatusCode()!=200) 9 { 10 throw new RuntimeException("The author could not be saved."); 11 } 12 } 73
  • 74. AuthorRestCollection getAuthor 1 public function getAuthor($id) 2 { 3 $id=(int)$id; 4 $this->httpClient->setMethod('GET'); 5 $this->httpClient->setUri($this->httpClientUri."/$id"); 6 $res=$this->httpClient->send(); 7 if($res->getStatusCode()!=200) 8 { 9 throw new RuntimeException(sprintf("There is no author with ID %d", $id)); 10 } 11 $json=$this->getJson(); 12 $all=$json->decode($res->getContent()); 13 $author=new Author(); 14 $author->exchangeArray(get_object_vars($all)); 15 return $author; 16 } 74
  • 75. 75
  • 77. Deleting authors 1. Create delete action 2. Create template for delete 3. Create deleteAuthor in AuthorRestCollection 4. Modify routes to accept delete action 77
  • 78. routes.php 1 <?php 2 $app->route( 3 '/author[/{action:add|edit|delete}[/{id}]]', 4 AuthorsActionAuthorsPage::class,['GET','POST'], 5 'author' 6 ); 78
  • 79. AuthorsPage.php deleteAction 1 <?php 2 public function deleteAction( 3 ServerRequestInterface $request, 4 DelegateInterface $delegate 5 ) 6 { 7 ... 8 if($entity_id===0) 9 { 10 return $this->redirect()->toRoute('author',['action'=>'add']); 11 } 12 if($request->getMethod()==='POST') 13 { 14 ... 15 if($del==='Yes') 16 { 17 $id=(int) $post['entity_id']; 18 $this->authorrestcollection->deleteAuthor($id); 19 } 20 return new RedirectResponse("/author"); 21 } 22 $author=$this->authorrestcollection->getAuthor($entity_id); 23 return new HtmlResponse( 24 $this->renderer->render("author/view::authors-delete", ['entity_id'=>$entity_id, 'author'=>$author]) 25 ); 79
  • 80. AuthorRestCollection deleteAuthor 1 <?php 2 public function deleteAuthor($id) 3 { 4 $id=(int)$id; 5 $this->httpClient->setMethod('DELETE'); 6 $this->httpClient->setUri($this- >httpClientUri."/$id"); 7 $res=$this->httpClient->send(); 8 if($res->getStatusCode()!=204) 9 { 10 throw new RuntimeException(sprintf("The author with ID %d was not deleted", $id)); 11 } 12 } 80
  • 81. 81
  • 82. Middleware advantages 1. Easy to learn 2. Easy to implement 3. You don’t loose modularity if you are used to MVC 4. Flexibility, you can use other libraries for routing, templating, DI, etc. 5. It adapts to small and big projects. 6. Easy to implement Zend-* libraries if you are used to them 82
  • 83. Middleware disadvantages 1. It’s a relatively “new” conceptual implementation in PHP, which is subject to more changes or adjustments and you’ll need to be ready if you want to catch up with updates 2. since it’s relatively “new” also, there are no too many people with experience on this. 83