Your SlideShare is downloading. ×
0
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Keeping It Small with Slim
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Keeping It Small with Slim

534

Published on

Raven developer Jeremy Kendall discusses PHP's Slim micro framework, with code examples from a photography website he built to learn it, also using Twig templating and Composer dependency management.

Raven developer Jeremy Kendall discusses PHP's Slim micro framework, with code examples from a photography website he built to learn it, also using Twig templating and Composer dependency management.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
534
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
27
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • WTF?\n
  • Blame it on github and their repo name suggetsions\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Four views\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Can be anything that returns true for is_callable()\n\n
  • Can be anything that returns true for is_callable()\n\n
  • Can be anything that returns true for is_callable()\n\n
  • Can be anything that returns true for is_callable()\n\n
  • Can be anything that returns true for is_callable()\n\n
  • Can be anything that returns true for is_callable()\n\n
  • Can be anything that returns true for is_callable()\n\n
  • Can be anything that returns true for is_callable()\n\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • GET, including route parameters and conditions\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • slim.before.router: after output buffering is turned on and before the router is dispatched. Once.\n\n
  • slim.before.router: after output buffering is turned on and before the router is dispatched. Once.\n\n
  • slim.before.router: after output buffering is turned on and before the router is dispatched. Once.\n\n
  • slim.before.router: after output buffering is turned on and before the router is dispatched. Once.\n\n
  • slim.before.router: after output buffering is turned on and before the router is dispatched. Once.\n\n
  • slim.before.router: after output buffering is turned on and before the router is dispatched. Once.\n\n
  • slim.before.router: after output buffering is turned on and before the router is dispatched. Once.\n\n
  • Has access to app, environment, request & response object\n
  • Has access to app, environment, request & response object\n
  • Has access to app, environment, request & response object\n
  • Has access to app, environment, request & response object\n
  • Has access to app, environment, request & response object\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • I won’t cover bootstrap, but it kicks ass\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Too much boilerplate to show off, but here come the important parts\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

    • 1. Keeping it smallGetting to know the Slim micro framework kendall@raventools.com
    • 2. Jeremy Kendallraventools.com
    • 3. Jeremy Kendall I love to coderaventools.com
    • 4. Jeremy Kendall I love to code I’m terribly forgetfulraventools.com
    • 5. Jeremy Kendall I love to code I’m terribly forgetful I take picturesraventools.com
    • 6. Jeremy Kendall I love to code I’m terribly forgetful I take picturesraventools.com I work at Raven
    • 7. Micro framework?
    • 8. Micro framework?Concise codebase
    • 9. Micro framework?Concise codebaseClear codebase
    • 10. Micro framework?Concise codebaseClear codebaseAddresses a small set of use cases
    • 11. Micro framework?Concise codebaseClear codebaseAddresses a small set of use casesAddresses those use cases well
    • 12. What is Slim?
    • 13. What is Slim?Inspired by Sinatra
    • 14. What is Slim?Inspired by SinatraFavors cleanliness over terseness
    • 15. What is Slim?Inspired by SinatraFavors cleanliness over tersenessFavors common cases over edge cases
    • 16. Installing Slim
    • 17. RTFM
    • 18. RTFM ;-)
    • 19. Don’t forget .htaccess!RewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^ index.php [QSA,L]http://docs.slimframework.com/pages/routing-url-rewriting/
    • 20. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
    • 21. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
    • 22. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
    • 23. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
    • 24. Hello world<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) { echo "Hello, $name";});$app->run();
    • 25. Let’s look at aSlim application
    • 26. Flaming Archer
    • 27. Flaming Archer wat
    • 28. “Great repository names are short and memorable. Need inspiration? How about flaming-archer.”
    • 29. Flaming Archer
    • 30. Flaming ArcherPhoto 365 project
    • 31. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)
    • 32. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles
    • 33. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles Routing
    • 34. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles Routing Twig views
    • 35. Flaming ArcherPhoto 365 projectBuilt in 4 days (Saturday through Tuesday)Basic application — a few bells, no whistles Routing Twig views Middleware
    • 36. 4 views
    • 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. Configuration
    • 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. 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. 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. 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. 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. $config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);
    • 45. $config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]); Config array goes here
    • 46. Routing
    • 47. Routing$app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); });
    • 48. RoutingHTTP Method $app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); } );
    • 49. Routing Resource URIHTTP Method $app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); } );
    • 50. Routing Resource URIHTTP Method Anonymous Function $app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); } );
    • 51. Routing$app->get(/, function () use ($app, $service) { $images = $service->findAll(); $app->render(index.html, array(images => $images)); });
    • 52. Routing$app->get(/, function () use ($app, $service) { Grabs all the pics $images = $service->findAll(); $app->render(index.html, array(images => $images)); });
    • 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. 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. 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. 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. 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. 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. 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. POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) { $data = $app->request()->post(); $service->save($data); $app->redirect(/admin); });
    • 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. 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. Multiple methods$app->map(/login, function() { // Login })->via(GET, POST);
    • 64. Multiple methods Not an HTTP Method$app->map(/login, function() { // Login })->via(GET, POST);
    • 65. Multiple methods Not an HTTP Method$app->map(/login, function() { // Login })->via(GET, POST); via() is the awesome sauce
    • 66. Logging and flash messaging
    • 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. $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. $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. $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. Middleware“The purpose of middleware is to inspect,analyze, or modify the applicationenvironment, request, and response beforeand/or after the Slim application isinvoked.” http://docs.slimframework.com/pages/middleware-overview/
    • 72. Hooks
    • 73. Hooksslim.before
    • 74. Hooksslim.beforeslim.before.router
    • 75. Hooksslim.beforeslim.before.routerslim.before.dispatch
    • 76. Hooksslim.before slim.after.dispatchslim.before.routerslim.before.dispatch
    • 77. Hooksslim.before slim.after.dispatchslim.before.router slim.after.routerslim.before.dispatch
    • 78. Hooksslim.before slim.after.dispatchslim.before.router slim.after.routerslim.before.dispatch slim.after
    • 79. Hooksslim.before slim.after.dispatchslim.before.router slim.after.routerslim.before.dispatch slim.after
    • 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. 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. 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. 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. 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. Middleware + Hooks = WIN
    • 86. Navigation example
    • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Views
    • 99. Two great tastesthat taste great together
    • 100. Twig
    • 101. TwigConcise
    • 102. TwigConciseTemplate oriented
    • 103. TwigConciseTemplate orientedFast
    • 104. TwigConcise Multiple inheritanceTemplate orientedFast
    • 105. TwigConcise Multiple inheritanceTemplate oriented BlocksFast
    • 106. TwigConcise Multiple inheritanceTemplate oriented BlocksFast Automatic escaping
    • 107. layout.html andindex.html
    • 108. layout.html
    • 109. <title>{% block page_title %} {% endblock %}</title>
    • 110. <ul class="nav"> {% for link in navigation %} <li class="{{link.class}}"> <a href="{{link.href}}">{{link.caption}}</a> </li> {% endfor %}</ul>
    • 111. <h1>365 Days of Photography</h1><h3>Photographer: Jeremy Kendall</h3>{% block content %} {% endblock %}<hr />
    • 112. index.html
    • 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. {% 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. {% 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. {% 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. {% 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. {% 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. {% 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. login.html
    • 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. {% 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. The other viewswould be redundant
    • 124. GOTO 0
    • 125. Small but powerful GOTO 0
    • 126. Small but powerful GOTO 0Excellent tools to write elegant code
    • 127. Small but powerful GOTO 0Excellent tools to write elegant codeRouting, middleware & hooks, views
    • 128. Small but powerful GOTO 0Excellent tools to write elegant codeRouting, middleware & hooks, viewsI just scratched the surface
    • 129. ReadSlim: slimframework.comTwig: twig.sensiolabs.orgComposer: getcomposer.orgMicroPHP Manifesto: microphp.orgFlaming Archer: http://git.io/rH0nrg
    • 130. Questions?
    • 131. Thanks!kendall@raventools.com

    ×