Keeping it small - Getting to know the Slim PHP micro framework
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 2,919 views

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 ...

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.

Statistics

Views

Total Views
2,919
Views on SlideShare
2,771
Embed Views
148

Actions

Likes
8
Downloads
114
Comments
0

1 Embed 148

http://librosweb.es 148

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

  • 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/Wednesday, May 15, 13
  • 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, May 15, 13
  • 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’s Composer. It’s that big of a deal.Wednesday, May 15, 13
  • 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.slimframework.com/#Route-URL-Rewriting(nginx documentation available at same URL)Wednesday, May 15, 13
  • Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  • Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  • Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  • Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  • Hello $name<?phprequire ../vendor/autoload.php;$app = new SlimSlim();$app->get(/hello/:name, function ($name) {echo "Hello, $name";});$app->run();Wednesday, May 15, 13
  • 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, May 15, 13
  • Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig templatesWednesday, May 15, 13
  • Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig templatesMiddlewareWednesday, May 15, 13
  • Flaming ArcherPhoto 365 projectBulk of app built in 4 daysBasic application — a few bells, no whistlesRoutingTwig templatesMiddlewareHooksWednesday, May 15, 13
  • 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: 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
  • ConfigurationWednesday, May 15, 13
  • 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
  • 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
  • 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
  • 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
  • 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
  • $config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);ConfigurationWednesday, May 15, 13
  • $config = require_once __DIR__ . /../config.php;// Prepare app$app = new SlimSlim($config[slim]);Config arraygoes hereConfigurationWednesday, May 15, 13
  • RoutingWednesday, May 15, 13
  • Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});Wednesday, May 15, 13
  • Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});HTTP MethodWednesday, May 15, 13
  • Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});HTTP MethodResource URIWednesday, May 15, 13
  • Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});HTTP MethodResource URIAnonymous FunctionWednesday, May 15, 13
  • Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});Wednesday, May 15, 13
  • Routing$app->get(/, function () use ($app, $service) {$images = $service->findAll();$app->render(index.html, array(images => $images));});Grabs all the picsWednesday, May 15, 13
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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 sauceWednesday, May 15, 13
  • Logging and flash messagingWednesday, May 15, 13
  • $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
  • $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
  • $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
  • $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
  • 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
  • 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 middlewareWednesday, May 15, 13
  • 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
  • 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
  • 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
  • Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authentication($auth, $config));Wednesday, May 15, 13
  • Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authentication($auth, $config));Wednesday, May 15, 13
  • Middleware// Prepare app$app = new SlimSlim($config[slim]);// . . .$app->add(new Navigation($auth));$app->add(new Authentication($auth, $config));Wednesday, May 15, 13
  • 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 implement call()Wednesday, May 15, 13
  • 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
  • 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
  • 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
  • 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
  • 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
  • Navigation exampleWednesday, May 15, 13
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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 callableWednesday, May 15, 13
  • 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
  • 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
  • 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
  • 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 time in theapplication’s lifecycle in a DRY, testable, andreusable manner.Wednesday, May 15, 13
  • Authentication ExampleWednesday, May 15, 13
  • 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
  • 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
  • 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
  • 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
  • // 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
  • // 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
  • // 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
  • // 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
  • 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 a string from render()Wednesday, May 15, 13
  • 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
  • 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
  • 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)Wednesday, May 15, 13
  • 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, Haanga, Blitz,Dwoo . . .https://github.com/codeguy/Slim-ExtrasWednesday, May 15, 13
  • 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>{% endfor %}</ul>layout.html: navigationWednesday, May 15, 13
  • <h1>365 Days of Photography</h1><h3>Photographer: Jeremy Kendall</h3>{% block content %} {% endblock %}<hr />layout.html:headers and contentWednesday, May 15, 13
  • index.html(extends layout.html)Wednesday, May 15, 13
  • {% 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
  • {% 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
  • {% 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
  • {% 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
  • {% 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
  • {% 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
  • {% 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
  • login.htmlWednesday, May 15, 13
  • {% 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
  • {% 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
  • 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 testableWednesday, May 15, 13
  • 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
  • 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
  • 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
  • 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 15, 13
  • Small but powerfulExcellent tools to write elegant codeRouting, middleware, hooks, templates, andviewsI just scratched the surfaceGOTO 0Wednesday, May 15, 13
  • ReadSlim: slimframework.comTwig: twig.sensiolabs.orgComposer: getcomposer.orgMicroPHP Manifesto: microphp.orgFlaming Archer: http://git.io/rH0nrgWednesday, May 15, 13
  • Questions?Wednesday, May 15, 13
  • Thanks!jeremy@jeremykendall.net@jeremykendallhttp://joind.in/8175Wednesday, May 15, 13