i using symfony's 3.1 routing component standalone component.
i wish debug routes.
according this: http://symfony.com/doc/current/routing/debug.html
this done running following command:
php bin/console debug:router
although trivial project running full symfony framework, how run when using router component standalone module?
i'd have posted comment not enough reputation..
anyway, should try require debug component in project in order use it:
$ composer require symfony/debug
answer update
okay, i've done research , testing, , got router debug command working. however, i'm still using 2 symfony components, console , config, i'm sure further searches can avoid config one.
i've created brand new project:
$ composer init $ composer require symfony/routing $ composer require symfony/console $ composer require symfony/config
don't forget autoload source code in composer.json:
{ "name": "lolmx/test", "require": { "php": "^5.6", "symfony/console": "^3.1", "symfony/routing": "^3.1", "symfony/config": "^3.1" }, "autoload": { "psr-0": { "": "src/" } } }
then $ composer install
.
create console file in project directory $ touch bin/console
, , write it:
<?php // include composer autoloader require_once __dir__."/../vendor/autoload.php"; // use statements use symfony\component\config\filelocator; use symfony\component\console\application; use symfony\component\routing\router; use symfony\component\routing\requestcontext; use symfony\component\routing\loader\phpfileloader; use appbundle\command\myrouterdebugcommand; $context = new requestcontext(); $locator = new filelocator(array(__dir__)); // needed symfony/config $router = new router( new phpfileloader($locator), // , class depends upon '../src/appbundle/routes.php', array(), $context ); $app = new application(); $app->add(new myrouterdebugcommand(null, $router)); $app->run(); ?>
i instantiate router, give command, , add command console application.
here routes.php looks like:
// src/appbundle/routes.php <?php use symfony\component\routing\routecollection; use symfony\component\routing\route; $collection = new routecollection(); $collection->add('name', new route("/myroute", array(), array(), array(), "myhost", array('http', 'https'), array('get', 'put'))); // more routes added here return $collection;
now let's write command class itself:
<?php namespace appbundle\command; use appbundle\descriptor\descriptorhelper; use appbundle\descriptor\textdescriptor; use symfony\component\console\command\command; use symfony\component\console\input\inputargument; use symfony\component\console\input\inputinterface; use symfony\component\console\input\inputoption; use symfony\component\console\output\outputinterface; use symfony\component\console\style\symfonystyle; use symfony\component\routing\router; use symfony\component\routing\routerinterface; use symfony\component\routing\route; class myrouterdebugcommand extends command { private $router; public function __construct($name = null, router $router) { parent::__construct($name); $this->router = $router; } /** * {@inheritdoc} */ public function isenabled() { if (is_null($this->router)) { return false; } if (!$this->router instanceof routerinterface) { return false; } return parent::isenabled(); } /** * {@inheritdoc} */ protected function configure() { $this ->setname('debug:router') ->setdefinition(array( new inputargument('name', inputargument::optional, 'a route name'), new inputoption('show-controllers', null, inputoption::value_none, 'show assigned controllers in overview'), new inputoption('format', null, inputoption::value_required, 'the output format (txt, xml, json, or md)', 'txt'), new inputoption('raw', null, inputoption::value_none, 'to output raw route(s)'), )) ->setdescription('displays current routes application') ->sethelp(<<<'eof' <info>%command.name%</info> displays configured routes: <info>php %command.full_name%</info> eof ) ; } /** * {@inheritdoc} * * @throws \invalidargumentexception when route not exist */ protected function execute(inputinterface $input, outputinterface $output) { $io = new symfonystyle($input, $output); $name = $input->getargument('name'); $helper = new descriptorhelper(); if ($name) { $route = $this->router->getroutecollection()->get($name); if (!$route) { throw new \invalidargumentexception(sprintf('the route "%s" not exist.', $name)); } $this->convertcontroller($route); $helper->describe($io, $route, array( 'format' => $input->getoption('format'), 'raw_text' => $input->getoption('raw'), 'name' => $name, 'output' => $io, )); } else { $routes = $this->router->getroutecollection(); foreach ($routes $route) { $this->convertcontroller($route); } $helper->describe($io, $routes, array( 'format' => $input->getoption('format'), 'raw_text' => $input->getoption('raw'), 'show_controllers' => $input->getoption('show-controllers'), 'output' => $io, )); } } private function convertcontroller(route $route) { $nameparser = new textdescriptor(); if ($route->hasdefault('_controller')) { try { $route->setdefault('_controller', $nameparser->build($route->getdefault('_controller'))); } catch (\invalidargumentexception $e) { } } } }
imagine you're using default descriptor helper use symfony\component\console\descriptor\descriptorhelper
$ php bin/console debug:router
will end wonderful error:
[symfony\component\console\exception\invalidargumentexception] object of type "symfony\component\routing\routecollection" not describable.
okay, need create our custom descriptorhelper. first implements interface
<?php namespace appbundle\descriptor; use symfony\component\console\descriptor\descriptorinterface; use symfony\component\console\output\outputinterface; use symfony\component\routing\route; use symfony\component\routing\routecollection; abstract class descriptor implements descriptorinterface { /** * @var outputinterface */ protected $output; /** * {@inheritdoc} */ public function describe(outputinterface $output, $object, array $options = array()) { $this->output = $output; switch (true) { case $object instanceof routecollection: $this->describeroutecollection($object, $options); break; case $object instanceof route: $this->describeroute($object, $options); break; case is_callable($object): $this->describecallable($object, $options); break; default: throw new \invalidargumentexception(sprintf('object of type "%s" not describable.', get_class($object))); } } /** * returns output. * * @return outputinterface output */ protected function getoutput() { return $this->output; } /** * writes content output. * * @param string $content * @param bool $decorated */ protected function write($content, $decorated = false) { $this->output->write($content, false, $decorated ? outputinterface::output_normal : outputinterface::output_raw); } /** * describes inputargument instance. * * @param routecollection $routes * @param array $options */ abstract protected function describeroutecollection(routecollection $routes, array $options = array()); /** * describes inputoption instance. * * @param route $route * @param array $options */ abstract protected function describeroute(route $route, array $options = array()); /** * describes callable. * * @param callable $callable * @param array $options */ abstract protected function describecallable($callable, array $options = array()); /** * formats value string. * * @param mixed $value * * @return string */ protected function formatvalue($value) { if (is_object($value)) { return sprintf('object(%s)', get_class($value)); } if (is_string($value)) { return $value; } return preg_replace("/\n\s*/s", '', var_export($value, true)); } /** * formats parameter. * * @param mixed $value * * @return string */ protected function formatparameter($value) { if (is_bool($value) || is_array($value) || (null === $value)) { $jsonstring = json_encode($value); if (preg_match('/^(.{60})./us', $jsonstring, $matches)) { return $matches[1].'...'; } return $jsonstring; } return (string) $value; } }
then override default descriptorhelper register our descriptor
<?php namespace appbundle\descriptor; use symfony\component\console\helper\descriptorhelper basedescriptorhelper; class descriptorhelper extends basedescriptorhelper { /** * constructor. */ public function __construct() { $this ->register('txt', new textdescriptor()) ; } }
and finally, implements our descriptor
<?php namespace appbundle\descriptor; use symfony\component\console\helper\table; use symfony\component\routing\route; use symfony\component\routing\routecollection; class textdescriptor extends descriptor { /** * {@inheritdoc} */ protected function describeroutecollection(routecollection $routes, array $options = array()) { $showcontrollers = isset($options['show_controllers']) && $options['show_controllers']; $tableheaders = array('name', 'method', 'scheme', 'host', 'path'); if ($showcontrollers) { $tableheaders[] = 'controller'; } $tablerows = array(); foreach ($routes->all() $name => $route) { $row = array( $name, $route->getmethods() ? implode('|', $route->getmethods()) : 'any', $route->getschemes() ? implode('|', $route->getschemes()) : 'any', '' !== $route->gethost() ? $route->gethost() : 'any', $route->getpath(), ); if ($showcontrollers) { $controller = $route->getdefault('_controller'); if ($controller instanceof \closure) { $controller = 'closure'; } elseif (is_object($controller)) { $controller = get_class($controller); } $row[] = $controller; } $tablerows[] = $row; } if (isset($options['output'])) { $options['output']->table($tableheaders, $tablerows); } else { $table = new table($this->getoutput()); $table->setheaders($tableheaders)->setrows($tablerows); $table->render(); } } /** * {@inheritdoc} */ protected function describeroute(route $route, array $options = array()) { $tableheaders = array('property', 'value'); $tablerows = array( array('route name', isset($options['name']) ? $options['name'] : ''), array('path', $route->getpath()), array('path regex', $route->compile()->getregex()), array('host', ('' !== $route->gethost() ? $route->gethost() : 'any')), array('host regex', ('' !== $route->gethost() ? $route->compile()->gethostregex() : '')), array('scheme', ($route->getschemes() ? implode('|', $route->getschemes()) : 'any')), array('method', ($route->getmethods() ? implode('|', $route->getmethods()) : 'any')), array('requirements', ($route->getrequirements() ? $this->formatrouterconfig($route->getrequirements()) : 'no custom')), array('class', get_class($route)), array('defaults', $this->formatrouterconfig($route->getdefaults())), array('options', $this->formatrouterconfig($route->getoptions())), ); $table = new table($this->getoutput()); $table->setheaders($tableheaders)->setrows($tablerows); $table->render(); } /** * {@inheritdoc} */ protected function describecallable($callable, array $options = array()) { $this->writetext($this->formatcallable($callable), $options); } /** * @param array $config * * @return string */ private function formatrouterconfig(array $config) { if (empty($config)) { return 'none'; } ksort($config); $configasstring = ''; foreach ($config $key => $value) { $configasstring .= sprintf("\n%s: %s", $key, $this->formatvalue($value)); } return trim($configasstring); } /** * @param callable $callable * * @return string */ private function formatcallable($callable) { if (is_array($callable)) { if (is_object($callable[0])) { return sprintf('%s::%s()', get_class($callable[0]), $callable[1]); } return sprintf('%s::%s()', $callable[0], $callable[1]); } if (is_string($callable)) { return sprintf('%s()', $callable); } if ($callable instanceof \closure) { return '\closure()'; } if (method_exists($callable, '__invoke')) { return sprintf('%s::__invoke()', get_class($callable)); } throw new \invalidargumentexception('callable not describable.'); } /** * @param string $content * @param array $options */ private function writetext($content, array $options = array()) { $this->write( isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : true ); } }
now writing $ php bin/console debug:router
output
------ --------- ------------ -------- ---------- name method scheme host path ------ --------- ------------ -------- ---------- name get|put http|https myhost /myroute ------ --------- ------------ -------- ----------
i dived symfony source code find of this, , different files are/may snippets of code symfony, symfony routing, console , framework-bundle.
Comments
Post a Comment