Keeping it smallGetting to know the Slim micro framework             @JeremyKendall
JeremyKendall
JeremyKendallI love to code
JeremyKendallI love to codeI’m terribly forgetful
JeremyKendallI love to codeI’m terribly forgetfulI take pictures
JeremyKendallI love to codeI’m terribly forgetfulI take picturesI work at OpenSky
Micro framework?
Micro framework?Concise codebase
Micro framework?Concise codebaseClear codebase
Micro framework?Concise codebaseClear codebaseAddresses a small set of use cases
Micro framework?Concise codebaseClear codebaseAddresses a small set of use casesAddresses those use cases well
What is Slim?
What is Slim?Inspired by Sinatra
What is Slim?Inspired by SinatraFavors cleanliness over terseness
What is Slim?Inspired by SinatraFavors cleanliness over tersenessFavors common cases over edge cases
Installing Slim
RTFM
RTFM ;-)
Don’t forget .htaccess!RewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^ index.php [QSA,L]http://docs.slimf...
Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {    echo "H...
Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {    echo "H...
Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {    echo "H...
Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {    echo "H...
Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {    echo "H...
Let’s look at aSlim application
Flaming Archer
Flaming Archer    wat
“Great repository names are short and memorable. Need inspiration? How about flaming-archer.”
Flaming Archer
Flaming ArcherPhoto 365 project
Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)
Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles
Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles   Ro...
Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles   Ro...
Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles   Ro...
4 views
phploc --exclude vendor,tests,templates .phploc 1.6.4 by Sebastian Bergmann.Directories:                                  ...
Configuration
return array(    slim => array(        templates.path => __DIR__ . /templates,        log.level => 4,        log.enabled =...
return array(    slim => array(        templates.path => __DIR__ . /templates,        log.level => 4,                     ...
return array(    slim => array(        templates.path => __DIR__ . /templates,        log.level => 4,                     ...
return array(    slim => array(        templates.path => __DIR__ . /templates,        log.level => 4,                     ...
return array(    slim => array(        templates.path => __DIR__ . /templates,        log.level => 4,                     ...
$config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);
$config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);                        C...
Routing
Routing$app->get(/, function () use ($app, $service) {        $images = $service->findAll();        $app->render(index.htm...
RoutingHTTP Method  $app->get(/, function () use ($app, $service) {          $images = $service->findAll();          $app-...
Routing                   Resource URIHTTP Method  $app->get(/, function () use ($app, $service) {          $images = $ser...
Routing                   Resource URIHTTP Method                            Anonymous Function  $app->get(/, function () ...
Routing$app->get(/, function () use ($app, $service) {        $images = $service->findAll();        $app->render(index.htm...
Routing$app->get(/, function () use ($app, $service) {      Grabs all the pics        $images = $service->findAll();      ...
Routing$app->get(/, function () use ($app, $service) {      Grabs all the pics        $images = $service->findAll();      ...
GET$app->get(/:day, function($day) use ($app, $service) {        $image = $service->find($day);        if (!$image) {     ...
GET          URL parameter$app->get(/:day, function($day) use ($app, $service) {        $image = $service->find($day);    ...
GET            ... gets passed as an          URL parameter                               argument$app->get(/:day, functio...
GET            ... gets passed as an          URL parameter                               argument$app->get(/:day, functio...
GET             ... gets passed as an          URL parameter                                argument$app->get(/:day, funct...
GET$app->get(/:day, function($day) use ($app, $service) {        $image = $service->find($day);        if (!$image) {     ...
POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) {        $data = $app->request()->post();...
POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) {        $data = $app->request()->post();...
POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) {        $data = $app->request()->post();...
Multiple methods$app->map(/login, function() {        // Login    })->via(GET, POST);
Multiple methods    Not an HTTP Method$app->map(/login, function() {        // Login    })->via(GET, POST);
Multiple methods    Not an HTTP Method$app->map(/login, function() {        // Login    })->via(GET, POST);              v...
Logging and flash messaging
$app->post(/admin/clear-cache, function() use ($app) {         $log = $app->getLog();         $cleared = null;         $cl...
$app->post(/admin/clear-cache, function() use ($app) {         $log = $app->getLog();       Get the log from   $app       ...
$app->post(/admin/clear-cache, function() use ($app) {         $log = $app->getLog();       Get the log from   $app       ...
$app->post(/admin/clear-cache, function() use ($app) {         $log = $app->getLog();       Get the log from   $app       ...
Middleware“. . . a Slim application can have middlewarethat may inspect, analyze, or modifythe application environment, re...
Hooks
Hooksslim.before
Hooksslim.beforeslim.before.router
Hooksslim.beforeslim.before.routerslim.before.dispatch
Hooksslim.before            slim.after.dispatchslim.before.routerslim.before.dispatch
Hooksslim.before            slim.after.dispatchslim.before.router     slim.after.routerslim.before.dispatch
Hooksslim.before            slim.after.dispatchslim.before.router     slim.after.routerslim.before.dispatch   slim.after
Hooksslim.before            slim.after.dispatchslim.before.router     slim.after.routerslim.before.dispatch   slim.after
class MyMiddleware extends SlimMiddleware{    public function call()    {        //The Slim application        $app = $thi...
class MyMiddleware extends SlimMiddleware     Extend this{    public function call()    {        //The Slim application   ...
class MyMiddleware extends SlimMiddleware            Extend this{    public function call()    {                          ...
class MyMiddleware extends SlimMiddleware            Extend this{    public function call()    {                          ...
class MyMiddleware extends SlimMiddleware            Extend this{    public function call()    {                          ...
Middleware + Hooks = WIN
Navigation example
namespace TsfMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware{    /**     * ...
namespace TsfMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware          exten...
namespace TsfMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware          exten...
public function call(){    $app = $this->app;    $auth = $this->auth;    $req = $app->request();    $home = array(caption ...
public function call(){    $app = $this->app;                           Arrays of    $auth = $this->auth;                 ...
public function call(){    $app = $this->app;                           Arrays of    $auth = $this->auth;                 ...
public function call(){    // . . .    $this->app->hook(slim.before.router, function () use (...) {             foreach ($...
public function call(){                                                Delicious hook    // . . .                         ...
public function call(){                                                 Delicious hook    // . . .                        ...
public function call(){                                                 Delicious hook    // . . .                        ...
public function call(){                                                 Delicious hook    // . . .                        ...
Views
Two great tastesthat taste great together
Twig
TwigConcise
TwigConciseTemplate oriented
TwigConciseTemplate orientedFast
TwigConcise             Multiple inheritanceTemplate orientedFast
TwigConcise             Multiple inheritanceTemplate oriented   BlocksFast
TwigConcise             Multiple inheritanceTemplate oriented   BlocksFast                Automatic escaping
layout.html    andindex.html
layout.html
<title>{% block page_title %} {% endblock %}</title>
<ul class="nav">    {% for link in navigation %}        <li class="{{link.class}}">            <a href="{{link.href}}">{{l...
<h1>365 Days of Photography</h1><h3>Photographer: Jeremy Kendall</h3>{% block content %} {% endblock %}<hr />
index.html
{% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in image...
{% extends layout.html %}      extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for i...
{% extends layout.html %}      extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}        ...
{% extends layout.html %}      extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}        ...
{% extends layout.html %}      extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}        ...
{% extends layout.html %}      extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}        ...
{% extends layout.html %}      extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}        ...
login.html
{% extends layout.html %}{% block page_title %}365.jeremykendall.net | Login{% endblock %}{% block content %}<div class="r...
{% extends layout.html %}{% block page_title %}365.jeremykendall.net | Login{% endblock %}{% block content %}<div class="r...
The other viewswould be redundant
GOTO 0
Small but powerful                     GOTO 0
Small but powerful                         GOTO 0Excellent tools to write elegant code
Small but powerful                         GOTO 0Excellent tools to write elegant codeRouting, middleware & hooks, views
Small but powerful                          GOTO 0Excellent tools to write elegant codeRouting, middleware & hooks, viewsI...
ReadSlim: slimframework.comTwig: twig.sensiolabs.orgComposer: getcomposer.orgMicroPHP Manifesto: microphp.orgFlaming Arche...
Questions?
Thanks!jeremy@jeremykendall.net    @jeremykendall
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
Upcoming SlideShare
Loading in...5
×

Keeping it Small: Getting to know the Slim Micro Framework

1,231

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,231
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
62
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Keeping it Small: Getting to know the Slim Micro Framework

  1. 1. Keeping it smallGetting to know the Slim micro framework @JeremyKendall
  2. 2. JeremyKendall
  3. 3. JeremyKendallI love to code
  4. 4. JeremyKendallI love to codeI’m terribly forgetful
  5. 5. JeremyKendallI love to codeI’m terribly forgetfulI take pictures
  6. 6. JeremyKendallI love to codeI’m terribly forgetfulI take picturesI work at OpenSky
  7. 7. Micro framework?
  8. 8. Micro framework?Concise codebase
  9. 9. Micro framework?Concise codebaseClear codebase
  10. 10. Micro framework?Concise codebaseClear codebaseAddresses a small set of use cases
  11. 11. Micro framework?Concise codebaseClear codebaseAddresses a small set of use casesAddresses those use cases well
  12. 12. What is Slim?
  13. 13. What is Slim?Inspired by Sinatra
  14. 14. What is Slim?Inspired by SinatraFavors cleanliness over terseness
  15. 15. What is Slim?Inspired by SinatraFavors cleanliness over tersenessFavors common cases over edge cases
  16. 16. Installing Slim
  17. 17. RTFM
  18. 18. RTFM ;-)
  19. 19. Don’t forget .htaccess!RewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^ index.php [QSA,L]http://docs.slimframework.com/pages/routing-url-rewriting/
  20. 20. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
  21. 21. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
  22. 22. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
  23. 23. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
  24. 24. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
  25. 25. Let’s look at aSlim application
  26. 26. Flaming Archer
  27. 27. Flaming Archer wat
  28. 28. “Great repository names are short and memorable. Need inspiration? How about flaming-archer.”
  29. 29. Flaming Archer
  30. 30. Flaming ArcherPhoto 365 project
  31. 31. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)
  32. 32. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles
  33. 33. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles Routing
  34. 34. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles Routing Twig views
  35. 35. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles Routing Twig views Middleware
  36. 36. 4 views
  37. 37. phploc --exclude vendor,tests,templates .phploc 1.6.4 by Sebastian Bergmann.Directories: 7Files: 13Lines of Code (LOC): 876 Cyclomatic Complexity / Lines of Code: 0.04Comment Lines of Code (CLOC): 272Non-Comment Lines of Code (NCLOC): 604
  38. 38. Configuration
  39. 39. return array( slim => array( templates.path => __DIR__ . /templates, log.level => 4, log.enabled => true, log.writer => new SlimExtrasLogDateTimeFileWriter( array( path => __DIR__ . /logs, name_format => y-m-d ) ) ), twig => array( // . . . ), cookies => array( // . . . ), flickr.api.key => FLICKR API KEY, pdo => array( // . . . ));
  40. 40. return array( slim => array( templates.path => __DIR__ . /templates, log.level => 4, Slim log.enabled => true, log.writer => new SlimExtrasLogDateTimeFileWriter( array( path => __DIR__ . /logs, name_format => y-m-d ) ) ), twig => array( // . . . ), cookies => array( // . . . ), flickr.api.key => FLICKR API KEY, pdo => array( // . . . ));
  41. 41. return array( slim => array( templates.path => __DIR__ . /templates, log.level => 4, Slim log.enabled => true, log.writer => new SlimExtrasLogDateTimeFileWriter( array( path => __DIR__ . /logs, name_format => y-m-d ) ) Views ), twig => array( // . . . ), cookies => array( // . . . ), flickr.api.key => FLICKR API KEY, pdo => array( // . . . ));
  42. 42. return array( slim => array( templates.path => __DIR__ . /templates, log.level => 4, Slim log.enabled => true, log.writer => new SlimExtrasLogDateTimeFileWriter( array( path => __DIR__ . /logs, name_format => y-m-d ) ) Views ), twig => array( // . . . ), cookies => array( Cookies // . . . ), flickr.api.key => FLICKR API KEY, pdo => array( // . . . ));
  43. 43. return array( slim => array( templates.path => __DIR__ . /templates, log.level => 4, Slim log.enabled => true, log.writer => new SlimExtrasLogDateTimeFileWriter( array( path => __DIR__ . /logs, name_format => y-m-d ) ) Views ), twig => array( // . . . ), cookies => array( Cookies // . . . ), flickr.api.key => FLICKR API KEY, pdo => array( // . . . ) My stuff);
  44. 44. $config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);
  45. 45. $config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]); Config array goes here
  46. 46. Routing
  47. 47. Routing$app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); });
  48. 48. RoutingHTTP Method $app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); } );
  49. 49. Routing Resource URIHTTP Method $app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); } );
  50. 50. Routing Resource URIHTTP Method Anonymous Function $app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); } );
  51. 51. Routing$app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); });
  52. 52. Routing$app->get(/, function () use ($app, $service) { Grabs all the pics $images = $service->findAll(); $app->render(index.html, array(images => $images)); });
  53. 53. Routing$app->get(/, function () use ($app, $service) { Grabs all the pics $images = $service->findAll(); $app->render(index.html, array(images => $images)); }); Passes array of image data to index.html
  54. 54. GET$app->get(/:day, function($day) use ($app, $service) { $image = $service->find($day); if (!$image) { $app->notFound(); } $app->render(images.html, $image); })->conditions(array(day => ([1-9]d?|[12]dd|3[0-5]d|36[0-6])));
  55. 55. GET URL parameter$app->get(/:day, function($day) use ($app, $service) { $image = $service->find($day); if (!$image) { $app->notFound(); } $app->render(images.html, $image); })->conditions(array(day => ([1-9]d?|[12]dd|3[0-5]d|36[0-6])));
  56. 56. GET ... gets passed as an URL parameter argument$app->get(/:day, function($day) use ($app, $service) { $image = $service->find($day); if (!$image) { $app->notFound(); } $app->render(images.html, $image); })->conditions(array(day => ([1-9]d?|[12]dd|3[0-5]d|36[0-6])));
  57. 57. GET ... gets passed as an URL parameter argument$app->get(/:day, function($day) use ($app, $service) { $image = $service->find($day); if (!$image) { $app->notFound(); } $app->render(images.html, $image); })->conditions(array(day => ([1-9]d?|[12]dd|3[0-5]d|36[0-6]))); Condition
  58. 58. GET ... gets passed as an URL parameter argument$app->get(/:day, function($day) use ($app, $service) { $image = $service->find($day); if (!$image) { $app->notFound(); } $app->render(images.html, $image); })->conditions(array(day => ([1-9]d?|[12]dd|3[0-5]d|36[0-6]))); Condition 1 to 366
  59. 59. GET$app->get(/:day, function($day) use ($app, $service) { $image = $service->find($day); if (!$image) { $app->notFound(); 404! } $app->render(images.html, $image); })->conditions(array(day => ([1-9]d?|[12]dd|3[0-5]d|36[0-6])));
  60. 60. POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) { $data = $app->request()->post(); $service->save($data); $app->redirect(/admin); });
  61. 61. POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) { $data = $app->request()->post(); $service->save($data); $app->redirect(/admin); } $_POST data is in); the request object
  62. 62. POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) { $data = $app->request()->post(); $service->save($data); $app->redirect(/admin); } $_POST data is in); the request object 302 Redirect
  63. 63. Multiple methods$app->map(/login, function() { // Login })->via(GET, POST);
  64. 64. Multiple methods Not an HTTP Method$app->map(/login, function() { // Login })->via(GET, POST);
  65. 65. Multiple methods Not an HTTP Method$app->map(/login, function() { // Login })->via(GET, POST); via() is the awesome sauce
  66. 66. Logging and flash messaging
  67. 67. $app->post(/admin/clear-cache, function() use ($app) { $log = $app->getLog(); $cleared = null; $clear = $app->request()->post(clear); if ($clear == 1) { if (apc_clear_cache(user)) { $cleared = Cache was successfully cleared!; } else { $cleared = Cache was not cleared!; $log->error(Cache not cleared); } } $app->flash(cleared, $cleared); $app->redirect(/admin); });
  68. 68. $app->post(/admin/clear-cache, function() use ($app) { $log = $app->getLog(); Get the log from $app $cleared = null; $clear = $app->request()->post(clear); if ($clear == 1) { if (apc_clear_cache(user)) { $cleared = Cache was successfully cleared!; } else { $cleared = Cache was not cleared!; $log->error(Cache not cleared); } } $app->flash(cleared, $cleared); $app->redirect(/admin); });
  69. 69. $app->post(/admin/clear-cache, function() use ($app) { $log = $app->getLog(); Get the log from $app $cleared = null; $clear = $app->request()->post(clear); if ($clear == 1) { if (apc_clear_cache(user)) { $cleared = Cache was successfully cleared!; } else { $cleared = Cache was not cleared!; $log->error(Cache not cleared); Error! } } $app->flash(cleared, $cleared); $app->redirect(/admin); });
  70. 70. $app->post(/admin/clear-cache, function() use ($app) { $log = $app->getLog(); Get the log from $app $cleared = null; $clear = $app->request()->post(clear); if ($clear == 1) { if (apc_clear_cache(user)) { $cleared = Cache was successfully cleared!; } else { $cleared = Cache was not cleared!; $log->error(Cache not cleared); Error! } } $app->flash(cleared, $cleared); Flash message available in $app->redirect(/admin); the next request. });
  71. 71. Middleware“. . . a Slim application can have middlewarethat may inspect, analyze, or modifythe application environment, request, andresponse before and/or after the Slimapplication is invoked.” http://docs.slimframework.com/pages/middleware-overview/
  72. 72. Hooks
  73. 73. Hooksslim.before
  74. 74. Hooksslim.beforeslim.before.router
  75. 75. Hooksslim.beforeslim.before.routerslim.before.dispatch
  76. 76. Hooksslim.before slim.after.dispatchslim.before.routerslim.before.dispatch
  77. 77. Hooksslim.before slim.after.dispatchslim.before.router slim.after.routerslim.before.dispatch
  78. 78. Hooksslim.before slim.after.dispatchslim.before.router slim.after.routerslim.before.dispatch slim.after
  79. 79. Hooksslim.before slim.after.dispatchslim.before.router slim.after.routerslim.before.dispatch slim.after
  80. 80. class MyMiddleware extends SlimMiddleware{ public function call() { //The Slim application $app = $this->app; //The Environment object $env = $app->environment(); //The Request object $req = $app->request(); //The Response object $res = $app->response(); //Optionally call the next middleware $this->next->call(); }}
  81. 81. class MyMiddleware extends SlimMiddleware Extend this{ public function call() { //The Slim application $app = $this->app; //The Environment object $env = $app->environment(); //The Request object $req = $app->request(); //The Response object $res = $app->response(); //Optionally call the next middleware $this->next->call(); }}
  82. 82. class MyMiddleware extends SlimMiddleware Extend this{ public function call() { Define call() //The Slim application $app = $this->app; //The Environment object $env = $app->environment(); //The Request object $req = $app->request(); //The Response object $res = $app->response(); //Optionally call the next middleware $this->next->call(); }}
  83. 83. class MyMiddleware extends SlimMiddleware Extend this{ public function call() { Define call() //The Slim application $app = $this->app; //The Environment object $env = $app->environment(); Inspect, analyze, and modify! //The Request object $req = $app->request(); //The Response object $res = $app->response(); //Optionally call the next middleware $this->next->call(); }}
  84. 84. class MyMiddleware extends SlimMiddleware Extend this{ public function call() { Define call() //The Slim application $app = $this->app; //The Environment object $env = $app->environment(); Inspect, analyze, and modify! //The Request object $req = $app->request(); //The Response object $res = $app->response(); //Optionally call the next middleware $this->next->call(); On to the next! }}
  85. 85. Middleware + Hooks = WIN
  86. 86. Navigation example
  87. 87. namespace TsfMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware{ /** * @var ZendAuthenticationAuthenticationService */ private $auth; public function __construct(AuthenticationService $auth) { $this->auth = $auth; } public function call() { // . . . }}
  88. 88. namespace TsfMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware extends{ /** * @var ZendAuthenticationAuthenticationService */ private $auth; public function __construct(AuthenticationService $auth) { $this->auth = $auth; } public function call() { // . . . }}
  89. 89. namespace TsfMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware extends{ /** * @var ZendAuthenticationAuthenticationService */ private $auth; public function __construct(AuthenticationService $auth) { $this->auth = $auth; } Constructor injection public function call() FTW { // . . . }}
  90. 90. public function call(){ $app = $this->app; $auth = $this->auth; $req = $app->request(); $home = array(caption => Home, href => /); $admin = array(caption => Admin, href => /admin); $login = array(caption => Login, href => /login); $logout = array(caption => Logout, href => /logout); if ($auth->hasIdentity()) { $navigation = array($home, $admin, $logout); } else { $navigation = array($home, $login); } // . . .}
  91. 91. public function call(){ $app = $this->app; Arrays of $auth = $this->auth; nav items $req = $app->request(); $home = array(caption => Home, href => /); $admin = array(caption => Admin, href => /admin); $login = array(caption => Login, href => /login); $logout = array(caption => Logout, href => /logout); if ($auth->hasIdentity()) { $navigation = array($home, $admin, $logout); } else { $navigation = array($home, $login); } // . . .}
  92. 92. public function call(){ $app = $this->app; Arrays of $auth = $this->auth; nav items $req = $app->request(); $home = array(caption => Home, href => /); $admin = array(caption => Admin, href => /admin); $login = array(caption => Login, href => /login); $logout = array(caption => Logout, href => /logout); if ($auth->hasIdentity()) { $navigation = array($home, $admin, $logout); } else { $navigation = array($home, $login); } Nav differs based // . . . on auth status}
  93. 93. public function call(){ // . . . $this->app->hook(slim.before.router, function () use (...) { foreach ($navigation as &$link) { if ($link[href] == $req->getPath()) { $link[class] = active; } else { $link[class] = ; } } $app->view() ->appendData(array(navigation => $navigation)); } ); $this->next->call();}
  94. 94. public function call(){ Delicious hook // . . . goodness $this->app->hook(slim.before.router, function () use (...) { foreach ($navigation as &$link) { if ($link[href] == $req->getPath()) { $link[class] = active; } else { $link[class] = ; } } $app->view() ->appendData(array(navigation => $navigation)); } ); $this->next->call();}
  95. 95. public function call(){ Delicious hook // . . . goodness $this->app->hook(slim.before.router, function () use (...) { foreach ($navigation as &$link) { if ($link[href] == $req->getPath()) { $link[class] = active; } else { $link[class] = ; } Match } dispatched path $app->view() ->appendData(array(navigation => $navigation)); } ); $this->next->call();}
  96. 96. public function call(){ Delicious hook // . . . goodness $this->app->hook(slim.before.router, function () use (...) { foreach ($navigation as &$link) { if ($link[href] == $req->getPath()) { $link[class] = active; } else { $link[class] = ; } Match } dispatched path $app->view() ->appendData(array(navigation => $navigation)); } ); Append $navigation to $this->next->call();} view
  97. 97. public function call(){ Delicious hook // . . . goodness $this->app->hook(slim.before.router, function () use (...) { foreach ($navigation as &$link) { if ($link[href] == $req->getPath()) { $link[class] = active; } else { $link[class] = ; } Match } dispatched path $app->view() ->appendData(array(navigation => $navigation)); } ); Append $navigation to $this->next->call(); On to the next!} view
  98. 98. Views
  99. 99. Two great tastesthat taste great together
  100. 100. Twig
  101. 101. TwigConcise
  102. 102. TwigConciseTemplate oriented
  103. 103. TwigConciseTemplate orientedFast
  104. 104. TwigConcise Multiple inheritanceTemplate orientedFast
  105. 105. TwigConcise Multiple inheritanceTemplate oriented BlocksFast
  106. 106. TwigConcise Multiple inheritanceTemplate oriented BlocksFast Automatic escaping
  107. 107. layout.html andindex.html
  108. 108. layout.html
  109. 109. <title>{% block page_title %} {% endblock %}</title>
  110. 110. <ul class="nav"> {% for link in navigation %} <li class="{{link.class}}"> <a href="{{link.href}}">{{link.caption}}</a> </li> {% endfor %}</ul>
  111. 111. <h1>365 Days of Photography</h1><h3>Photographer: Jeremy Kendall</h3>{% block content %} {% endblock %}<hr />
  112. 112. index.html
  113. 113. {% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in images %}<div class="row"> <div class="span6"> <h2><a href="/{{image.day}}">{{image.day}}/365</a></h2> <p> <a href="/{{image.day}}"> <img src="{{image.sizes.size.5.source}}" /> </a> </p> <p>Posted {{image.posted|date("m/d/Y")}}</p> </div></div>{% else %}<p>No images in project</p>{% endfor %}{% endblock %}
  114. 114. {% extends layout.html %} extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in images %}<div class="row"> <div class="span6"> <h2><a href="/{{image.day}}">{{image.day}}/365</a></h2> <p> <a href="/{{image.day}}"> <img src="{{image.sizes.size.5.source}}" /> </a> </p> <p>Posted {{image.posted|date("m/d/Y")}}</p> </div></div>{% else %}<p>No images in project</p>{% endfor %}{% endblock %}
  115. 115. {% extends layout.html %} extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %} <title />{% for image in images %}<div class="row"> <div class="span6"> <h2><a href="/{{image.day}}">{{image.day}}/365</a></h2> <p> <a href="/{{image.day}}"> <img src="{{image.sizes.size.5.source}}" /> </a> </p> <p>Posted {{image.posted|date("m/d/Y")}}</p> </div></div>{% else %}<p>No images in project</p>{% endfor %}{% endblock %}
  116. 116. {% extends layout.html %} extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %} <title />{% for image in images %}<div class="row"> <div class="span6"> <h2><a href="/{{image.day}}">{{image.day}}/365</a></h2> <p> <a href="/{{image.day}}"> <img src="{{image.sizes.size.5.source}}" /> </a> </p> <p>Posted {{image.posted|date("m/d/Y")}}</p> </div></div>{% else %}<p>No images in project</p>{% endfor %}{% endblock %}
  117. 117. {% extends layout.html %} extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %} <title />{% for image in images %} iterator<div class="row"> <div class="span6"> <h2><a href="/{{image.day}}">{{image.day}}/365</a></h2> <p> <a href="/{{image.day}}"> <img src="{{image.sizes.size.5.source}}" /> </a> </p> <p>Posted {{image.posted|date("m/d/Y")}}</p> </div></div>{% else %}<p>No images in project</p>{% endfor %}{% endblock %}
  118. 118. {% extends layout.html %} extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %} <title />{% for image in images %} iterator<div class="row"> <div class="span6"> <h2><a href="/{{image.day}}">{{image.day}}/365</a></h2> <p> <a href="/{{image.day}}"> <img src="{{image.sizes.size.5.source}}" /> </a> </p> <p>Posted {{image.posted|date("m/d/Y")}}</p> </div></div> else{% else %}<p>No images in project</p>{% endfor %}{% endblock %}
  119. 119. {% extends layout.html %} extends{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %} <title />{% for image in images %} iterator<div class="row"> <div class="span6"> <h2><a href="/{{image.day}}">{{image.day}}/365</a></h2> <p> <a href="/{{image.day}}"> <img src="{{image.sizes.size.5.source}}" /> </a> </p> <p>Posted {{image.posted|date("m/d/Y")}}</p> </div></div> else{% else %}<p>No images in project</p> format{% endfor %}{% endblock %}
  120. 120. login.html
  121. 121. {% extends layout.html %}{% block page_title %}365.jeremykendall.net | Login{% endblock %}{% block content %}<div class="row"> <div class="span4"> <h2>Login</h2> {% if flash.error %} <p style="color: red;">{{flash.error}}</p> {% endif %} <form name="login" id="login" class="well" method="post"> // Login form . . . </form> </div></div>{% endblock %}
  122. 122. {% extends layout.html %}{% block page_title %}365.jeremykendall.net | Login{% endblock %}{% block content %}<div class="row"> <div class="span4"> <h2>Login</h2> {% if flash.error %} <p style="color: red;">{{flash.error}}</p> {% endif %} <form name="login" id="login" class="well" method="post"> // Login form . . . </form> </div></div>{% endblock %}
  123. 123. The other viewswould be redundant
  124. 124. GOTO 0
  125. 125. Small but powerful GOTO 0
  126. 126. Small but powerful GOTO 0Excellent tools to write elegant code
  127. 127. Small but powerful GOTO 0Excellent tools to write elegant codeRouting, middleware & hooks, views
  128. 128. Small but powerful GOTO 0Excellent tools to write elegant codeRouting, middleware & hooks, viewsI just scratched the surface
  129. 129. ReadSlim: slimframework.comTwig: twig.sensiolabs.orgComposer: getcomposer.orgMicroPHP Manifesto: microphp.orgFlaming Archer: http://git.io/rH0nrg
  130. 130. Questions?
  131. 131. Thanks!jeremy@jeremykendall.net @jeremykendall
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×