Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Complex Sites with Silex

2,369 views

Published on

Everyone knows that Silex is a great microframework for APIs and small sites, but what do you do when you want to build a large site, or your little tiny site has grown up? Silex has many different ways to let you build larger, complex websites that might still be too small for Symfony, but have outgrown the single page app it once was. We’ll look at what Silex offers us, and different ways we can structure our site.

Published in: Technology
  • Be the first to comment

Complex Sites with Silex

  1. 1. Complex Sites with Silex Chris Tankersley ZendCon 2014
  2. 2. 2 Who Am I? ● A PHP Developer for 10 Years ● Lots of projects no one uses, and a few some do ● https://github.com/dragonmantank
  3. 3. 3 What is Silex?
  4. 4. 4 Microframework ● Built off of the Symfony2 Components ● Micro Service Container ● Provides Routing ● Provides Extensions
  5. 5. 5 Why to Not Use Silex ● You have to piece things together ● Not great for large projects
  6. 6. 6 Why use Silex? ● You can use the libraries you want ● Great for small/medium projects ● Prototypers best friend
  7. 7. 7 Sites Change over time
  8. 8. 8 Silex Allows Us To Adapt
  9. 9. 9 Basic Silex App
  10. 10. 10 Set up Silex composer require “silex/silex”:”~1.2”
  11. 11. 11 Sample Silex App <?php require_once __DIR__ . '/../vendor/autoload.php'; $app = new SilexApplication(); $app->get('/', function() use ($app) { return 'Hello World'; }); $app->run();
  12. 12. 12 Congrats!
  13. 13. 13 And you add more pages <?php require_once __DIR__ . '/../vendor/autoload.php'; $app = new SilexApplication(); $app->get('/', function() use ($app) {/*...*/}); $app->get('/about, function() use ($app) {/*...*/}); $app->get('/contact', function() use ($app) {/*...*/}); $app->get('/services', function() use ($app) {/*...*/}); $app->run();
  14. 14. 14 Service Providers
  15. 15. 15 What do they do? ● Allows code reuse ● For both services and controllers
  16. 16. 16 Service Providers ● Twig ● URL Generator ● Session ● Validator ● Form ● HTTP Cache ● HTTP Fragments ● Security ● Remember Me ● Switftmailer ● Monolog ● Translation ● Serializer ● Doctrine ● Controllers as Services
  17. 17. 17 And you add templating <?php require_once __DIR__ . '/../vendor/autoload.php'; $app = new SilexApplication(); $app->register(new SilexProviderTwigServiceProvider(), array( 'twig.path' => __DIR__.'/../views', )); $app->get('/', function() use ($app) { return $app['twig']->render('homepage.html.twig'); }); $app->get('/about, function() use ($app) {/*...*/}); $app->get('/contact', function() use ($app) {/*...*/}); $app->get('/services', function() use ($app) {/*...*/}); $app->run();
  18. 18. 18 Adding a Form ●We need to generate the form ●We need to accept the form ●We need to e-mail the form
  19. 19. 19 Now we add a form <?php require_once __DIR__ . '/../vendor/autoload.php'; use SymfonyComponentHttpFoundationRequest; $app = new SilexApplication(); $app->register(new SilexProviderTwigServiceProvider(), array( 'twig.path' => __DIR__.'/views', )); $app->register(new SilexProviderFormServiceProvider()); $app->register(new SilexProviderTranslationServiceProvider()); $app->get('/', function() use ($app) {/*...*/}); $app->get('/about, function() use ($app) {/*...*/}); $app->get('/contact', function(Request $request) use ($app) { $form = $app['form.factory']->createBuilder('form') ->add('name') ->add('email') ->getForm() ; $form->handleRequest($request); if($form->isValid()) { $data = $form->getData(); // Mail it } return $app['twig']->render('contact.html.twig', array('form' => $form->createView())); }); $app->get('/services', function() use ($app) {/*..}); $app->run();
  20. 20. 20 HTTP Method Routing
  21. 21. 21 Whoops
  22. 22. 22 Allow Both Methods <?php require_once __DIR__ . '/../vendor/autoload.php'; use SymfonyComponentHttpFoundationRequest; $app = new SilexApplication(); $app->register(new SilexProviderTwigServiceProvider(), array( 'twig.path' => __DIR__.'/views', )); $app->register(new SilexProviderFormServiceProvider()); $app->register(new SilexProviderTranslationServiceProvider()); $app->get('/', function() use ($app) {/*...*/}); $app->get('/about, function() use ($app) {/*...*/}); $app->match('/contact', function(Request $request) use ($app) { $form = $app['form.factory']->createBuilder('form') ->add('name') ->add('email') ->getForm() ; $form->handleRequest($request); if($form->isValid()) { $data = $form->getData(); // Mail it } return $app['twig']->render('contact.html.twig', array('form' => $form->createView())); })->method('GET|POST'); $app->get('/services', function() use ($app) {/*..}); $app->run();
  23. 23. 23 We've silently introduced a problem into our code
  24. 24. 24 Code Quickly Turns to Spaghetti http://commons.wikimedia.org/wiki/File:Spaghetti-prepared.jpg
  25. 25. 25 Pretend to be a big framework
  26. 26. 26 What do we need to do? ● Consistent File Layout ● Separate out functionality ● Make things more testable
  27. 27. 27 Clean up our file structure
  28. 28. 28 Break up that big file ● File for bootstrapping the app ● File for routes ● File for running the app
  29. 29. 29 web/index.php require_once __DIR__ . '/../vendor/autoload.php'; $app = new SilexApplication(); require_once __DIR__ . '/../app/bootstrap.php'; require_once __DIR__ . '/../app/routes.php'; $app->run();
  30. 30. 30 app/bootstrap.php $config = include_once 'config/config.php'; $app['config'] = $config; $app->register(new SilexProviderTwigServiceProvider(), array( 'twig.path' => $app['config']['template_path'], )); $app->register(new SilexProviderFormServiceProvider()); $app->register(new SilexProviderTranslationServiceProvider());
  31. 31. 31 app/routes.php $app->get('/', function() use ($app) {/*...*/}); $app->get('/about, function() use ($app) {/*...*/}); $app->match('/contact', function(Request $request) use ($app) { $form = $app['form.factory']->createBuilder('form') ->add('name') ->add('email') ->getForm() ; $form->handleRequest($request); if($form->isValid()) { $data = $form->getData(); // Mail it } return $app['twig']->render('contact.html.twig', array('form' => $form->createView())); })->method('GET|POST'); $app->get('/services', function() use ($app) {/*..});
  32. 32. 32 Service Providers
  33. 33. 33 For Services ● Implement SilexServiceProviderInterface ● Implement boot() and register()
  34. 34. 34 For Controllers ● Implement SilexControllerProviderInterface ● Implement connect()
  35. 35. 35 Sample Controller use SilexApplication; use SilexControllerProviderInterface; class BlogController implements ControllerProviderInterface { public function connect(Application $app) { $controllers = $app['controllers_factory']; $controllers->get('/', array($this, 'index')); $controllers->get('/inline', function() use ($app) { /* Logic Here */ }); } protected function index(Application $app) { /* Logic Here */ } } $app->mount('/blog', new BlogController());
  36. 36. 36 Controllers as Services ● Ships with Silex ● Allows attaching objects to routes ● Favors dependency injection ● Framework Agnostic
  37. 37. 37 Create our Object // src/MyApp/Controller/IndexController.php namespace MyAppController; use SilexApplication; use SymfonyComponentHttpFoundationRequest; class IndexController { public function indexAction(Application $app) { return $app['twig']->render('Index/index.html.twig'); } public function aboutAction(Application $app) { /* … */ } public function servicesAction(Application $app) { /* … */ } public function contactAction(Application $app) { /* … */ } }
  38. 38. 38 Register Controllers as Services $config = include_once 'config/config.php'; $app['config'] = $config; $app->register(new SilexProviderTwigServiceProvider(), array( 'twig.path' => $app['config']['template_path'], )); $app->register(new SilexProviderFormServiceProvider()); $app->register(new SilexProviderTranslationServiceProvider()); $app['controller.index'] = $app->share(function() use ($app) { return new MyAppControllerIndexController(); });
  39. 39. 39 Register our routes $app->get('/', 'controller.index:indexAction')->bind('homepage'); $app->get('/about', 'controller.index:aboutAction')->bind('about'); $app->get('/services', 'controller.index:servicesAction')->bind('services'); $app->match('/contact', 'controller.index:contactAction')->bind('contact')->method('GET|POST');
  40. 40. 40 A Little Planning goes a Long Way
  41. 41. 41 Questions?
  42. 42. 42 Thanks! ● http://joind.in/talk/view/12080 ● @dragonmantank ● chris@ctankersley.com

×