$30 off During Our Annual Pro Sale. View details »

Symfony2's descend into phpDocumentor2

Mike van Riel
September 14, 2012

Symfony2's descend into phpDocumentor2

Mike van Riel

September 14, 2012
Tweet

More Decks by Mike van Riel

Other Decks in Technology

Transcript

  1. joind.in / 7059 phpDocumentor A Symfony Components use-case by Mike

    van Riel
  2. joind.in / 7059 phpDocumentor Who am I? Mike van Riel

    ➔ @mvriel ➔ Lead Developer for phpDocumentor 2 ➔ Core Developer for Cilex ➔ Contributor for many others ➔ Foster-father of 2 (dogs)
  3. joind.in / 7059 phpDocumentor What is going to be covered?

    ➔ Introduction to Symfony Components ➔ Timeline of phpDocumentor2: Components ➔ Autoloader ➔ Console ➔ Finder ➔ EventDispatcher ➔ Twig
  4. joind.in / 7059 phpDocumentor “With this presentation I intend to

    inspire you to reduce the amount of code you maintain, and use Symfony Components to help you achieve that.”
  5. joind.in / 7059 phpDocumentor Components

  6. joind.in / 7059 phpDocumentor Benefits Less maintenance Reliable Easy To

    use ➔ Unit-tested ➔ Peer- reviewed ➔ Widely used ➔ Community Support ➔ Automatic updates ➔ Less code to maintain
  7. joind.in / 7059 phpDocumentor Which components are there? ➔ Browserkit

    ➔ Classloader ➔ Config ➔ Console ➔ CssSelector ➔ Dependency Injection ➔ DomCrawler ➔ Event Dispatcher ➔ Finder ➔ Form ➔ Http Foundation ➔ HttpKernel ➔ Locale ➔ Process ➔ Routing ➔ Security ➔ Serializer ➔ Templating ➔ Translation ➔ Validator ➔ Yaml
  8. joind.in / 7059 phpDocumentor Installing { "require": { "symfony/config": "2.*"

    } } $ pear channel-discover pear.symfony.com $ pear install symfony2/config Composer Pear
  9. joind.in / 7059 phpDocumentor

  10. joind.in / 7059 phpDocumentor “phpDocumentor did not use Symfony”

  11. joind.in / 7059 phpDocumentor First version

  12. joind.in / 7059 phpDocumentor Later

  13. joind.in / 7059 phpDocumentor Stuck on PHP 5.2.6

  14. joind.in / 7059 phpDocumentor Introducing plugins

  15. joind.in / 7059 phpDocumentor Moving to PHP 5.3.3 ➔ Faster

    performance ➔ Enabled Symfony2 Components ➔ Namespaces ➔ PSR-0 Compatibility
  16. joind.in / 7059 phpDocumentor Missing a lightweight framework

  17. joind.in / 7059 phpDocumentor Missing a lightweight framework

  18. joind.in / 7059 phpDocumentor Cilex was born Class Loader Console

    Pimple Cilex
  19. joind.in / 7059 phpDocumentor Minimal CLI Application <?php require_once __DIR__

    . '/cilex.phar'; $app = new \Cilex\Application('Cilex'); $app->command(new \Cilex\Command\GreetCommand()); $app->run(); <?php namespace Cilex\Command; use Symfony\Component\Console\Input\InputArgument, Symfony\Component\Console\Input\InputInterface, Symfony\Component\Console\Input\InputOption, Symfony\Component\Console\Output\OutputInterface; class GreetCommand extends Command { protected function configure() { $this->setName('demo:greet') ->setDescription('Greet someone') ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?') } protected function execute(InputInterface $input, OutputInterface $output) { $name = $input->getArgument('name'); $output->writeln('Hello'.($name ? ' '.$name : '')); } }
  20. joind.in / 7059 phpDocumentor Cilex

  21. joind.in / 7059 phpDocumentor Now with Cilex

  22. joind.in / 7059 phpDocumentor Components Class Loader

  23. joind.in / 7059 phpDocumentor What does it do? ➔ Autoloader

    ➔ PSR-0 compatible ➔ PEAR compatible ➔ Can use classmaps for extra performance ➔ Can use APC to cache
  24. joind.in / 7059 phpDocumentor Installing { "require": { "symfony/class-loader": "2.*"

    } } $ pear channel-discover pear.symfony.com $ pear install pear.symfony.com/ClassLoader Composer Pear
  25. joind.in / 7059 phpDocumentor Example $loader = new UniversalClassLoader(); $loader->registerNamespaces(array(

    'Symfony' => __DIR__.'/../vendor/symfony/symfony/src', 'Monolog' => __DIR__.'/../vendor/monolog/monolog/src', )); $loader->register();
  26. joind.in / 7059 phpDocumentor Components Console

  27. joind.in / 7059 phpDocumentor What does it do? ➔ Enables

    Commands ➔ Provides default list command ➔ Provides default help command ➔ Interactive Commands ➔ Testability
  28. joind.in / 7059 phpDocumentor Installing { "require": { "symfony/console": "2.*"

    } } $ pear channel-discover pear.symfony.com $ pear install pear.symfony.com/Console Composer Pear
  29. joind.in / 7059 phpDocumentor Commands ➔ a single activity of

    a command line application ➔ Example: `phpdoc template:list` ➔ May have options ➔ Example: --help ➔ May have one or more arguments ➔ Example: `scrybe manual:to-html file1.rst file2.rst` ➔ Can be interactive ➔ Question-based instead of option-based
  30. joind.in / 7059 phpDocumentor Example from phpDocumentor $console = new

    Console\Application($name, $version); protected function addCommandsForProjectNamespace() { $this->command( new \phpDocumentor\Command\Project\ParseCommand() ); $this->command( new \phpDocumentor\Command\Project\RunCommand() ); $this->command( new \phpDocumentor\Command\Project\TransformCommand() ); } Convenience method provided by Cilex $console->add(new GreetCommand()); $console->run(); without Cilex
  31. joind.in / 7059 phpDocumentor Creating a command (with Cilex) <?php

    namespace Cilex\Command; use Symfony\Component\Console\Input\InputArgument, Symfony\Component\Console\Input\InputInterface, Symfony\Component\Console\Input\InputOption, Symfony\Component\Console\Output\OutputInterface; class GreetCommand extends Command { protected function configure() { $this->setName('demo:greet') ->setDescription('Greet someone') ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?') } protected function execute(InputInterface $input, OutputInterface $output) { $name = $input->getArgument('name'); $output->writeln('Hello'.($name ? ' '.$name : '')); } }
  32. joind.in / 7059 phpDocumentor Creating a command (without Cilex) <?php

    namespace My\Application\Command; use Symfony\Component\Console\Input\InputArgument, Symfony\Component\Console\Input\InputInterface, Symfony\Component\Console\Input\InputOption, Symfony\Component\Console\Output\OutputInterface, Symfony\Component\Console\Command\Command; class GreetCommand extends Command { protected function configure() { $this->setName('demo:greet') ->setDescription('Greet someone') ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?') } protected function execute(InputInterface $input, OutputInterface $output) { $name = $input->getArgument('name'); $output->writeln('Hello'.($name ? ' '.$name : '')); } }
  33. joind.in / 7059 phpDocumentor Let's pause for a moment http://www.flickr.com/photos/nicsuzor/2554668884

  34. joind.in / 7059 phpDocumentor FileSet

  35. joind.in / 7059 phpDocumentor Gathering files

  36. joind.in / 7059 phpDocumentor Components Finder

  37. joind.in / 7059 phpDocumentor What does it do? ➔ Finds

    files and folders ➔ Returns them as SplFileInfo objects ➔ Provides a DSL to retrieve a specific set of files ➔ Highly configurable and filterable ➔ Can use streams to find files in ➔ Example: `\Zend_Service_Amazon_S3`
  38. joind.in / 7059 phpDocumentor Installing { "require": { "symfony/finder": "2.*"

    } } $ pear channel-discover pear.symfony.com $ pear install pear.symfony.com/Finder Composer Pear
  39. joind.in / 7059 phpDocumentor Example from phpDocumentor $finder = new

    \Symfony\Component\Finder\Finder(); $finder ->files() ->in($path) ->name( '/\.('.implode('|', $this->allowed_extensions).')$/' ) ->ignoreDotFiles($this->getIgnoreHidden()) ->filter( function(\SplFileInfo $file) use ($patterns) { if (!$patterns) { return true; } // apply ignore list on path instead of file, finder // can't do that by default return !preg_match($patterns, $file->getPathname()); } );
  40. joind.in / 7059 phpDocumentor Plugins (revisited)

  41. joind.in / 7059 phpDocumentor Gathering files

  42. joind.in / 7059 phpDocumentor Components EventDispatcher

  43. joind.in / 7059 phpDocumentor What does it do? ➔ Allows

    a non-linear approach ➔ For example: hooks for a plugin ➔ Similar to: concepts from Aspect Oriented Programming ➔ Provide third-parties with controlled interaction ➔ Observer variant: Event Dispatcher pattern
  44. joind.in / 7059 phpDocumentor Installing { "require": { "symfony/event-dispatcher": "2.*"

    } } $ pear channel-discover pear.symfony.com $ pear install pear.symfony.com/EventDispatcher Composer Pear
  45. joind.in / 7059 phpDocumentor Events ➔ Have a name (eg.

    event.log) ➔ Are objects too ➔ Are used to: ➔ Trigger listeners ➔ Transfer state
  46. joind.in / 7059 phpDocumentor Stock example $listener = new AcmeListener();

    $dispatcher->addListener( 'foo.action', array($listener, 'onFooAction') ); use Symfony\Component\EventDispatcher\EventDispatcher; $dispatcher = new EventDispatcher(); $event = new FilterOrderEvent($order); $dispatcher->dispatch( StoreEvents::STORE_ORDER, $event );
  47. joind.in / 7059 phpDocumentor Example from phpDocumentor $this->event_dispatcher->addListener( $event->getDescription(), array($this,

    $method->getName()) ); * @phpdoc-event reflection.docblock.tag.export */ public function exportTag($data) { /** @var \phpDocumentor\Reflection\BaseReflector $subject */ $subject = $data->getSubject(); ... } $event = ..\Event\ExportDocBlockExtractionEvent::createInstance($this) ->setDocblock($this->doc_block) \phpDocumentor\Event\Dispatcher::getInstance()->dispatch( 'reflection.docblock-extraction.export', $event );
  48. joind.in / 7059 phpDocumentor Twig Templates

  49. joind.in / 7059 phpDocumentor Using Twig to generate artifacts

  50. joind.in / 7059 phpDocumentor Components Twig

  51. joind.in / 7059 phpDocumentor What does it do? ➔ Converts

    a template into any text format ➔ Is inspired on Jinja, the Python templating engine ➔ Provides a concise, readable interface
  52. joind.in / 7059 phpDocumentor Installing { "require": { "twig/twig": "1.*"

    } } $ pear channel-discover pear.twig-project.org $ pear install twig/Twig Composer Pear
  53. joind.in / 7059 phpDocumentor Example from phpDocumentor $base_extension = new

    \phpDocumentor\Plugin\Twig\Extension( $structure, $transformation ); $env->addExtension($base_extension); $env = new \Twig_Environment( new \Twig_Loader_Filesystem( $transformation->getTransformer()->getTemplatesPath().'/..' .DIRECTORY_SEPARATOR.$template_path ) ); file_put_contents( $destination, $environment->render( substr($transformation->getSource(), strlen($template_path)) ) );
  54. joind.in / 7059 phpDocumentor Example template <!DOCTYPE html> <html> <head>

    <title>My Webpage</title> </head> <body> <ul id="navigation"> {% for item in navigation %} <li> <a href="{{ item.href }}"> {{ item.caption }} </a> </li> {% endfor %} </ul> <h1>My Webpage</h1> {{ a_variable }} </body> </html>
  55. joind.in / 7059 phpDocumentor Conclusion ➔ Reduce the amount of

    LOC you need to maintain ➔ Use Components ➔ Build on the shoulders of giants ➔ It's easy
  56. joind.in / 7059 phpDocumentor Questions? ➔ Please rate this talk

    on http://joind.in/7059 ➔ More information can be found at: http://symfony.com/components ➔ You can follow me on twitter: @mvriel