As @hous said, this post was useful, but incomplete and its accepted answer misleading.
A) Getting the controllers
With this code I get all controllers, but with their FQCN::method
or service:method
notation.
// in a Controller.
$this->container->get('router')->getRouteCollection()->all()
Some Background
The previous method will return a big array of routes. Follows one key => value:
'admin_chacra' => // route name
object(Symfony\Component\Routing\Route)[1313]
...
private 'defaults' =>
array (size=1)
'_controller' => string 'Application\ColonizacionBundle\Controller\ChacraController::indexAction' (length=71)
The FQCN::method
notation is the right argument to the build method of ControllerNameParser::build(). The service notation is not parsed, as it gets handled by the following code in ControllerResolver::createController()`
$count = substr_count($controller, ':');
if (2 == $count) {
// controller in the a:b:c notation then
/* @var $this->parser ControllerNameParser parse() is the oposite of build()*/
$controller = $this->parser->parse($controller);
} elseif (1 == $count) {
// controller in the service:method notation
list($service, $method) = explode(':', $controller, 2);
return array($this->container->get($service), $method);
} else {
throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller));
}
B) Generating Logical Controller Names
So all I have to do is filter out the controllers I don't want, {FOS; framework's; etc} and feed build()
with each selected one. E.g. by selecting only the _controller attributes that matches my bundles namespace Application\*Bundle
in my case.
Here's the build docBlock
/**
* Converts a class::method notation to a short one (a:b:c).
*
* @param string $controller A string in the class::method notation
*
* @return string A short notation controller (a:b:c)
*
* @throws \InvalidArgumentException when the controller is not valid or cannot be found in any bundle
*/
My Implementation
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
class ActivityRoleControllerType extends AbstractType
{
...
/**
* Controller choices
*
* @var array
*/
private static $controllers = array();
/**
* Controller Name Parser
*
* @var ControllerNameParser
*/
private $parser;
/**
* expects the service_container service
*/
public function __construct(ContainerInterface $container)
{
$this->parser = new ControllerNameParser($container->get('kernel'));
self::$controllers = $this->getControllerLogicalNames(
$container->get('router')->getRouteCollection()->all(), $this->parser
);
}
/**
* Creates Logical Controller Names for all controllers under \Application\*
* namespace.
*
* @param Route[] $routes The routes to iterate through.
* @param ControllerNameParser $parser The Controller Name parser.
*
* @return array the ChoiceType choices compatible array of Logical Controller Names.
*/
public function getControllerLogicalNames(array $routes, ControllerNameParser $parser)
{
if (! empty(self::$controllers)) {
return self::$controllers;
}
$controllers = array();
/* @var $route \Symfony\Component\Routing\Route */
foreach ($routes as $route) {
$controller = $route->getDefault('_controller')
if (0 === strpos($controller, 'Application\\')) {
try {
$logicalName = $parser->build($controller);
$controllers[$logicalName] = $logicalName;
} catch (\InvalidArgumentException $exc) {
// Do nothing, invalid names skiped
continue;
}
}
}
asort($controllers);
return $controllers;
}
}