Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Silex (phpday)

Silex (phpday)

Igor Wiedler

May 29, 2012
Tweet

More Decks by Igor Wiedler

Other Decks in Programming

Transcript

  1. View Slide

  2. • phpBB
    • Symfony2
    • Silex
    • Composer
    igorw
    @igorwesome

    View Slide

  3. View Slide

  4. $s=stream_socket_server('tcp://127.0.0.1:81');
    while($c=stream_socket_accept($s))
    fwrite($c,"HTTP/1.1 200 OK\r\nContent-Length:
    2\r\n\r\nHi");

    View Slide

  5. require __DIR__.'/c.php';
    if (!is_callable($c = @$_GET['c'] ?: function() { echo 'Woah!'; }))
    throw new Exception('Error');
    $c();

    View Slide

  6. Silex
    Symfony2 μ-framework

    View Slide

  7. Silex is not Symfony

    View Slide

  8. Microframework

    View Slide

  9. View Slide

  10. What?
    • Bare bones
    • Routes mapped to controllers
    • The ‘C’ of ‘MVC’
    • REST
    • Single file app (ish)

    View Slide

  11. Why?

    View Slide

  12. Sometimes a full-stack framework is
    too much for a simple task.

    View Slide

  13. simple

    View Slide

  14. What makes silex
    special?

    View Slide

  15. • concise
    • extensible
    • testable

    View Slide

  16. • concise
    • extensible
    • testable

    View Slide

  17. • concise
    • extensible
    • testable

    View Slide

  18. • concise
    • extensible
    • testable

    View Slide

  19. • concise
    • extensible
    • testable

    View Slide

  20. Http Kernel
    Interface

    View Slide

  21. Response handle(Request $request)

    View Slide

  22. client

    View Slide

  23. request
    client

    View Slide

  24. reponse
    client
    request

    View Slide

  25. clean

    View Slide

  26. PSR-0

    View Slide

  27. View Slide

  28. Silex is not Symfony

    View Slide

  29. Silex
    is a user interface for
    Symfony

    View Slide

  30. require_once __DIR__.'/silex.phar';
    $app = new Silex\Application();
    $app->get('/', function() {
    return "Hello world!";
    });

    View Slide

  31. Phar
    require_once __DIR__.'/silex.phar';
    $app = new Silex\Application();
    $app->get('/', function() {
    return "Hello world!";
    });

    View Slide

  32. Phar
    require_once __DIR__.'/silex.phar';
    $app = new Silex\Application();
    $app->get('/', function() {
    return "Hello world!";
    });
    = FUBAR

    View Slide

  33. Composer
    require_once 'vendor/autoload.php';
    $app = new Silex\Application();
    $app->get('/', function() {
    return "Hello world!";
    });

    View Slide

  34. Application
    require_once 'vendor/autoload.php';
    $app = new Silex\Application();
    $app->get('/', function() {
    return "Hello world!";
    });

    View Slide

  35. require_once 'vendor/autoload.php';
    $app = new Silex\Application();
    $app->get('/', function() {
    return "Hello world!";
    });
    Controller

    View Slide

  36. $app->run();

    View Slide

  37. View Slide


  38. RewriteEngine On
    RewriteBase /some/path
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php [QSA,L]

    View Slide

  39. server {
    index index.php
    location / {
    try_files $uri $uri/ /index.php;
    }
    location ~ index\.php$ {
    fastcgi_pass /var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    }
    }

    View Slide

  40. Wait a minute!

    View Slide

  41. Lambdas
    λ

    View Slide

  42. $(function () {
    $("a").on("click", function (event) {
    alert("Thanks for visiting!");
    });
    });

    View Slide

  43. PHP 5.3

    View Slide

  44. $f = function ($a, $b) {
    return $a + $b;
    };
    $f(1, 2);

    View Slide

  45. lazy
    $f = function () {
    exit;
    };

    View Slide

  46. nested
    $f = function () {
    return function () {
    return true;
    };
    };
    $g = $f();
    $value = $g();

    View Slide

  47. scope
    $outer = 'world';
    $f = function () use ($outer) {
    $inner = 'hello';
    return "$inner $outer";
    };
    => "hello world"

    View Slide

  48. scope
    $helloWorld = function () {
    $outer = 'world';
    $f = function () use ($outer) {
    $inner = 'hello';
    return "$inner $outer";
    };
    return $f();
    }

    View Slide

  49. passing
    $output = function ($info) {
    echo $info."\n";
    };
    $doStuff = function ($output) {
    $output('doing some magic');
    doMagic();
    $output('did some magic');
    };

    View Slide

  50. factory
    $userFactory = function ($name) {
    return new User($name);
    };
    // ...
    $user = $userFactory($_POST['name']);

    View Slide

  51. event listener
    $emitter = new EventEmitter();
    $emitter->on('user.create', function (User $user) {
    $msg = sprintf("User %s created.", $user->name);
    log($msg);
    });

    View Slide

  52. Usage

    View Slide

  53. $app->get('/', function () {
    return "Hello world!";
    });

    View Slide

  54. Dynamic Routing

    View Slide

  55. $app->get('/hello/{name}',
    function ($name) use ($app) {
    return "Hello ".$app->escape($name);
    });

    View Slide

  56. $app->get('/hello/{name}',
    function ($name) use ($app) {
    return "Hello ".$app->escape($name);
    });

    View Slide

  57. Controllers

    View Slide

  58. assert
    $app->get('/blog/{id}', function ($id) {
    ...
    })
    ->assert('id', '\d+');

    View Slide

  59. value
    $app->get('/{page}', function ($page) {
    ...
    })
    ->value('page', 'index');

    View Slide

  60. bind
    $app->get('/', function () {
    ...
    })
    ->bind('homepage');
    $app['url_generator']->generate('homepage')

    View Slide

  61. bind
    $app->get('/blog/{id}', function ($id) {
    ...
    })
    ->bind('blog.post');
    $app['url_generator']
    ->generate('blog.post', array('id' => $id))

    View Slide

  62. convert
    $app->get('/blog/{post}', function (Post $post) {
    ...
    })
    ->convert('post', function ($post) use ($app) {
    $id = (int) $post;
    return $app['posts']->find($id);
    });

    View Slide

  63. Before & After

    View Slide

  64. $app->before(function () {
    ...
    });
    $app->get('/', function () {
    ...
    });
    $app->after(function () {
    ...
    });

    View Slide

  65. $app->before(function (Request $request) {
    $loggedIn = $request
    ->getSession()
    ->get('logged_in');
    if (!$loggedIn) {
    return new RedirectResponse('/login');
    }
    });

    View Slide

  66. $app->after(function (Request $request, Response $response) {
    // tweak the Response
    });

    View Slide

  67. Methods

    View Slide

  68. • get
    • post
    • put
    • delete
    • head
    • options

    View Slide

  69. $app->get('/posts/{id}', ...);
    $app->post('/posts', ...);
    $app->put('/posts/{id}', ...);
    $app->delete('/post/{id}', ...);

    View Slide

  70. use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    $app->post('/message', function (Request $request) {
    mail(
    '[email protected]',
    'New message',
    $request->get('body')
    );
    return new Response('Email has been sent!', 201);
    });

    View Slide

  71. Caching

    View Slide

  72. Error Handling

    View Slide

  73. use Symfony\Component\HttpFoundation\Response;
    $app->error(function (\Exception $e, $code) {
    return new Response('Whoops!', $code);
    });

    View Slide

  74. $app->abort(404, "Could not find the thing.");

    View Slide

  75. $app['debug'] = true;

    View Slide

  76. Redirecting

    View Slide

  77. $app->get('/', function () use ($app) {
    return $app->redirect('/hello');
    });

    View Slide

  78. Pimple

    View Slide

  79. ~50 NCLOC

    View Slide

  80. $container = new Pimple();

    View Slide

  81. $app = new Silex\Application();

    View Slide

  82. Parameters
    $app['some_parameter'] = 'value';
    $app['asset.host'] = 'http://cdn.mysite.com/';
    $app['database.dsn'] = 'mysql:dbname=myapp';

    View Slide

  83. Services
    $app['some_service'] = function () {
    return new Service();
    };

    View Slide

  84. $service = $app['some_service'];

    View Slide

  85. Dependencies
    $app['some_service'] = function ($app) {
    return new Service(
    $app['some_other_service'],
    $app['some_service.config']
    );
    };

    View Slide

  86. Shared
    $app['some_service'] = $app->share(function () {
    return new Service();
    });

    View Slide

  87. Protected
    $app['lambda_parameter'] = $app->protect(
    function ($a, $b) {
    return $a + $b;
    });
    // will not execute the lambda
    $add = $app['lambda_parameter'];
    // calling it now
    echo $add(2, 3);

    View Slide

  88. Exposed Services
    • debug
    • request
    • autoloader
    • routes
    • controllers
    • dispatcher
    • resolver
    • kernel

    View Slide

  89. Service Providers

    View Slide

  90. interface ServiceProviderInterface
    {
    function register(Application $app);
    }

    View Slide

  91. Core
    Service Providers
    • doctrine
    • form
    • http cache
    • monolog
    • session
    • swiftmailer
    • symfony bridges
    • translation
    • twig
    • url generator
    • validator

    View Slide

  92. 3rd Party
    • doctrine orm
    • propel
    • pomm (postgres)
    • predis
    • mongo
    • KyotoTycoon
    • memcache
    • rest
    • markdown
    • gravatar
    • buzz
    • config
    • solr
    • profiler
    • ...

    View Slide

  93. Redis

    View Slide

  94. $app->register(new PredisServiceProvider());

    View Slide

  95. $app->get('/{id}', function ($id) use ($app) {
    $key = 'pastes:'.$id;
    $paste = $app['predis']->hgetall($key);
    ...
    });

    View Slide

  96. View Slide

  97. • smallish sites
    • well-defined scope
    • prototyping
    • restful apis
    When to use

    View Slide

  98. and many more...

    View Slide

  99. View Slide

  100. New feature:
    Streaming

    View Slide

  101. $app->get('/some-video', function () use ($app) {
    $file = $app['app.video_filename'];
    $stream = function () use ($file) {
    readfile($file);
    };
    return $app->stream(
    $stream,
    200,
    array('Content-Type' => 'video/mpeg')
    );
    });

    View Slide

  102. New feature:
    Middlewares

    View Slide

  103. $mustBeLogged = function (Request $request) use ($app) {
    if (!$app['session']->has('userId')) {
    return $app->redirect('/user/login');
    }
    };
    $app->get('/user/my-profile', function () {
    ...
    })
    ->middleware($mustBeLogged);

    View Slide

  104. New feature:
    JSON helper

    View Slide

  105. $app->get('/users/{id}', function ($id) use ($app) {
    $user = getUser($id);
    if (!$user) {
    $message = 'The user was not found.';
    $error = array('message' => $message);
    return $app->json($error, 404);
    }
    return $app->json($user);
    });

    View Slide

  106. New feature:
    Finish filter

    View Slide

  107. $app->finish(function () {
    // send e-mails
    // very slow query
    // some slow API calls
    });

    View Slide

  108. New feature:
    Composer

    View Slide

  109. View Slide

  110. {
    "minimum-stability": "dev",
    "require": {
    "silex/silex": "1.0.*@dev"
    }
    }
    composer.json

    View Slide

  111. $ php composer.phar install

    View Slide

  112. require 'vendor/autoload.php';

    View Slide

  113. on github
    fabpot/Silex
    fabpot/Pimple

    View Slide

  114. silex.sensiolabs.org

    View Slide

  115. Ω

    View Slide

  116. Questions?
    joind.in/6391
    @igorwesome
    speakerdeck.com
    /u/igorw

    View Slide