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

Symfony components in the wild [SymfonyCon 2013]

Jakub Zalas
December 13, 2013

Symfony components in the wild [SymfonyCon 2013]

Symfony is a full-stack framework built on top of reusable components. Since those components are decoupled, they’re also successfully used with many open source projects, custom-built applications, other frameworks or even legacy applications needing an injection of up-to-date technology. The talk is an introduction to several Symfony components. It shows how easy it is to use them alone, integrated into a custom project and how components are used with existing open source applications.

Feedback on joind.in: https://joind.in/talk/view/10366

Jakub Zalas

December 13, 2013
Tweet

More Decks by Jakub Zalas

Other Decks in Programming

Transcript

  1. 0 100 200 300 400 500 600 700 Bundles Other

    Symfony Component based projects
  2. Fixing PHP Debug HttpFoundation Yaml Tools Filesystem Finder Process Stopwatch

    Web Framework Foundation HttpKernel Routing Templating Data Helpers Config OptionsResolver PropertyAccess Serializer Patterns DependencyInjection   EventDispatcher   I18n Intl + Icu Locale Translation Crawlers BrowserKit CssSelector DomCrawler Framework+ ClassLoader Console ExpressionLanguage Form Security Validator
  3. $expiresAt = new \DateTime('+1hour'); $expiresAt->setTimezone( new \DateTimeZone('UTC') ); $expires =

    $expresAt->format('D, d M Y H:i:s'); $expires.= ' GMT’; header('X-Event: SymfonyCon'); header('Cache-Control: public'); header('Expires: '.$expires); echo 'Hello!';
  4. // Somewhere in a controller $id = $request->query->get('id'); $date =

    $this->getPageUpdatedAtById($id); $response = new Response(); $response->setPublic(); $response->setLastModified($date); if ($response->isNotModified($request)) { return $response; } // else do heavy processing to render the page
  5. use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); $configuration = new \Proxy\Configuration(); $configuration->setBackend('nousefreak.be');

    $proxy = new \Proxy\Proxy(); $proxy->setConfiguration($configuration); $response = $proxy->proxy($request); $response->send(); nousefreak/proxy  
  6. protected function createResponse( GuzzleResponse $gResponse, Request $request ) { $response

    = new Response( $gResponse->getBody(), $gResponse->getStatusCode() ); foreach ($gResponse->getHeaderLines() as $header) { list($name, $value) = explode(':', $header, 2); $response->headers->set($name, $value); } return $this->prepareResponse($response, $request); } nousefreak/proxy  
  7. use Symfony\Component\Yaml\Yaml; $yaml = <<<YAML parameters: username: kuba password: 123123

    YAML; $data = Yaml::parse($yaml); var_dump($data); // array( // 'parameters' => array( // 'username' => 'kuba', // 'password' => '123123' // ) // )
  8. foo: &foo bar: ~ hello: cześć test: <<: *foo bar:

    true obj: !!php/object:O:8:"stdClass":1:{s: 5:"title";s:14:"Foo in the bar";}
  9. namespace Nelmio\Alice\Loader; use Symfony\Component\Yaml\Yaml as YamlParser; class Yaml extends Base

    { public function load($file) { ob_start(); $loader = $this; $includeWrapper = function () use ($file, $loader) { return include $file; }; $data = $includeWrapper(); if (true !== $data) { $yaml = ob_get_clean(); $data = YamlParser::parse($yaml); } // ... } } nelmio/alice  
  10. #!/usr/bin/env php <?php if (!@include __DIR__.'/../autoload.php') { die('You must set

    up the project dependencies'); } use Symfony\Component\Debug\Debug; Debug::enable(); $application = new Carew\Carew(); $application->run(); carew/carew  
  11. $printCallback = function ($type, $data) { printf('[%s] %s', $type, $data);

    }; $process = new Process( 'echo "Symfony"; sleep 2; echo "Con";' ); $process->start($printCallback); // [...] do other stuff while command is running $pid = $process->getPid(); // wait untill it finishes $process->wait();
  12. $server = new HttpServer\HttpServer( '/var/www', 'localhost', 8080 ); $server->start(); $contents

    = file_get_contents( 'http://localhost:8080/example.php' ); $server->stop(); robloach/h6pserver  
  13. class HttpServer extends PhpProcess { // ... public function start($callback

    = null) { if (false === $php = $this->executableFinder->find()) { throw new \RuntimeException('Unable to find PHP'); } $options = ' -S ' . $this->addr . ':' . $this->port; if (isset($this->documentRoot)) { $options .= ' -t ' . $this->documentRoot; } $this->setCommandLine($php . $options); parent::start($callback); } } robloach/h6pserver  
  14. Subjects   Listeners   Event  Dispatcher   Mailer  Listener  

    RegistraAon   Dispatcher   add  listener   registraAon.success   noAfy   registraAon.success   call   register  
  15. Subjects   Listeners   Event  Dispatcher   Mailer   Listener

      RegistraAon   Dispatcher   add  listener   registraAon.success   noAfy   registraAon.success   call   SMS   Listener   add  listener   registraAon.success   call   register  
  16. use Symfony\Component\EventDispatcher\GenericEvent; class Registration { // ... public function register($user)

    { // register the user ... // dispatch an event if registration was // successful $this->dispatcher->dispatch( 'registration.success', new GenericEvent($user) ); } }
  17. class MailerListener { private $mailer; private $twig; public function __construct(

    Mailer $mailer, TwigEngine $twig ) { $this->mailer = $mailer; $this->twig = $twig; } // ... }
  18. use Symfony\Component\EventDispatcher\GenericEvent; class MailerListener { // ... public function sendMail(GenericEvent

    $event) { $user = $event->getSubject(); $message = $this->createMessage($user) $this->mailer->send($message); } private function createMessage($user) { return $this->twig->render(/* */); } }
  19. use Symfony\Component\EventDispatcher\EventDispatcher; $mailerListener = new MailerListener($mailer, $twig); $smsListener = new

    SmsListener($smsGateway); $dispatcher = new EventDispatcher(); $dispatcher->addListener( 'registration.success', array($mailerListener, 'sendMail') ); $dispatcher->addListener( 'registration.success', array($smsListener, 'sendSms’) ); $registration = new Registration($dispatcher); $registration->register($user);
  20. use Phoebe\Connection; use Phoebe\Event\Event; $freenode = new Connection(); $freenode->setServerHostname('irc.freenode.net'); $freenode->setNickname('Phoebe2');

    $dispatcher = $freenode->getEventDispatcher(); $dispatcher->addListener( 'irc.received.001', function (Event $event) { $event->getWriteStream()->ircJoin('#symfony'); } ); $events->addSubscriber(new BeerPlugin()); sAl/phoebe  
  21. use Phoebe\Event\Event; use Phoebe\Plugin\PluginInterface; class BeerPlugin implements PluginInterface { public

    static function getSubscribedEvents() { return [ 'irc.received.PRIVMSG' => array('onMessage', 0) ]; } public function onMessage(Event $event) { $message = $event->getMessage(); if (!$message->matchText('/SymfonyCon/') { return; } $es = $event->getWriteStream(); $es->ircPrivmsg($message->getSource(), 'Hello!'); } } sAl/phoebe  
  22. <?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/..." ...> <services> <service id="http_client" class="HttpClient">

    <argument>%symfonycon.api.username%</argument> <argument>%symfonycon.api.key%</argument> </service> <service id="symfonycon.api" class="SymfonyCon"> <argument type="service" id="http_client" /> <call method="chooseEndpoint"> <argument>%symfonycon.api.endpoint%</argument> </call> <service> </services> </container>
  23. // BehatApplication protected function createContainer( InputInterface $input ) { $container

    = new ContainerBuilder(); $this->loadCoreExtension( $container, $this->loadConfiguration( $container, $input ) ); $container->compile(); return $container; } behat/behat  
  24. namespace PSS\Behat\Symfony2MockerExtension; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Behat\Behat\Extension\ExtensionInterface;

    class Extension implements ExtensionInterface { public function load( array $config, ContainerBuilder $container ) { $loader = new XmlFileLoader( $container, new FileLocator(__DIR__.'/services') ); $loader->load('core.xml'); } // ... } behat/behat  
  25. use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; $context = new RequestContext( '/hello/Poland', 'GET’

    ); $matcher = new UrlMatcher($routes, $context); $parameters = $matcher->match('/hello/Poland'); var_dump($parameters); // array( // 'controller' => 'HelloController', // 'name' => 'Poland', // '_route' => 'hello' // )
  26. use Ratchet\App; use Ratchet\Server\EchoServer; $app = new App('localhost', 8080); $app->route('/chat',

    new MyChat()); $app->route('/echo', new EchoServer(), ['*']); $app->run(); cboden/ratchet  
  27. echo $language->evaluate( 'life + universe + everything', array( 'life' =>

    10, 'universe' => 10, 'everything' => 22, ) ); // 42
  28. class Conference { public function getName() { return 'SymfonyCon'; }

    } echo $language->evaluate( 'c.getName()', array('c' => new Conference('SymfonyCon')) ); // SymfonyCon
  29. $language->register( 'reverse', function ($string) { if (!is_string($string)) { return $string;

    } return sprintf('strrev(%s)', $string); }, function ($arguments, $string) { if (!is_string($string)) { return $string; } return strrev($string); } ); echo $language->evaluate('reverse("SymfonyCon")');
  30. /** * @Route("/post/{id}") * @Method("GET") * @Cache(lastModified="post.getUpdatedAt()") * @ParamConverter("post", class="Sensio:Post")

    * @Security("has_role('ROLE_USER')") * @Template() * @MyResponseConverter("xml") */ public function showAction(Post $post) { return $post; } Annotation Driven Development
  31. /** * @Hateoas\Relation( * "self", * href = "expr('/api/users/' ~

    object.getId())" * ) */ class Post {} willdurand/hateoas  
  32. use BCC\EnumerableUtility\Collection; $values = new Collection(array(1, 2, 3)); $values->where(function($item) {

    return $item % 2; }); $values->select(array( 'i' => 'i * m', 'm' => 2, )); bcc/enumerable-­‐uAlity  
  33. Credits •  http://www.sxc.hu/photo/1223174 •  http://www.sxc.hu/photo/338038 •  http://www.sxc.hu/photo/13223 •  http://www.sxc.hu/photo/1092493 • 

    http://www.sxc.hu/photo/308460 •  http://www.sxc.hu/photo/1412072 •  http://www.sxc.hu/photo/771223 •  http://www.sxc.hu/photo/1178514 •  http://www.sxc.hu/photo/1379212 •  http://www.sxc.hu/photo/1432060 •  http://www.sxc.hu/photo/1115716