Keeping it smallGetting to know the Slim micro frameworkphp[tek] 2013Wednesday, May 15, 13
Wednesday, May 15, 13
I love to codeWednesday, May 15, 13
I love to codeI’m terribly forgetfulWednesday, May 15, 13
I love to codeI’m terribly forgetfulI take picturesWednesday, May 15, 13
I love to codeI’m terribly forgetfulI take picturesI work at OpenSkyWednesday, May 15, 13
Micro framework?Wednesday, May 15, 13
MicroPHP ManifestoWednesday, May 15, 13
MicroPHP ManifestoWritten by Ed FinklerWednesday, May 15, 13
MicroPHP ManifestoWritten by Ed FinklerPunk rock vs. Prog rockWednesday, May 15, 13
MicroPHP ManifestoWritten by Ed FinklerPunk rock vs. Prog rockProphet or Madman?Wednesday, May 15, 13
MicroPHP ManifestoWritten by Ed FinklerPunk rock vs. Prog rockProphet or Madman?Guiding principleWednesday, May 15, 13
MicroPHP ManifestoWritten by Ed FinklerPunk rock vs. Prog rockProphet or Madman?Guiding principlehttp://microphp.org/Wedne...
Micro framework?Wednesday, May 15, 13
Micro framework?Concise codebaseWednesday, May 15, 13
Micro framework?Concise codebaseClear codebaseWednesday, May 15, 13
Micro framework?Concise codebaseClear codebaseAddresses a small set of use casesWednesday, May 15, 13
Micro framework?Concise codebaseClear codebaseAddresses a small set of use casesAddresses those use cases wellWednesday, M...
I chose Slim PHPWednesday, May 15, 13
I chose Slim PHPand I sucked at itWednesday, May 15, 13
What is Slim?Wednesday, May 15, 13
What is Slim?Inspired by SinatraWednesday, May 15, 13
What is Slim?Inspired by SinatraFavors cleanliness over tersenessWednesday, May 15, 13
What is Slim?Inspired by SinatraFavors cleanliness over tersenessFavors common cases over edge casesWednesday, May 15, 13
Installing SlimWednesday, May 15, 13
Install Composercurl -s https://getcomposer.org/installer | phpWednesday, May 15, 13
Install Composercurl -s https://getcomposer.org/installer | phpIf you take nothing else away from this talk, I hope thatit...
composer.json{"require": {"slim/slim": "2.*"}}Wednesday, May 15, 13
Install via Composerphp composer.phar installWednesday, May 15, 13
Add this to index.php<?phprequire vendor/autoload.php;Wednesday, May 15, 13
Pro tipmv composer.phar /usr/local/bin/composerWednesday, May 15, 13
Don’t forget .htaccess!RewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^ index.php [QSA,L]http://docs.slimf...
Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello...
Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello...
Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello...
Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello...
Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello...
Getting therehttp://localhost/index.php/hello/tekORhttp://localhost/hello/tekWednesday, May 15, 13
Slim in practiceWednesday, May 15, 13
Flaming Archer!Wednesday, May 15, 13
“Great repository names are short and memorable.Need inspiration? How about flaming-archer.”Wednesday, May 15, 13
Flaming ArcherWednesday, May 15, 13
Flaming ArcherPhoto 365 projectWednesday, May 15, 13
Flaming ArcherPhoto 365 projectBulk of app built in 4 daysWednesday, May 15, 13
Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesWednesday, May 15, 13
Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingWednesday, Ma...
Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig template...
Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig template...
Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig template...
4 viewsWednesday, May 15, 13
Wednesday, May 15, 13
Wednesday, May 15, 13
Wednesday, May 15, 13
Wednesday, May 15, 13
phploc --exclude vendor --exclude tests --exclude templates .phploc 1.7.4 by Sebastian Bergmann.Directories: 8Files: 16Lin...
ConfigurationWednesday, May 15, 13
return array(slim => array(templates.path => __DIR__ . /templates,log.level => 4,log.enabled => true,log.writer => new Sli...
return array(slim => array(templates.path => __DIR__ . /templates,log.level => 4,log.enabled => true,log.writer => new Sli...
return array(slim => array(templates.path => __DIR__ . /templates,log.level => 4,log.enabled => true,log.writer => new Sli...
return array(slim => array(templates.path => __DIR__ . /templates,log.level => 4,log.enabled => true,log.writer => new Sli...
return array(slim => array(templates.path => __DIR__ . /templates,log.level => 4,log.enabled => true,log.writer => new Sli...
$config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);ConfigurationWednesday, Ma...
$config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);Config arraygoes hereConfig...
RoutingWednesday, May 15, 13
Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images ...
Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images ...
Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images ...
Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images ...
Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images ...
Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images ...
Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images ...
GET$app->get(/:day, function($day) use ($app, $service) {$image = $service->find($day);if (!$image) {$app->notFound();}$ap...
GET$app->get(/:day, function($day) use ($app, $service) {$image = $service->find($day);if (!$image) {$app->notFound();}$ap...
GET$app->get(/:day, function($day) use ($app, $service) {$image = $service->find($day);if (!$image) {$app->notFound();}$ap...
GET$app->get(/:day, function($day) use ($app, $service) {$image = $service->find($day);if (!$image) {$app->notFound();}$ap...
GET$app->get(/:day, function($day) use ($app, $service) {$image = $service->find($day);if (!$image) {$app->notFound();}$ap...
GET$app->get(/:day, function($day) use ($app, $service) {$image = $service->find($day);if (!$image) {$app->notFound();}$ap...
POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) {$data = $app->request()->post();$service...
POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) {$data = $app->request()->post();$service...
POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) {$data = $app->request()->post();$service...
Multiple methods$app->map(/login, function() {// Login})->via(GET, POST);Wednesday, May 15, 13
Multiple methods$app->map(/login, function() {// Login})->via(GET, POST);Not an HTTP MethodWednesday, May 15, 13
Multiple methods$app->map(/login, function() {// Login})->via(GET, POST);Not an HTTP Methodvia() is theawesome sauceWednes...
Logging and flash messagingWednesday, May 15, 13
$app->post(/admin/clear-cache, function() use ($app) {$log = $app->getLog();$cleared = null;$clear = $app->request()->post...
$app->post(/admin/clear-cache, function() use ($app) {$log = $app->getLog();$cleared = null;$clear = $app->request()->post...
$app->post(/admin/clear-cache, function() use ($app) {$log = $app->getLog();$cleared = null;$clear = $app->request()->post...
$app->post(/admin/clear-cache, function() use ($app) {$log = $app->getLog();$cleared = null;$clear = $app->request()->post...
Middleware“. . . a Slim application can have middlewarethat may inspect, analyze, or modifythe application environment, re...
MiddlewareWednesday, May 15, 13
MiddlewareLike layers of an onionWednesday, May 15, 13
MiddlewareLike layers of an onionThe Slim application is the core of the onionWednesday, May 15, 13
MiddlewareLike layers of an onionThe Slim application is the core of the onionEach new middleware wraps any existing middl...
MiddlewareLike layers of an onionThe Slim application is the core of the onionEach new middleware wraps any existing middl...
MiddlewareLike layers of an onionThe Slim application is the core of the onionEach new middleware wraps any existing middl...
MiddlewareLike layers of an onionThe Slim application is the core of the onionEach new middleware wraps any existing middl...
Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authenti...
Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authenti...
Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authenti...
Existing MiddlewareWednesday, May 15, 13
Existing MiddlewareFlash messagingWednesday, May 15, 13
Existing MiddlewareFlash messagingContent typesWednesday, May 15, 13
Existing MiddlewareFlash messagingContent typesPretty exceptionsWednesday, May 15, 13
Existing MiddlewareFlash messagingContent typesPretty exceptionsSession cookieWednesday, May 15, 13
Existing MiddlewareFlash messagingContent typesPretty exceptionsSession cookieMore in Slim ExtrasWednesday, May 15, 13
Roll your own MiddlewareWednesday, May 15, 13
Roll your own MiddlewareSuper easyWednesday, May 15, 13
Roll your own MiddlewareSuper easyDRYs up codeWednesday, May 15, 13
Roll your own MiddlewareSuper easyDRYs up codeAwesome application wide functionalityWednesday, May 15, 13
Roll your own MiddlewareSuper easyDRYs up codeAwesome application wide functionalityJust extend SlimMiddleware and impleme...
class MyMiddleware extends SlimMiddleware{public function call(){//The Slim application$app = $this->app;//The Environment...
class MyMiddleware extends SlimMiddleware{public function call(){//The Slim application$app = $this->app;//The Environment...
class MyMiddleware extends SlimMiddleware{public function call(){//The Slim application$app = $this->app;//The Environment...
class MyMiddleware extends SlimMiddleware{public function call(){//The Slim application$app = $this->app;//The Environment...
class MyMiddleware extends SlimMiddleware{public function call(){//The Slim application$app = $this->app;//The Environment...
Navigation exampleWednesday, May 15, 13
namespace FaMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware{/** @var Authen...
namespace FaMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware{/** @var Authen...
namespace FaMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware{/** @var Authen...
public function call(){$app = $this->app;$auth = $this->auth;$req = $app->request();$home = array(caption => Home, href =>...
public function call(){$app = $this->app;$auth = $this->auth;$req = $app->request();$home = array(caption => Home, href =>...
public function call(){$app = $this->app;$auth = $this->auth;$req = $app->request();$home = array(caption => Home, href =>...
public function call(){// . . .foreach ($navigation as &$link) {if ($link[href] == $req->getPath()) {$link[class] = active...
public function call(){// . . .foreach ($navigation as &$link) {if ($link[href] == $req->getPath()) {$link[class] = active...
public function call(){// . . .foreach ($navigation as &$link) {if ($link[href] == $req->getPath()) {$link[class] = active...
public function call(){// . . .foreach ($navigation as &$link) {if ($link[href] == $req->getPath()) {$link[class] = active...
Route MiddlewareWednesday, May 15, 13
Route MiddlewareAnything that returns true for is_callable()Wednesday, May 15, 13
Route MiddlewareAnything that returns true for is_callable()Apply directly to route!Wednesday, May 15, 13
Route MiddlewareAnything that returns true for is_callable()Apply directly to route!Goes between route definition and route...
Route Middleware<?phpfunction mw1() {echo "This is middleware!";}function mw2() {echo "This is middleware!";}$app = new Sl...
Route Middleware<?phpfunction mw1() {echo "This is middleware!";}function mw2() {echo "This is middleware!";}$app = new Sl...
HooksA “hook” is a moment in the Slim application lifecycleat which a priority list of callables assigned to thehook will ...
HooksWednesday, May 15, 13
HooksAnything that returns true for is_callable()Wednesday, May 15, 13
HooksAnything that returns true for is_callable()PrioritizedWednesday, May 15, 13
HooksAnything that returns true for is_callable()PrioritizedSix default hooksWednesday, May 15, 13
HooksWednesday, May 15, 13
slim.beforeHooksWednesday, May 15, 13
slim.beforeslim.before.routerHooksWednesday, May 15, 13
slim.beforeslim.before.routerslim.before.dispatchHooksWednesday, May 15, 13
slim.beforeslim.before.routerslim.before.dispatchslim.after.dispatchHooksWednesday, May 15, 13
slim.beforeslim.before.routerslim.before.dispatchslim.after.dispatchslim.after.routerHooksWednesday, May 15, 13
slim.beforeslim.before.routerslim.before.dispatchslim.after.dispatchslim.after.routerslim.afterHooksWednesday, May 15, 13
slim.beforeslim.before.routerslim.before.dispatchslim.after.dispatchslim.after.routerslim.afterHooksWednesday, May 15, 13
Hooks$app = new SlimSlim();$app->hook(the.hook.name, function () {//Do something}, 5);Wednesday, May 15, 13
Hooks$app = new SlimSlim();$app->hook(the.hook.name, function () {//Do something}, 5);Optional PriorityWednesday, May 15, 13
Middleware + Hooks = WINWednesday, May 15, 13
Middleware + HooksUsing middleware to register hooks allowsme to inspect, analyze, or modify myapplication at a specific ti...
Authentication ExampleWednesday, May 15, 13
public function call(){$app = $this->app;$req = $app->request();$auth = $this->auth;$config = $this->config;// $checkAuth ...
public function call(){$app = $this->app;$req = $app->request();$auth = $this->auth;$config = $this->config;// $checkAuth ...
public function call(){$app = $this->app;$req = $app->request();$auth = $this->auth;$config = $this->config;// $checkAuth ...
public function call(){$app = $this->app;$req = $app->request();$auth = $this->auth;$config = $this->config;// $checkAuth ...
// Snip looping through secured url arrayif (preg_match($urlPattern, $req->getPathInfo())&& !$auth->hasIdentity()) {if ($r...
// Snip looping through secured url arrayif (preg_match($urlPattern, $req->getPathInfo())&& !$auth->hasIdentity()) {if ($r...
// Snip looping through secured url arrayif (preg_match($urlPattern, $req->getPathInfo())&& !$auth->hasIdentity()) {if ($r...
// Snip looping through secured url arrayif (preg_match($urlPattern, $req->getPathInfo())&& !$auth->hasIdentity()) {if ($r...
ViewsWednesday, May 15, 13
SlimViewWednesday, May 15, 13
SlimViewSlim delegates rendering of templates to its view object.Wednesday, May 15, 13
SlimViewSlim delegates rendering of templates to its view object.Easily extensible by extending theView class andreturning...
SlimViewSlim delegates rendering of templates to its view object.Easily extensible by extending theView class andreturning...
SlimViewSlim delegates rendering of templates to its view object.Easily extensible by extending theView class andreturning...
Rendering an app view$app->render(hello.html,array( name => Josh ),200);Wednesday, May 15, 13
Rendering an app view$app->render(hello.html,array( name => Josh ),200);TemplateWednesday, May 15, 13
Rendering an app view$app->render(hello.html,array( name => Josh ),200);Template View data(optional)Wednesday, May 15, 13
Rendering an app view$app->render(hello.html,array( name => Josh ),200);Template View data(optional)HTTP Response(optional...
TemplatesWednesday, May 15, 13
Two great tastesthat taste great togetherWednesday, May 15, 13
TwigWednesday, May 15, 13
TwigConciseWednesday, May 15, 13
TwigConciseTemplate orientedWednesday, May 15, 13
TwigConciseTemplate orientedFastWednesday, May 15, 13
TwigConciseTemplate orientedFastMultiple inheritanceWednesday, May 15, 13
TwigConciseTemplate orientedFastMultiple inheritanceContent blocksWednesday, May 15, 13
TwigConciseTemplate orientedFastMultiple inheritanceContent blocksAutomatic escapingWednesday, May 15, 13
BootstrapBecause I majorly suck at designWednesday, May 15, 13
CaveatI chose Twig because I wanted to learn Twig,but you could choose any or more of thefollowing:PHP, Mustache, Haml, Ha...
layout.htmlandindex.htmlWednesday, May 15, 13
layout.htmlandindex.htmlWednesday, May 15, 13
layout.htmlandindex.htmlWednesday, May 15, 13
layout.htmlWednesday, May 15, 13
<title>{% block page_title %} {% endblock %}</title>layout.html: titleWednesday, May 15, 13
<ul class="nav">{% for link in navigation %}<li class="{{link.class}}"><a href="{{link.href}}">{{link.caption}}</a></li>{%...
<h1>365 Days of Photography</h1><h3>Photographer: Jeremy Kendall</h3>{% block content %} {% endblock %}<hr />layout.html:h...
index.html(extends layout.html)Wednesday, May 15, 13
{% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in image...
{% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in image...
{% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in image...
{% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in image...
{% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in image...
{% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in image...
{% extends layout.html %}{% block page_title %}365.jeremykendall.net{% endblock %}{% block content %}{% for image in image...
login.htmlWednesday, May 15, 13
{% 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 templatesare just more of the sameWednesday, May 15, 13
Application CodeAnother big hurdle I had with Slim wasfiguring out how to organize my applicationcode.Wednesday, May 15, 13
Thin Controller, Fat ModelWednesday, May 15, 13
Thin Controller, Fat ModelDuh!Wednesday, May 15, 13
Thin Controller, Fat ModelDuh!All my application code is in a library directoryWednesday, May 15, 13
Thin Controller, Fat ModelDuh!All my application code is in a library directoryIt’s all namespaced, autoloadable, and test...
Thin Controller, Fat ModelDuh!All my application code is in a library directoryIt’s all namespaced, autoloadable, and test...
Thin Controller, Fat ModelDuh!All my application code is in a library directoryIt’s all namespaced, autoloadable, and test...
Thin Controller, Fat ModelDuh!All my application code is in a library directoryIt’s all namespaced, autoloadable, and test...
GOTO 0Wednesday, May 15, 13
Small but powerful GOTO 0Wednesday, May 15, 13
Small but powerfulExcellent tools to write elegant codeGOTO 0Wednesday, May 15, 13
Small but powerfulExcellent tools to write elegant codeRouting, middleware, hooks, templates, andviewsGOTO 0Wednesday, May...
Small but powerfulExcellent tools to write elegant codeRouting, middleware, hooks, templates, andviewsI just scratched the...
ReadSlim: slimframework.comTwig: twig.sensiolabs.orgComposer: getcomposer.orgMicroPHP Manifesto: microphp.orgFlaming Arche...
Questions?Wednesday, May 15, 13
Thanks!jeremy@jeremykendall.net@jeremykendallhttp://joind.in/8175Wednesday, May 15, 13
Upcoming SlideShare
Loading in...5
×

Keeping it small - Getting to know the Slim PHP micro framework

5,852

Published on

Learn what the big deal is about PHP micro frameworks by taking a tour through an application written in Slim PHP. I'll briefly introduce you to some high level concepts, show how those concepts can be implemented in Slim, and see how powerful and elegant micro framework can be.

0 Comments
16 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,852
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
223
Comments
0
Likes
16
Embeds 0
No embeds

No notes for slide

Keeping it small - Getting to know the Slim PHP micro framework

  1. 1. Keeping it smallGetting to know the Slim micro frameworkphp[tek] 2013Wednesday, May 15, 13
  2. 2. Wednesday, May 15, 13
  3. 3. I love to codeWednesday, May 15, 13
  4. 4. I love to codeI’m terribly forgetfulWednesday, May 15, 13
  5. 5. I love to codeI’m terribly forgetfulI take picturesWednesday, May 15, 13
  6. 6. I love to codeI’m terribly forgetfulI take picturesI work at OpenSkyWednesday, May 15, 13
  7. 7. Micro framework?Wednesday, May 15, 13
  8. 8. MicroPHP ManifestoWednesday, May 15, 13
  9. 9. MicroPHP ManifestoWritten by Ed FinklerWednesday, May 15, 13
  10. 10. MicroPHP ManifestoWritten by Ed FinklerPunk rock vs. Prog rockWednesday, May 15, 13
  11. 11. MicroPHP ManifestoWritten by Ed FinklerPunk rock vs. Prog rockProphet or Madman?Wednesday, May 15, 13
  12. 12. MicroPHP ManifestoWritten by Ed FinklerPunk rock vs. Prog rockProphet or Madman?Guiding principleWednesday, May 15, 13
  13. 13. MicroPHP ManifestoWritten by Ed FinklerPunk rock vs. Prog rockProphet or Madman?Guiding principlehttp://microphp.org/Wednesday, May 15, 13
  14. 14. Micro framework?Wednesday, May 15, 13
  15. 15. Micro framework?Concise codebaseWednesday, May 15, 13
  16. 16. Micro framework?Concise codebaseClear codebaseWednesday, May 15, 13
  17. 17. Micro framework?Concise codebaseClear codebaseAddresses a small set of use casesWednesday, May 15, 13
  18. 18. Micro framework?Concise codebaseClear codebaseAddresses a small set of use casesAddresses those use cases wellWednesday, May 15, 13
  19. 19. I chose Slim PHPWednesday, May 15, 13
  20. 20. I chose Slim PHPand I sucked at itWednesday, May 15, 13
  21. 21. What is Slim?Wednesday, May 15, 13
  22. 22. What is Slim?Inspired by SinatraWednesday, May 15, 13
  23. 23. What is Slim?Inspired by SinatraFavors cleanliness over tersenessWednesday, May 15, 13
  24. 24. What is Slim?Inspired by SinatraFavors cleanliness over tersenessFavors common cases over edge casesWednesday, May 15, 13
  25. 25. Installing SlimWednesday, May 15, 13
  26. 26. Install Composercurl -s https://getcomposer.org/installer | phpWednesday, May 15, 13
  27. 27. Install Composercurl -s https://getcomposer.org/installer | phpIf you take nothing else away from this talk, I hope thatit’s Composer. It’s that big of a deal.Wednesday, May 15, 13
  28. 28. composer.json{"require": {"slim/slim": "2.*"}}Wednesday, May 15, 13
  29. 29. Install via Composerphp composer.phar installWednesday, May 15, 13
  30. 30. Add this to index.php<?phprequire vendor/autoload.php;Wednesday, May 15, 13
  31. 31. Pro tipmv composer.phar /usr/local/bin/composerWednesday, May 15, 13
  32. 32. Don’t forget .htaccess!RewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^ index.php [QSA,L]http://docs.slimframework.com/#Route-URL-Rewriting(nginx documentation available at same URL)Wednesday, May 15, 13
  33. 33. Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  34. 34. Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  35. 35. Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  36. 36. Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  37. 37. Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  38. 38. Getting therehttp://localhost/index.php/hello/tekORhttp://localhost/hello/tekWednesday, May 15, 13
  39. 39. Slim in practiceWednesday, May 15, 13
  40. 40. Flaming Archer!Wednesday, May 15, 13
  41. 41. “Great repository names are short and memorable.Need inspiration? How about flaming-archer.”Wednesday, May 15, 13
  42. 42. Flaming ArcherWednesday, May 15, 13
  43. 43. Flaming ArcherPhoto 365 projectWednesday, May 15, 13
  44. 44. Flaming ArcherPhoto 365 projectBulk of app built in 4 daysWednesday, May 15, 13
  45. 45. Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesWednesday, May 15, 13
  46. 46. Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingWednesday, May 15, 13
  47. 47. Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig templatesWednesday, May 15, 13
  48. 48. Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig templatesMiddlewareWednesday, May 15, 13
  49. 49. Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig templatesMiddlewareHooksWednesday, May 15, 13
  50. 50. 4 viewsWednesday, May 15, 13
  51. 51. Wednesday, May 15, 13
  52. 52. Wednesday, May 15, 13
  53. 53. Wednesday, May 15, 13
  54. 54. Wednesday, May 15, 13
  55. 55. phploc --exclude vendor --exclude tests --exclude templates .phploc 1.7.4 by Sebastian Bergmann.Directories: 8Files: 16Lines of Code (LOC): 1212Cyclomatic Complexity / Lines of Code: 0.03Comment Lines of Code (CLOC): 453Non-Comment Lines of Code (NCLOC): 759Wednesday, May 15, 13
  56. 56. ConfigurationWednesday, May 15, 13
  57. 57. 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(// . . .));Wednesday, May 15, 13
  58. 58. 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(// . . .));SlimWednesday, May 15, 13
  59. 59. 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(// . . .));SlimViewsWednesday, May 15, 13
  60. 60. 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(// . . .));SlimViewsCookiesWednesday, May 15, 13
  61. 61. 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(// . . .));SlimViewsCookiesApp specificWednesday, May 15, 13
  62. 62. $config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);ConfigurationWednesday, May 15, 13
  63. 63. $config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);Config arraygoes hereConfigurationWednesday, May 15, 13
  64. 64. RoutingWednesday, May 15, 13
  65. 65. Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});Wednesday, May 15, 13
  66. 66. Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});HTTP MethodWednesday, May 15, 13
  67. 67. Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});HTTP MethodResource URIWednesday, May 15, 13
  68. 68. Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});HTTP MethodResource URIAnonymous FunctionWednesday, May 15, 13
  69. 69. Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});Wednesday, May 15, 13
  70. 70. Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});Grabs all the picsWednesday, May 15, 13
  71. 71. Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});Grabs all the picsPasses array of image data to index.htmlWednesday, May 15, 13
  72. 72. 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])));Wednesday, May 15, 13
  73. 73. 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])));URL parameterWednesday, May 15, 13
  74. 74. 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])));URL parameter... gets passed as anargumentWednesday, May 15, 13
  75. 75. 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])));URL parameter... gets passed as anargumentConditionWednesday, May 15, 13
  76. 76. 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])));URL parameter... gets passed as anargumentCondition 1 to 366Wednesday, May 15, 13
  77. 77. 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])));404!Wednesday, May 15, 13
  78. 78. POST (with redirect)$app->post(/admin/add-photo, function() use ($app, $service) {$data = $app->request()->post();$service->save($data);$app->redirect(/admin);});Wednesday, May 15, 13
  79. 79. 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 inthe request objectWednesday, May 15, 13
  80. 80. 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 inthe request object302 RedirectWednesday, May 15, 13
  81. 81. Multiple methods$app->map(/login, function() {// Login})->via(GET, POST);Wednesday, May 15, 13
  82. 82. Multiple methods$app->map(/login, function() {// Login})->via(GET, POST);Not an HTTP MethodWednesday, May 15, 13
  83. 83. Multiple methods$app->map(/login, function() {// Login})->via(GET, POST);Not an HTTP Methodvia() is theawesome sauceWednesday, May 15, 13
  84. 84. Logging and flash messagingWednesday, May 15, 13
  85. 85. $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);});Wednesday, May 15, 13
  86. 86. $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);});Get the log from $appWednesday, May 15, 13
  87. 87. $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);});Get the log from $appError!Wednesday, May 15, 13
  88. 88. $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);});Get the log from $appError!Flash message available inthe next request.Wednesday, May 15, 13
  89. 89. 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/#Middleware-OverviewWednesday, May 15, 13
  90. 90. MiddlewareWednesday, May 15, 13
  91. 91. MiddlewareLike layers of an onionWednesday, May 15, 13
  92. 92. MiddlewareLike layers of an onionThe Slim application is the core of the onionWednesday, May 15, 13
  93. 93. MiddlewareLike layers of an onionThe Slim application is the core of the onionEach new middleware wraps any existing middlewareWednesday, May 15, 13
  94. 94. MiddlewareLike layers of an onionThe Slim application is the core of the onionEach new middleware wraps any existing middlewareEach middleware optionally calls the next middleware inthe chainWednesday, May 15, 13
  95. 95. MiddlewareLike layers of an onionThe Slim application is the core of the onionEach new middleware wraps any existing middlewareEach middleware optionally calls the next middleware inthe chainMiddleware is executed from the outside inWednesday, May 15, 13
  96. 96. MiddlewareLike layers of an onionThe Slim application is the core of the onionEach new middleware wraps any existing middlewareEach middleware optionally calls the next middleware inthe chainMiddleware is executed from the outside inPay careful attention to the order in which you registermiddlewareWednesday, May 15, 13
  97. 97. Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authentication($auth, $config));Wednesday, May 15, 13
  98. 98. Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authentication($auth, $config));Wednesday, May 15, 13
  99. 99. Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authentication($auth, $config));Wednesday, May 15, 13
  100. 100. Existing MiddlewareWednesday, May 15, 13
  101. 101. Existing MiddlewareFlash messagingWednesday, May 15, 13
  102. 102. Existing MiddlewareFlash messagingContent typesWednesday, May 15, 13
  103. 103. Existing MiddlewareFlash messagingContent typesPretty exceptionsWednesday, May 15, 13
  104. 104. Existing MiddlewareFlash messagingContent typesPretty exceptionsSession cookieWednesday, May 15, 13
  105. 105. Existing MiddlewareFlash messagingContent typesPretty exceptionsSession cookieMore in Slim ExtrasWednesday, May 15, 13
  106. 106. Roll your own MiddlewareWednesday, May 15, 13
  107. 107. Roll your own MiddlewareSuper easyWednesday, May 15, 13
  108. 108. Roll your own MiddlewareSuper easyDRYs up codeWednesday, May 15, 13
  109. 109. Roll your own MiddlewareSuper easyDRYs up codeAwesome application wide functionalityWednesday, May 15, 13
  110. 110. Roll your own MiddlewareSuper easyDRYs up codeAwesome application wide functionalityJust extend SlimMiddleware and implement call()Wednesday, May 15, 13
  111. 111. 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();}}Wednesday, May 15, 13
  112. 112. 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();}}Extend thisWednesday, May 15, 13
  113. 113. 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();}}Extend thisDefine call()Wednesday, May 15, 13
  114. 114. 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();}}Extend thisDefine call()Inspect, analyze,and modify!Wednesday, May 15, 13
  115. 115. 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();}}Extend thisDefine call()On to the next!Inspect, analyze,and modify!Wednesday, May 15, 13
  116. 116. Navigation exampleWednesday, May 15, 13
  117. 117. namespace FaMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware{/** @var AuthenticationService */private $auth;public function __construct(AuthenticationService $auth){$this->auth = $auth;}public function call(){// . . .}}Wednesday, May 15, 13
  118. 118. namespace FaMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware{/** @var AuthenticationService */private $auth;public function __construct(AuthenticationService $auth){$this->auth = $auth;}public function call(){// . . .}}extendsWednesday, May 15, 13
  119. 119. namespace FaMiddleware;use ZendAuthenticationAuthenticationService;class Navigation extends SlimMiddleware{/** @var AuthenticationService */private $auth;public function __construct(AuthenticationService $auth){$this->auth = $auth;}public function call(){// . . .}}Constructor injectionFTWextendsWednesday, May 15, 13
  120. 120. 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);}// . . .}Wednesday, May 15, 13
  121. 121. 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);}// . . .}Arrays ofnav itemsWednesday, May 15, 13
  122. 122. 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);}// . . .}Arrays ofnav itemsNav differs basedon auth statusWednesday, May 15, 13
  123. 123. public function call(){// . . .foreach ($navigation as &$link) {if ($link[href] == $req->getPath()) {$link[class] = active;} else {$link[class] = ;}}$app->view()->appendData(array(navigation => $navigation));$this->next->call();}Wednesday, May 15, 13
  124. 124. public function call(){// . . .foreach ($navigation as &$link) {if ($link[href] == $req->getPath()) {$link[class] = active;} else {$link[class] = ;}}$app->view()->appendData(array(navigation => $navigation));$this->next->call();}Matchdispatched pathWednesday, May 15, 13
  125. 125. public function call(){// . . .foreach ($navigation as &$link) {if ($link[href] == $req->getPath()) {$link[class] = active;} else {$link[class] = ;}}$app->view()->appendData(array(navigation => $navigation));$this->next->call();}Matchdispatched pathAppend$navigation toviewWednesday, May 15, 13
  126. 126. public function call(){// . . .foreach ($navigation as &$link) {if ($link[href] == $req->getPath()) {$link[class] = active;} else {$link[class] = ;}}$app->view()->appendData(array(navigation => $navigation));$this->next->call();}Matchdispatched pathAppend$navigation toviewOn to the next!Wednesday, May 15, 13
  127. 127. Route MiddlewareWednesday, May 15, 13
  128. 128. Route MiddlewareAnything that returns true for is_callable()Wednesday, May 15, 13
  129. 129. Route MiddlewareAnything that returns true for is_callable()Apply directly to route!Wednesday, May 15, 13
  130. 130. Route MiddlewareAnything that returns true for is_callable()Apply directly to route!Goes between route definition and route callableWednesday, May 15, 13
  131. 131. Route Middleware<?phpfunction mw1() {echo "This is middleware!";}function mw2() {echo "This is middleware!";}$app = new SlimSlim();$app->get(/foo, mw1, mw2, function () {//Do something});http://docs.slimframework.com/#Route-MiddlewareWednesday, May 15, 13
  132. 132. Route Middleware<?phpfunction mw1() {echo "This is middleware!";}function mw2() {echo "This is middleware!";}$app = new SlimSlim();$app->get(/foo, mw1, mw2, function () {//Do something});http://docs.slimframework.com/#Route-MiddlewareWednesday, May 15, 13
  133. 133. HooksA “hook” is a moment in the Slim application lifecycleat which a priority list of callables assigned to thehook will be invoked.A hook is identified by a stringname.http://docs.slimframework.com/#Hooks-OverviewWednesday, May 15, 13
  134. 134. HooksWednesday, May 15, 13
  135. 135. HooksAnything that returns true for is_callable()Wednesday, May 15, 13
  136. 136. HooksAnything that returns true for is_callable()PrioritizedWednesday, May 15, 13
  137. 137. HooksAnything that returns true for is_callable()PrioritizedSix default hooksWednesday, May 15, 13
  138. 138. HooksWednesday, May 15, 13
  139. 139. slim.beforeHooksWednesday, May 15, 13
  140. 140. slim.beforeslim.before.routerHooksWednesday, May 15, 13
  141. 141. slim.beforeslim.before.routerslim.before.dispatchHooksWednesday, May 15, 13
  142. 142. slim.beforeslim.before.routerslim.before.dispatchslim.after.dispatchHooksWednesday, May 15, 13
  143. 143. slim.beforeslim.before.routerslim.before.dispatchslim.after.dispatchslim.after.routerHooksWednesday, May 15, 13
  144. 144. slim.beforeslim.before.routerslim.before.dispatchslim.after.dispatchslim.after.routerslim.afterHooksWednesday, May 15, 13
  145. 145. slim.beforeslim.before.routerslim.before.dispatchslim.after.dispatchslim.after.routerslim.afterHooksWednesday, May 15, 13
  146. 146. Hooks$app = new SlimSlim();$app->hook(the.hook.name, function () {//Do something}, 5);Wednesday, May 15, 13
  147. 147. Hooks$app = new SlimSlim();$app->hook(the.hook.name, function () {//Do something}, 5);Optional PriorityWednesday, May 15, 13
  148. 148. Middleware + Hooks = WINWednesday, May 15, 13
  149. 149. Middleware + HooksUsing middleware to register hooks allowsme to inspect, analyze, or modify myapplication at a specific time in theapplication’s lifecycle in a DRY, testable, andreusable manner.Wednesday, May 15, 13
  150. 150. Authentication ExampleWednesday, May 15, 13
  151. 151. public function call(){$app = $this->app;$req = $app->request();$auth = $this->auth;$config = $this->config;// $checkAuth anonymous function snipped$this->app->hook(slim.before.router, $checkAuth);$this->next->call();}Wednesday, May 15, 13
  152. 152. public function call(){$app = $this->app;$req = $app->request();$auth = $this->auth;$config = $this->config;// $checkAuth anonymous function snipped$this->app->hook(slim.before.router, $checkAuth);$this->next->call();}Grab stuff toinspectWednesday, May 15, 13
  153. 153. public function call(){$app = $this->app;$req = $app->request();$auth = $this->auth;$config = $this->config;// $checkAuth anonymous function snipped$this->app->hook(slim.before.router, $checkAuth);$this->next->call();}Grab stuff toinspect(via constructor)Wednesday, May 15, 13
  154. 154. public function call(){$app = $this->app;$req = $app->request();$auth = $this->auth;$config = $this->config;// $checkAuth anonymous function snipped$this->app->hook(slim.before.router, $checkAuth);$this->next->call();}Grab stuff toinspectRegister hook(via constructor)Wednesday, May 15, 13
  155. 155. // Snip looping through secured url arrayif (preg_match($urlPattern, $req->getPathInfo())&& !$auth->hasIdentity()) {if ($req->getPath() !== $config[login.url]) {$app->redirect($config[login.url]);}}Wednesday, May 15, 13
  156. 156. // Snip looping through secured url arrayif (preg_match($urlPattern, $req->getPathInfo())&& !$auth->hasIdentity()) {if ($req->getPath() !== $config[login.url]) {$app->redirect($config[login.url]);}}Match path tosecured urlWednesday, May 15, 13
  157. 157. // Snip looping through secured url arrayif (preg_match($urlPattern, $req->getPathInfo())&& !$auth->hasIdentity()) {if ($req->getPath() !== $config[login.url]) {$app->redirect($config[login.url]);}}Match path tosecured urlLogged in?Wednesday, May 15, 13
  158. 158. // Snip looping through secured url arrayif (preg_match($urlPattern, $req->getPathInfo())&& !$auth->hasIdentity()) {if ($req->getPath() !== $config[login.url]) {$app->redirect($config[login.url]);}}Match path tosecured urlLogged in?RedirectWednesday, May 15, 13
  159. 159. ViewsWednesday, May 15, 13
  160. 160. SlimViewWednesday, May 15, 13
  161. 161. SlimViewSlim delegates rendering of templates to its view object.Wednesday, May 15, 13
  162. 162. SlimViewSlim delegates rendering of templates to its view object.Easily extensible by extending theView class andreturning a string from render()Wednesday, May 15, 13
  163. 163. SlimViewSlim delegates rendering of templates to its view object.Easily extensible by extending theView class andreturning a string from render()Use Slim application’s render() method in your appWednesday, May 15, 13
  164. 164. SlimViewSlim delegates rendering of templates to its view object.Easily extensible by extending theView class andreturning a string from render()Use Slim application’s render() method in your appWill echo() template output, buffer the output, andappend to response object’s bodyWednesday, May 15, 13
  165. 165. Rendering an app view$app->render(hello.html,array( name => Josh ),200);Wednesday, May 15, 13
  166. 166. Rendering an app view$app->render(hello.html,array( name => Josh ),200);TemplateWednesday, May 15, 13
  167. 167. Rendering an app view$app->render(hello.html,array( name => Josh ),200);Template View data(optional)Wednesday, May 15, 13
  168. 168. Rendering an app view$app->render(hello.html,array( name => Josh ),200);Template View data(optional)HTTP Response(optional)Wednesday, May 15, 13
  169. 169. TemplatesWednesday, May 15, 13
  170. 170. Two great tastesthat taste great togetherWednesday, May 15, 13
  171. 171. TwigWednesday, May 15, 13
  172. 172. TwigConciseWednesday, May 15, 13
  173. 173. TwigConciseTemplate orientedWednesday, May 15, 13
  174. 174. TwigConciseTemplate orientedFastWednesday, May 15, 13
  175. 175. TwigConciseTemplate orientedFastMultiple inheritanceWednesday, May 15, 13
  176. 176. TwigConciseTemplate orientedFastMultiple inheritanceContent blocksWednesday, May 15, 13
  177. 177. TwigConciseTemplate orientedFastMultiple inheritanceContent blocksAutomatic escapingWednesday, May 15, 13
  178. 178. BootstrapBecause I majorly suck at designWednesday, May 15, 13
  179. 179. CaveatI chose Twig because I wanted to learn Twig,but you could choose any or more of thefollowing:PHP, Mustache, Haml, Haanga, Blitz,Dwoo . . .https://github.com/codeguy/Slim-ExtrasWednesday, May 15, 13
  180. 180. layout.htmlandindex.htmlWednesday, May 15, 13
  181. 181. layout.htmlandindex.htmlWednesday, May 15, 13
  182. 182. layout.htmlandindex.htmlWednesday, May 15, 13
  183. 183. layout.htmlWednesday, May 15, 13
  184. 184. <title>{% block page_title %} {% endblock %}</title>layout.html: titleWednesday, May 15, 13
  185. 185. <ul class="nav">{% for link in navigation %}<li class="{{link.class}}"><a href="{{link.href}}">{{link.caption}}</a></li>{% endfor %}</ul>layout.html: navigationWednesday, May 15, 13
  186. 186. <h1>365 Days of Photography</h1><h3>Photographer: Jeremy Kendall</h3>{% block content %} {% endblock %}<hr />layout.html:headers and contentWednesday, May 15, 13
  187. 187. index.html(extends layout.html)Wednesday, May 15, 13
  188. 188. {% 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 %}Wednesday, May 15, 13
  189. 189. {% 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 %}extendsWednesday, May 15, 13
  190. 190. {% 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 %}extends<title />Wednesday, May 15, 13
  191. 191. {% 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 %}extends<title />Wednesday, May 15, 13
  192. 192. {% 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 %}extends<title />iteratorWednesday, May 15, 13
  193. 193. {% 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 %}extends<title />iteratorelseWednesday, May 15, 13
  194. 194. {% 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 %}extends<title />iteratorelseformatWednesday, May 15, 13
  195. 195. login.htmlWednesday, May 15, 13
  196. 196. {% 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 %}login.htmlWednesday, May 15, 13
  197. 197. {% 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 %}login.htmlWednesday, May 15, 13
  198. 198. The other templatesare just more of the sameWednesday, May 15, 13
  199. 199. Application CodeAnother big hurdle I had with Slim wasfiguring out how to organize my applicationcode.Wednesday, May 15, 13
  200. 200. Thin Controller, Fat ModelWednesday, May 15, 13
  201. 201. Thin Controller, Fat ModelDuh!Wednesday, May 15, 13
  202. 202. Thin Controller, Fat ModelDuh!All my application code is in a library directoryWednesday, May 15, 13
  203. 203. Thin Controller, Fat ModelDuh!All my application code is in a library directoryIt’s all namespaced, autoloadable, and testableWednesday, May 15, 13
  204. 204. Thin Controller, Fat ModelDuh!All my application code is in a library directoryIt’s all namespaced, autoloadable, and testableI have (almost) zero business logic in index.phpWednesday, May 15, 13
  205. 205. Thin Controller, Fat ModelDuh!All my application code is in a library directoryIt’s all namespaced, autoloadable, and testableI have (almost) zero business logic in index.phpDependencies are managed by ComposerWednesday, May 15, 13
  206. 206. Thin Controller, Fat ModelDuh!All my application code is in a library directoryIt’s all namespaced, autoloadable, and testableI have (almost) zero business logic in index.phpDependencies are managed by ComposerI could theoretically switch frameworks with very littleeffortWednesday, May 15, 13
  207. 207. GOTO 0Wednesday, May 15, 13
  208. 208. Small but powerful GOTO 0Wednesday, May 15, 13
  209. 209. Small but powerfulExcellent tools to write elegant codeGOTO 0Wednesday, May 15, 13
  210. 210. Small but powerfulExcellent tools to write elegant codeRouting, middleware, hooks, templates, andviewsGOTO 0Wednesday, May 15, 13
  211. 211. Small but powerfulExcellent tools to write elegant codeRouting, middleware, hooks, templates, andviewsI just scratched the surfaceGOTO 0Wednesday, May 15, 13
  212. 212. ReadSlim: slimframework.comTwig: twig.sensiolabs.orgComposer: getcomposer.orgMicroPHP Manifesto: microphp.orgFlaming Archer: http://git.io/rH0nrgWednesday, May 15, 13
  213. 213. Questions?Wednesday, May 15, 13
  214. 214. Thanks!jeremy@jeremykendall.net@jeremykendallhttp://joind.in/8175Wednesday, May 15, 13
  1. A particular slide catching your eye?

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

×