2016-08-01 1 views
1

Symfony의 3.1 라우팅 구성 요소를 독립 실행 형 구성 요소로 사용하고 있습니다.Symfony Routing을 독립 실행 형 구성 요소로 사용하여 경로를 디버깅하는 방법은 무엇입니까?

경로를 디버깅하고 싶습니다.

이에 따르면이 다음 명령을 실행하여 수행됩니다 http://symfony.com/doc/current/routing/debug.html

: 사용할 때 전체 심포니 프레임 워크를 실행하는 프로젝트에 대한 사소한하지만

php bin/console debug:router 

을 수행하는 방법 나는 그것을 실행 독립 실행 형 모듈로 라우터 구성 요소?

$ composer require symfony/debug 

을 어쨌든

내가 코멘트는 아니지만 충분히 명성을 게시 한 것

답변

2
..

, 당신은 그것을 사용하기 위해 프로젝트의 디버그 구성 요소를 필요로하는 것을 시도해야 대답 업데이트

좋아, 일부 다시 짓을했는지

검색 및 테스트를 마친 후 마침내 라우터 디버그 명령을 작동 시켰습니다. 그러나 콘솔과 설정 두 개의 symfony 구성 요소를 사용하고 있습니다. 그러나 추가 검색을 사용하면 설정 하나를 피할 수 있습니다.

나는 새로운 프로젝트를 만들었습니다

$ composer init 
$ composer require symfony/routing 
$ composer require symfony/console 
$ composer require symfony/config 

가 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/" 
     } 
    } 
} 

그런 $ composer install합니다.

프로젝트 디렉토리 $ touch bin/console에서 콘솔 파일을 만들고 그것을 쓰기 :

<?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__)); // I needed symfony/config for this 
$router = new Router(
    new PhpFileLoader($locator), // And this class depends upon too 
    '../src/AppBundle/Routes.php', 
    array(), 
    $context 
); 

$app = new Application(); 
$app->add(new MyRouterDebugCommand(null, $router)); 
$app->run(); 
?> 

난 그저, 내 라우터를 인스턴스화 내 명령을주고, 콘솔 응용 프로그램에 명령을 추가합니다. 여기 내 Routes.php이 모습

같은 : 이제

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

의 명령 클래스 자체 작성할 수 :

<?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 for an application') 
      ->setHelp(<<<'EOF' 
The <info>%command.name%</info> displays the configured routes: 
    <info>php %command.full_name%</info> 
EOF 
      ) 
     ; 
    } 

    /** 
    * {@inheritdoc} 
    * 
    * @throws \InvalidArgumentException When route does 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" does 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 as $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) { 
      } 
     } 
    } 
} 

하는 기본 설명 도우미 use Symfony\Component\Console\Descriptor\DescriptorHelper

$ php bin/console debug:router 
을 사용하는 상상을

멋진 오류로 끝납니다 :

[Symfony\Component\Console\Exception\InvalidArgumentException]    
Object of type "Symfony\Component\Routing\RouteCollection" is not describable. 

좋아요, 그래서 우리는 사용자 정의 DescriptorHelper를 만들어야합니다.먼저 우리의 기술자

<?php 

namespace AppBundle\Descriptor; 

use Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper; 

class DescriptorHelper extends BaseDescriptorHelper 
{ 
    /** 
    * Constructor. 
    */ 
    public function __construct() 
    { 
     $this 
      ->register('txt', new TextDescriptor()) 
     ; 
    } 
} 

그리고 마지막으로 등록

<?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" is not describable.', get_class($object))); 
     } 
    } 
    /** 
    * Returns the output. 
    * 
    * @return OutputInterface The output 
    */ 
    protected function getOutput() 
    { 
     return $this->output; 
    } 
    /** 
    * Writes content to 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 an InputArgument instance. 
    * 
    * @param RouteCollection $routes 
    * @param array   $options 
    */ 
    abstract protected function describeRouteCollection(RouteCollection $routes, array $options = array()); 
    /** 
    * Describes an InputOption instance. 
    * 
    * @param Route $route 
    * @param array $options 
    */ 
    abstract protected function describeRoute(Route $route, array $options = array()); 
    /** 
    * Describes a callable. 
    * 
    * @param callable $callable 
    * @param array $options 
    */ 
    abstract protected function describeCallable($callable, array $options = array()); 
    /** 
    * Formats a value as 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 a 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; 
    } 
} 

그런 다음 오버라이드 (override) 인터페이스를 기본 DescriptorHelper을 구현, 우리의 기술자

<?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() as $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 as $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 is 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 
     ); 
    } 
} 

지금 쓰는 $ php bin/console debug:router가 출력을 구현

------ --------- ------------ -------- ---------- 
    Name Method Scheme  Host  Path  
------ --------- ------------ -------- ---------- 
    name GET|PUT http|https myHost /myRoute 
------ --------- ------------ -------- ---------- 

이 모든 것을 찾기 위해 symfony 소스 코드로 나눴습니다. 다른 파일은 Symfony, symfony routing, consoleframework-bundle의 코드 스 니펫입니다.

+0

예 필요했습니다. 하지만 문제는 필자가 Symfony 프레임 워크 전체를 사용하지 않고 있으므로 bin/console도 없다는 것입니다. 구성 요소를 선택하기 만하면됩니다. –

+0

흠,'심포니/콘솔'이 필요하십니까? – lolmx

+1

@lolmx - 개별 Symfony 구성 요소 (예 : 라우팅 구성 요소)와 Symfony 프레임 워크의 차이점에 대해 조금 연구하고 싶을 수도 있습니다. 프레임 워크는 routing debug 명령을 구현합니다. 개별 구성 요소를 설치하지 않아도 라우팅 디버그 명령이 표시됩니다. – Cerad

관련 문제