2013-03-27 2 views
0

Редактировать

после копания в коде симфони, в частности ControllerResolver, кажется, что им пытаются сделать на самом деле разве это возможно, если я не подкласс/реализации ControllerResolverInterface сам.Symfony 2 зависимостей контроллера, простирающиеся ContainerAware

это следующий код, который инициализирует контроллер передается от маршрута:

protected function createController($controller) 
{ 
    if (false === strpos($controller, '::')) { 
     throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller)); 
    } 

    list($class, $method) = explode('::', $controller, 2); 

    if (!class_exists($class)) { 
     throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); 
    } 

    return array(new $class(), $method); 
} 

как вы можете видеть на последней строке, это всегда экземпляр без аргументов, переданных, поэтому мне придется переопределить метод для инъекции чего-либо таким образом. чувствует себя очень взломанным.


Оригинал Вопрос

Я пытаюсь понять, как я могу вводить услуги в пользовательский контроллер, определенным в динамических маршрутов с использованием компонентов Symfony (например не полной рамочные стека).

Обратите внимание: я не с использованием полной структуры стека и не использую их код src DemoBundle. У меня есть composer.json файл, который требует компонентов, поэтому у меня есть собственный index.php файл, который является более или менее такой же, как и подробное здесь:

http://fabien.potencier.org/article/55/create-your-own-framework-on-top-of-the-symfony2-components-part-12

я следующее:

$routes = new RouteCollection(); 
$routes->add(
    'some route name', 
    new Route(
     'a route path', 
     array(
     '_controller' => 'App\MyBundle\Controller\MyController::handle' 
    ) 
    ) 
); 

Тогда у меня есть следующие в App/MyBundle/DependencyInjection/MyExtension.php:

public function load(array $configs, ContainerBuilder $container) { 
    $loader = new XmlFileLoader(
     $container, 
     new FileLocator(__DIR__.'/../Resource/config') 
    ); 
    $loader->load('services.xml'); 
} 

App/MyBundle/Resources/config/services.xml:

<container xmlns="http://symfony.com/schema/dic/services" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://symfony.com/schema/dic/services 
         http://symfony.com/schema/dic/services/services-1.0.xsd"> 

<services> 
    <service id="templating" class="Symfony\Component\Templating\EngineInterface" /> 
    <service id="navigation" class="App\MyBundle\Controller\MyController"> 
    <argument type="service" id="templating" /> 
    </service> 
</services> 
</container> 

Я в основном пытаюсь получить услугу шаблонной впрыскивается в MyController конструктор, и я понимаю, файл MyExtension должен загружаться автоматически. Я предполагаю, что, поскольку я не использую полную структуру стека, это причина, но как я могу заставить это работать?

+0

Загрузка расширений является частью структуры. Это происходит, когда вы добавляете пакет в AppKernel. Так что нет, это, вероятно, не будет автоматическим. Я не прочитал весь учебник, но я подозреваю, что вам может понадобиться изменить src/app.php? Посмотрите, где строится контейнер. – Cerad

+0

Привет, нет app.php - как указано, я использую автономные компоненты, а не полную структуру. Я использую свой собственный контейнер. проблема заключается в том, как я могу ввести что-то в контроллер, который определяет атрибут Route _controller. – djjjuk

+0

Я понимаю это. Ссылка, которую вы указали, фактически указывает на часть 6 учебника, а не на часть 12. Возможно, это исправить. Я имел в виду src/app.php из части 6. – Cerad

ответ

0

Ну, сначала. Вам не нужно вводить услуги в ваш контроллер. Нормальный контроллер расширит Symfony\Bundle\FrameworkBundle\Controller\Controller, который впрыснет контейнер с отверстием. Это означает, что вы можете получить доступ к templating службы, как это:

public function myAction() 
{ 
    $templating = $this->get('templating'); 
} 

Но Symfony2 дает вам также возможность создания контроллера в качестве услуг. Это означает, что вы удаляете расширение по умолчанию Controller, а вместо этого вводите только нужные вам услуги (обычно request и response). Более подробную информацию можно найти в this great post от Richard Miller.
Вы также можете прочитать this post от Lukas Kahwe Smith, в котором он говорит о том, почему он считает, что услуги являются «лучшей практикой» (обратите внимание, что Fabien, бывший из проекта Symfony, не согласен с этим).

+0

Первый комментарий не имеет значения как, как указано в вопросе, я не использую ни одного из пакетов Symfonys ', поэтому не могу их продлить. последнее - это то, что я пытаюсь сделать, но не работает. я подозреваю, что это не так, чтобы не загружать конфигурационные файлы. – djjjuk

2

Ничего страшного с переопределением ControllerResolver. Полная структура стека делает это тоже. В противном случае контроллеры не могли быть ContainerAware.

Я также использую Symfony компоненту без полной структуры стеки и, частично скопировать полную структуру стеки, я закончил с этим, чтобы впрыснуть контейнер в моих контроллерах

class ControllerResolver extends SymfonyControllerResolver 
{ 
    protected $container; 

    public function __construct(ContainerInterface $container, LoggerInterface $logger = null) 
    { 
     $this->container = $container; 

     parent::__construct($logger); 
    } 

    protected function createController($controller) 
    { 
     if (false === strpos($controller, '::')) { 
      throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller)); 
     } 

     list($class, $method) = explode('::', $controller, 2); 

     $class = "Namespace\\Controllers\\" . $class; 

     if (!class_exists($class)) { 
      throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); 
     } 

     $controller = new $class(); 
     if ($controller instanceof ContainerAwareInterface) { 
      $controller->setContainer($this->container); 
     } 

     return array($controller, $method); 
    } 
} 

Если вы хотите добавить возможность определить контроллеры в качестве услуг, которые вы можете заменить

if (!class_exists($class)) { 
     throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); 
    } 

    $controller = new $class(); 
    if ($controller instanceof ContainerAwareInterface) { 
     $controller->setContainer($this->container); 
    } 

с чем-то вроде

if (!class_exists($class)) { 
    if (!$this->container->has($class)) { 
     throw new \Exception(...); 
    } 
    $controller = $this->container->get($class); 

    return array($controller, $method); 
} 

$controller = new $class(); 
if ($controller instanceof ContainerAwareInterface) { 
    $controller->setContainer($this->container); 
} 

return array($controller, $method); 
Смежные вопросы