SlideShare ist ein Scribd-Unternehmen logo
1 von 85
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

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
 

Was ist angesagt? (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
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Kürzlich hochgeladen

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 

Kürzlich hochgeladen (20)

%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 

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