Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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)

Slide 3

Slide 3 text

joind.in / 7059 phpDocumentor What is going to be covered? ➔ Introduction to Symfony Components ➔ Timeline of phpDocumentor2: Components ➔ Autoloader ➔ Console ➔ Finder ➔ EventDispatcher ➔ Twig

Slide 4

Slide 4 text

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.”

Slide 5

Slide 5 text

joind.in / 7059 phpDocumentor Components

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

joind.in / 7059 phpDocumentor Installing { "require": { "symfony/config": "2.*" } } $ pear channel-discover pear.symfony.com $ pear install symfony2/config Composer Pear

Slide 9

Slide 9 text

joind.in / 7059 phpDocumentor

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

joind.in / 7059 phpDocumentor First version

Slide 12

Slide 12 text

joind.in / 7059 phpDocumentor Later

Slide 13

Slide 13 text

joind.in / 7059 phpDocumentor Stuck on PHP 5.2.6

Slide 14

Slide 14 text

joind.in / 7059 phpDocumentor Introducing plugins

Slide 15

Slide 15 text

joind.in / 7059 phpDocumentor Moving to PHP 5.3.3 ➔ Faster performance ➔ Enabled Symfony2 Components ➔ Namespaces ➔ PSR-0 Compatibility

Slide 16

Slide 16 text

joind.in / 7059 phpDocumentor Missing a lightweight framework

Slide 17

Slide 17 text

joind.in / 7059 phpDocumentor Missing a lightweight framework

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

joind.in / 7059 phpDocumentor Minimal CLI Application command(new \Cilex\Command\GreetCommand()); $app->run(); 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 : '')); } }

Slide 20

Slide 20 text

joind.in / 7059 phpDocumentor Cilex

Slide 21

Slide 21 text

joind.in / 7059 phpDocumentor Now with Cilex

Slide 22

Slide 22 text

joind.in / 7059 phpDocumentor Components Class Loader

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

joind.in / 7059 phpDocumentor Installing { "require": { "symfony/class-loader": "2.*" } } $ pear channel-discover pear.symfony.com $ pear install pear.symfony.com/ClassLoader Composer Pear

Slide 25

Slide 25 text

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();

Slide 26

Slide 26 text

joind.in / 7059 phpDocumentor Components Console

Slide 27

Slide 27 text

joind.in / 7059 phpDocumentor What does it do? ➔ Enables Commands ➔ Provides default list command ➔ Provides default help command ➔ Interactive Commands ➔ Testability

Slide 28

Slide 28 text

joind.in / 7059 phpDocumentor Installing { "require": { "symfony/console": "2.*" } } $ pear channel-discover pear.symfony.com $ pear install pear.symfony.com/Console Composer Pear

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

joind.in / 7059 phpDocumentor Creating a command (with Cilex) 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 : '')); } }

Slide 32

Slide 32 text

joind.in / 7059 phpDocumentor Creating a command (without Cilex) 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 : '')); } }

Slide 33

Slide 33 text

joind.in / 7059 phpDocumentor Let's pause for a moment http://www.flickr.com/photos/nicsuzor/2554668884

Slide 34

Slide 34 text

joind.in / 7059 phpDocumentor FileSet

Slide 35

Slide 35 text

joind.in / 7059 phpDocumentor Gathering files

Slide 36

Slide 36 text

joind.in / 7059 phpDocumentor Components Finder

Slide 37

Slide 37 text

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`

Slide 38

Slide 38 text

joind.in / 7059 phpDocumentor Installing { "require": { "symfony/finder": "2.*" } } $ pear channel-discover pear.symfony.com $ pear install pear.symfony.com/Finder Composer Pear

Slide 39

Slide 39 text

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()); } );

Slide 40

Slide 40 text

joind.in / 7059 phpDocumentor Plugins (revisited)

Slide 41

Slide 41 text

joind.in / 7059 phpDocumentor Gathering files

Slide 42

Slide 42 text

joind.in / 7059 phpDocumentor Components EventDispatcher

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

joind.in / 7059 phpDocumentor Installing { "require": { "symfony/event-dispatcher": "2.*" } } $ pear channel-discover pear.symfony.com $ pear install pear.symfony.com/EventDispatcher Composer Pear

Slide 45

Slide 45 text

joind.in / 7059 phpDocumentor Events ➔ Have a name (eg. event.log) ➔ Are objects too ➔ Are used to: ➔ Trigger listeners ➔ Transfer state

Slide 46

Slide 46 text

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 );

Slide 47

Slide 47 text

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 );

Slide 48

Slide 48 text

joind.in / 7059 phpDocumentor Twig Templates

Slide 49

Slide 49 text

joind.in / 7059 phpDocumentor Using Twig to generate artifacts

Slide 50

Slide 50 text

joind.in / 7059 phpDocumentor Components Twig

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

joind.in / 7059 phpDocumentor Installing { "require": { "twig/twig": "1.*" } } $ pear channel-discover pear.twig-project.org $ pear install twig/Twig Composer Pear

Slide 53

Slide 53 text

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)) ) );

Slide 54

Slide 54 text

joind.in / 7059 phpDocumentor Example template My Webpage

My Webpage

{{ a_variable }}

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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