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

How to build Console Applications @ phplx

How to build Console Applications @ phplx

In some cases you feel the need to have some specific command-line commands for deployment, testing some code or do any other specific task.

The Symfony2 Console component is a tool that gives you in a simple and easy way to build a console application with your own command-line commands.

This talk is an introduction to the Console component and a walkthrough on how to use it in an effective way.

0fe2d959c89cf2d9de497a237c4ea99d?s=128

Daniel Gomes

October 17, 2013
Tweet

More Decks by Daniel Gomes

Other Decks in Programming

Transcript

  1. Daniel Gomes @danielcsgomes October 17, 2013 icon by Austin Andrews

    © http://thenounproject.com/Templarian How to Build Console Applications
  2. • Software Engineer @ GuestCentric Systems • ZCE PHP 5.3,

    OCP MySQL 5 Developer, CSM • @danielcsgomes about me
  3. Lots of scripts Too many di!erent tools Tedious and boring

  4. Centralize your tools Have interactive tools Easy to use by

    everyone Usage manual what about
  5. Meet symfony Console Component

  6. • Application • Command • Input • Output • Helpers

    • Events • Formatters console component toolset
  7. APPLICATION COMMAND A COMMAND B COMMAND C plug-in & run

  8. { "require": { "symfony/console": "2.3.*@dev" } } install via composer

    zero dependencies
  9. <?php // app.php require_once __DIR__ . '/vendor/autoload.php'; use Symfony\Component\Console\Application; $app

    = new Application('Clear Cache App', '0.0.1'); $app->run(); Bootstrapping the application
  10. $ php app.php

  11. basic command

  12. // Command/CacheClearCommand.php namespace DCSG\Command; use Symfony\Component\Console\Command\Command; class CacheClearCommand extends Command

    { protected function configure() { $this ->setName('cache:clear') ->setDescription('Clears Application Cache') ->setHelp(<<<EOF The <info>cache:clear</info> command removes all files inside the <info>cache directory</info>. EOF ); } // ... }
  13. <?php require_once __DIR__ . '/vendor/autoload.php'; use DCSG\Command\CacheClearCommand; use Symfony\Component\Console\Application; $app

    = new Application('Clear Cache App', '0.0.1'); $app->add(new CacheClearCommand()); $app->run(); adding to application
  14. $ php app.php

  15. $ php app.php help cache:clear

  16. add arguments

  17. • ordered • input type: • optional • required •

    array arguments are:
  18. // Command/CacheClearCommand.php $this->addArgument( 'directory', // name InputArgument::OPTIONAL, // input type

    'The cache directory', // description './cache' // default value ); adding an argument
  19. add options

  20. • unordered • input type: • optional • required •

    array • none (no input) options are:
  21. // CacheClearCommand.php $this->addOption( 'force', // name 'f', // shortname InputOption::VALUE_NONE,

    // input type 'Forces to clear the cache.' // description ); adding an option
  22. add logic

  23. // Command/CacheClearCommand.php protected function execute( InputInterface $input, OutputInterface $output) {

    // Logic here } execute the command
  24. // Command/CacheClearCommand.php protected function execute(InputInterface $input, OutputInterface $output) { //

    Reads the Input $directory = $input->getArgument('directory'); // Removes all files inside the directory $counter = 0; $files = glob($cacheDir . '/*'); foreach ($files as $file) { if (is_file($file)) { unlink($file); $counter++; } } // Writes the Output $output->writeln(sprintf('Cache cleared. Removed %d files.', $counter)); }
  25. always validate the input

  26. // Command/CacheClearCommand.php // Reads the Input $directory = $input->getArgument('directory'); //

    Validate the argument input if (false === $cacheDir = realpath($directory)) { throw new \InvalidArgumentException('Directory does't exist.'); } // InputOption::VALUE_NONE does not need to be validate // since it does not accept parameters // in this case will return true or false $force = $input->getOption('force');
  27. $ php app.php cache:clear /foo/bar

  28. interact with the user

  29. • Dialog helper • Formatter helper • Progress helper •

    Table helper
  30. dialog HELPER

  31. // Symfony/Component/Console/Helper/DialogHelper.php public function select(...){...} public function ask(...){...} public function

    askConfirmation(...){...} public function askHiddenResponse(...){...} public function askAndValidate(...){...} public function askHiddenResponseAndValidate (...){...}
  32. // Command/CacheClearCommand.php // ... // Ask the user if it's

    the right directory $dialog = $this->getHelperSet()->get('dialog'); $answer = $dialog->askConfirmation( $output, sprintf('Remove all files in: %s ? (no)', $cacheDir), false // default value ); // ... Remove all files in: ./cache ? (no) yes OUTPUT
  33. OUTPUT // examples/Helpers/select.php $colors = array('Red', 'Blue', 'Green', 'Yellow'); //

    Ask the user the favorite color $dialog = $this->getHelperSet()->get('dialog'); $colorIndex = $dialog->select( $output, 'What color do you like?', $colors ); // Writes the Output $output->writeln( sprintf('The color you like is <info>%s</info>.', $colors[$colorIndex]) );
  34. formatter HELPER

  35. OUTPUT $formatter = $this->getHelperSet()->get('formatter'); $formattedLine = $formatter->formatSection( 'SomeSection', 'Here is

    some message related to that section' ); $output->writeln($formattedLine); $msg = array('Something went wrong'); $formattedBlock = $formatter->formatBlock($msg, 'error'); $output->writeln($formattedBlock); $msg = array('Custom Colors'); $formattedBlock = $formatter->formatBlock($msg, 'bg=blue;fg=white'); $output->writeln($formattedBlock);
  36. progress helper

  37. 05/50 [== ] 10% 25/50 [============= ] 50% 50/50 [============================]

    100% $progress = $this->getHelperSet()->get('progress'); $progress->start($output, 50); $i = 0; while ($i++ < 50) { $progress->advance(); } $progress->finish(); OUTPUT
  38. table helper

  39. $table = $this->getHelperSet()->get('table'); $table ->setHeaders(array('Color', 'HEX')) ->setRows( array( array('Red', '#ff0000'),

    array('Blue', '#0000ff'), array('Green', '#008000'), array('Yellow', '#ffff00') ) ); $table->render($output); OUTPUT
  40. command events

  41. • command - before run • exception - on exceptions

    • terminate - before return exit code the events
  42. testing Commands

  43. public function testCacheClear() { $application = new Application(); $application->add(new CacheClearCommand());

    // Mock the DialogHelper to skip interact // ... $command = $application->find('cache:clear'); // Add Mock to command $commandTester = new CommandTester($command); $commandTester->execute(array( 'command' => 'cache:clear', 'directory' => './cache' )); $this->assertFileNotExists($filename); }
  44. // Symfony/Component/Console/Tester/CommandTester.php class CommandTester { private $command; private $input; private

    $output; public function __construct(Command $command){..} public function execute(array $input, array $options=array()){..} public function getDisplay($normalize = false){..} public function getInput(){..} public function getOutput(){..} } command tester
  45. $ ./vendor/bin/phpunit

  46. dependency injection in your application

  47. Application Container CacheClearCommand FileSystem Finder Services setContainer(...) getContainer() addCommand() ...

    Other Commands
  48. namespace Symfony\Component\DependencyInjection; interface ContainerAwareInterface { public function setContainer( ContainerInterface $container

    = null ); } container aware interface
  49. // DCSG/Application.php class Application extends BaseApplication implements ContainerAwareInterface { private

    $container; public function setContainer(..){..} public function getContainer(){..} } implement in the application
  50. // DCSG/Command/CacheClearCommand.php // ... $container = $this->getApplication()->getContainer(); $fs = $container->get('filesystem');

    $finder = $container->get('finder'); $files = $finder->in($cacheDir); $fs->remove($files); // ... usage in the command
  51. http://goo.gl/h0Xcfe http://symfony.com/doc/current/components/process.html Long running processes resources http://symfony.com/doc/current/components/console/index.html http://symfony.com/doc/current/cookbook/console/index.html http://symfony.com/doc/current/cookbook/service_container/index.html http://symfony.com/doc/current/components/dependency_injection/index.html

    Symfony2 Docs Cron jobs http://www.cyberciti.biz/faq/how-do-i-add-jobs-to-cron-under-linux-or-unix-oses/ Source Code https://github.com/danielcsgomes/phplx-how-to-build-console-app https://github.com/symfony/Console
  52. @danielcsgomes | me@danielcsgomes.com | http://danielcsgomes.com Photo by Jian Awe ©

    http://www."ickr.com/photos/qqjawe/6511141237 Please give feedback: https://joind.in/9615 Questions?