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

Silex: From Micro to Full stack

Silex: From Micro to Full stack

"Silex: From Micro to Full stack" presented at SymfonyLive Berlin 2014

Avatar for Dustin Whittle

Dustin Whittle

October 30, 2014
Tweet

More Decks by Dustin Whittle

Other Decks in Technology

Transcript

  1. What I have worked on • Developer Evangelist @ •

    Consultant & Trainer @ • Developer Evangelist @

  2. What is Silex? • Do you know Sinatra, Express, or

    Flask?
 • Silex is a micro framework standing on the shoulders of giants • Based on Symfony components • Easy installation with Composer • Created by Fabien Potencier + Igor Wiedler • MIT License • http://silex.sensiolabs.org/
  3. Silex Philosophy • Silex, being a micro-framework, has some limitations.

    Silex will never support the following: • A CLI tool + any feature that would introduce the need for a CLI tool • Any feature that needs mandatory external files (XML/YAML configuration files) • Any feature that is not PHPish (annotations) • Any feature that adds a lot of code to Silex • Any feature to the "core" (Application class)
  4. Why use Silex? • A full-stack framework is overkill for

    a simple task • Map routes to controllers • Silex != Symfony2 • Concise • Extensible • Testable
  5. Hello World! <?php require_once __DIR__.'/../vendor/autoload.php'; $app = new Silex\Application(); $app->get('/hello/{name}',

    function ($name) use ($app) { return 'Hello '.$app->escape($name); }); $app->run();
  6. An app structure for Silex Config: config/dev.php config/prod.php
 App: console

    src/app.php src/console.php src/controllers.php Views: templates/404.html templates/500.html templates/index.html templates/layout.html
 Front Controller: web/index.php web/index_dev.php
  7. Adding features with providers • A provider exposes functionality to

    a Silex application • Pimple is a simple dependency injection container • Use community providers to add functionality that isn’t available by default • Just like Symfony2 bundles
  8. Core Service Providers • URL Generator • Session • Validator

    • Form • Security • Translation • HTTP Cache • Twig • Monolog • Doctrine • SwiftMailer • ServiceController
  9. Adding a router to Silex /* Add url generator support

    */ $app->register(new Silex\Provider\UrlGeneratorServiceProvider()); /* Add controllers for app */ $app->get('/', function () use ($app) { return $app['twig']->render('index.html.twig', array()); })->bind('homepage'); /* Generate a url */ $app->get('/navigation', function () use ($app) { return '<a href="'.$app['url_generator']- >generate('homepage').'">Home</a>'; });
  10. Adding sessions to Silex /* Add session support */ $app->register(new

    Silex\Provider\SessionServiceProvider()); /* Save something in session */ $app['session']->set('user', array('username' => 'symfonylive')); /* Fetch something in session */ $user = $app['session']->get('user')
  11. Integrating Twig /* Add twig support */ $app->register(new Silex\Provider\TwigServiceProvider(), array(

    'twig.path' => __DIR__.'/../templates', )); /* Add controllers for app */ $app->get('/', function () use ($app) { return $app['twig']->render('index.html.twig', array()); })->bind('homepage');
  12. Adding translations to Silex /* Add translation support */ $app->register(new

    Silex\Provider\TranslationServiceProvider(), array( 'locale_fallback' => 'en', ));
 $app['translator.domains'] = array( 'messages' => array( 'en' => array( 'hello' => 'Hello %name%', 'goodbye' => 'Goodbye %name%', ), 'fr' => array( 'hello' => 'Bonjour %name%', 'goodbye' => 'Au revoir %name%', ), ) ), ); $app->get('/{_locale}/{message}/{name}', function ($message, $name) use ($app) { return $app['translator']->trans($message, array('%name%' => $name)); });
  13. Adding a form to Silex $app->register(new Silex\Provider\FormServiceProvider()); $app->match('/contact', function (Request

    $request) use ($app) { $data = array( 'name' => 'Your name', 'email' => 'Your email', ); $form = $app['form.factory']->createBuilder('form', $data) ->add('name') ->add('email') ->add('gender', 'choice', array( 'choices' => array(1 => 'male', 2 => 'female'), 'expanded' => true, )) ->getForm(); if ('POST' == $request->getMethod()) { $form->bind($request); if ($form->isValid()) { $data = $form->getData(); return $app->redirect('...'); } } return $app['twig']->render('index.twig', array('form' => $form->createView())); });
  14. Adding a validator to Silex use Symfony\Component\Validator\Constraints as Assert; $app->register(new

    Silex\Provider\ValidatorServiceProvider()); $app->register(new Silex\Provider\TranslationServiceProvider(), array( 'translator.messages' => array(), )); $form = $app['form.factory']->createBuilder('form') ->add('name', 'text', array( 'constraints' => array(new Assert\NotBlank(), new Assert\MinLength(5)) )) ->add('email', 'text', array( 'constraints' => new Assert\Email() )) ->add('gender', 'choice', array( 'choices' => array(1 => 'male', 2 => 'female'), 'expanded' => true, 'constraints' => new Assert\Choice(array(1, 2)), )) ->getForm();
  15. Adding a form to Silex <form action="#" method="post"> {{ form_widget(form)

    }} <input type="submit" name="submit" /> </form>
  16. Adding caching to Silex use Symfony\Component\HttpFoundation\Response; /* Add http cache

    support */ $app->register(new Silex\Provider\HttpCacheServiceProvider(), array( 'http_cache.cache_dir' => __DIR__.'/cache', )); $app->get('/', function() { return new Response('Foo', 200, array( 'Cache-Control' => 's-maxage=5', )); });
  17. Integrating Doctrine DBAL /* Add doctrine dbal support */ $app->register(new

    Silex\Provider\DoctrineServiceProvider(), array( 'db.options' => array( 'driver' => 'pdo_sqlite', 'path' => __DIR__.'/app.db', ), )); /* Execute a sql query */ $data = $app['db']->fetchAssoc('SELECT * FROM table');
  18. Simple JSON API $app->get('/todo/{id}', function ($id) use ($app) { $sql

    = 'SELECT * FROM todo WHERE id = ?'; $todo = $app['db']->fetchAssoc($sql, array((int) $id)); if (!$todo) { $app->abort(404, sprintf('Todo %s does not exist.', $id); } return $app->json($todo); });
  19. Integrating Monolog /* Add monolog support */ $app->register(new Silex\Provider\MonologServiceProvider(), array(

    'monolog.logfile' => __DIR__.'/../log/app.log', )); /* Write to log */ $app['monolog']->addDebug('OMG! SymfonyLive...');
  20. Integrating SwiftMailer /* Add swiftmailer support */ $app->register(new Silex\Provider\SwiftmailerServiceProvider()); $app->post('/feedback',

    function () use ($app) { $message = \Swift_Message::newInstance() ->setSubject('[YourSite] Feedback') ->setFrom('[email protected]') ->setTo('[email protected]') ->setBody($app['request']->get('message')); $app['mailer']->send($message); return new Response('Thank you for your feedback!', 201); });
  21. Adding security to Silex /* Add security support */ $app->register(new

    Silex\Provider\SecurityServiceProvider()); $app['security.firewalls'] = array( 'admin' => array( 'pattern' => '^/admin/', 'form' => array('login_path' => '/login', 'check_path' => '/admin/login_check'), 'users' => array( 'admin' => array('ROLE_ADMIN', '...'), ), ), ) /* Fetch user token */ $token = $app['security']->getToken();
  22. What is a full stack framework? • Default Structure •

    Default Conventions • Configuration (yml, xml, ini, etc) • Symfony2 you remove features • Silex you add them
  23. Scaling Silex for larger apps • Exposing new functionality with

    service providers • Moving out of a single file • Controllers in different files • Using twig for templates • Adding support for database + cache + … • Using controllers as services
  24. Creating your own provider • Integrate any third party library

    easily by adding a service to the container • Facebook SDK
  25. $app['facebook.app_id'] = 'xxx'; $app['facebook.secret'] = 'xxx'; $app['facebook'] = $app->share(function ()

    use ($app) { return new \Facebook(array( 'appId' => $app['facebook.app_id'], 'secret' => $app['facebook.secret'], )); }); Adding a Facebook Service Provider
  26. Adding a Facebook Service Provider namespace SymfonyLive\Provider; use Silex\Application; use

    Silex\ServiceProviderInterface; class FacebookServiceProvider implements ServiceProviderInterface { public function register(Application $app) { $app['facebook'] = $app->share(function () use ($app) { return new \Facebook(array( 'appId' => $app['facebook.app_id'], 'secret' => $app['facebook.secret'], )); }); } public function boot(Application $app) { } }
  27. Using Facebook Service Provider $app = new Silex\Application(); $app->register(new SymfonyLive\FacebookServiceProvider(),

    array( 'facebook.app_id' => 'xxx', 'facebook.secret' => 'xxx', )); $app->get('/', function () use ($app) { $user = $app['facebook']->getUser(); return $app->json($user); });
  28. Adding controllers as services use Silex\Application; use Demo\Repository\PostRepository; $app =

    new Application(); $app->register(new Silex\Provider\ServiceControllerServiceProvider()); $app['posts.repository'] = $app->share(function() { return new PostRepository(); }); $app->get('/posts.json', function() use ($app) { return $app->json($app['posts.repository']->findAll()); });
  29. Bootstrap the kitchen sink • composer.phar create-project lyrixx/Silex-Kitchen-Edition
 • HTML5

    Boilerplate + Twitter Bootstrap • Providers + Examples • Twig, Cache, Form, Session, Security, Translation, Assetic, Doctrine
  30. When Silex makes sense? • Simple applications • RESTful API

    applications • Silex can replace Symfony2
  31. When to use a full stack? • You have a

    large application that requires the structure of Symfony2 • You need an ORM • You need a more powerful service container • ...
  32. Support • Mailing list • http://groups.google.com/group/silex-php • IRC • #silex-php

    on irc.freenode.net • Github • http://github.com/fabpot/Silex/issues