Skip to content

Commit bbd0ca7

Browse files
Tobionfabpot
authored andcommitted
Deprecate bundle:controller:action and service:method notation
1 parent 9971e31 commit bbd0ca7

File tree

17 files changed

+74
-90
lines changed

17 files changed

+74
-90
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ CHANGELOG
1111
* Using a `RouterInterface` that does not implement the `WarmableInterface` is deprecated.
1212
* The `RequestDataCollector` class has been deprecated. Use the `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector` class instead.
1313
* The `RedirectController` class allows for 307/308 HTTP status codes
14+
* Deprecated `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method` instead where `serviceOrFqcn`
15+
is either the service ID or the FQCN of the controller.
16+
* Deprecated `Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser`
1417

1518
4.0.0
1619
-----

Command/RouterDebugCommand.php

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,13 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Command;
1313

1414
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
15-
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
1615
use Symfony\Component\Console\Command\Command;
1716
use Symfony\Component\Console\Input\InputArgument;
1817
use Symfony\Component\Console\Input\InputInterface;
1918
use Symfony\Component\Console\Input\InputOption;
2019
use Symfony\Component\Console\Output\OutputInterface;
2120
use Symfony\Component\Console\Style\SymfonyStyle;
22-
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
2321
use Symfony\Component\Routing\RouterInterface;
24-
use Symfony\Component\Routing\Route;
2522

2623
/**
2724
* A console command for retrieving information about routes.
@@ -83,20 +80,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
8380
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
8481
}
8582

86-
$callable = $this->extractCallable($route);
87-
8883
$helper->describe($io, $route, array(
8984
'format' => $input->getOption('format'),
9085
'raw_text' => $input->getOption('raw'),
9186
'name' => $name,
9287
'output' => $io,
93-
'callable' => $callable,
9488
));
9589
} else {
96-
foreach ($routes as $route) {
97-
$this->convertController($route);
98-
}
99-
10090
$helper->describe($io, $routes, array(
10191
'format' => $input->getOption('format'),
10292
'raw_text' => $input->getOption('raw'),
@@ -105,41 +95,4 @@ protected function execute(InputInterface $input, OutputInterface $output)
10595
));
10696
}
10797
}
108-
109-
private function convertController(Route $route)
110-
{
111-
if ($route->hasDefault('_controller')) {
112-
$nameParser = new ControllerNameParser($this->getApplication()->getKernel());
113-
try {
114-
$route->setDefault('_controller', $nameParser->build($route->getDefault('_controller')));
115-
} catch (\InvalidArgumentException $e) {
116-
}
117-
}
118-
}
119-
120-
private function extractCallable(Route $route)
121-
{
122-
if (!$route->hasDefault('_controller')) {
123-
return;
124-
}
125-
126-
$controller = $route->getDefault('_controller');
127-
128-
if (1 === substr_count($controller, ':')) {
129-
list($service, $method) = explode(':', $controller);
130-
try {
131-
return sprintf('%s::%s', get_class($this->getApplication()->getKernel()->getContainer()->get($service)), $method);
132-
} catch (ServiceNotFoundException $e) {
133-
}
134-
}
135-
136-
$nameParser = new ControllerNameParser($this->getApplication()->getKernel());
137-
try {
138-
$shortNotation = $nameParser->build($controller);
139-
$route->setDefault('_controller', $shortNotation);
140-
141-
return $controller;
142-
} catch (\InvalidArgumentException $e) {
143-
}
144-
}
14598
}

Console/Descriptor/TextDescriptor.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,6 @@ protected function describeRoute(Route $route, array $options = array())
9595
array('Defaults', $this->formatRouterConfig($route->getDefaults())),
9696
array('Options', $this->formatRouterConfig($route->getOptions())),
9797
);
98-
if (isset($options['callable'])) {
99-
$tableRows[] = array('Callable', $options['callable']);
100-
}
10198

10299
$table = new Table($this->getOutput());
103100
$table->setHeaders($tableHeaders)->setRows($tableRows);

Controller/ControllerNameParser.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
* (Bundle\BlogBundle\Controller\PostController::indexAction).
2020
*
2121
* @author Fabien Potencier <[email protected]>
22+
*
23+
* @deprecated since Symfony 4.1
2224
*/
2325
class ControllerNameParser
2426
{
@@ -41,6 +43,10 @@ public function __construct(KernelInterface $kernel)
4143
*/
4244
public function parse($controller)
4345
{
46+
if (2 > func_num_args() || func_get_arg(1)) {
47+
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.1.', __CLASS__), E_USER_DEPRECATED);
48+
}
49+
4450
$parts = explode(':', $controller);
4551
if (3 !== count($parts) || in_array('', $parts, true)) {
4652
throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "a:b:c" controller string.', $controller));
@@ -86,6 +92,8 @@ public function parse($controller)
8692
*/
8793
public function build($controller)
8894
{
95+
@trigger_error(sprintf('The %s class is deprecated since Symfony 4.1.', __CLASS__), E_USER_DEPRECATED);
96+
8997
if (0 === preg_match('#^(.*?\\\\Controller\\\\(.+)Controller)::(.+)Action$#', $controller, $match)) {
9098
throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "class::method" string.', $controller));
9199
}

Controller/ControllerResolver.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,13 @@ protected function createController($controller)
3737
{
3838
if (false === strpos($controller, '::') && 2 === substr_count($controller, ':')) {
3939
// controller in the a:b:c notation then
40-
$controller = $this->parser->parse($controller);
41-
}
42-
43-
$resolvedController = parent::createController($controller);
40+
$deprecatedNotation = $controller;
41+
$controller = $this->parser->parse($deprecatedNotation, false);
4442

45-
if (1 === substr_count($controller, ':') && is_array($resolvedController)) {
46-
$resolvedController[0] = $this->configureController($resolvedController[0]);
43+
@trigger_error(sprintf('Referencing controllers with %s is deprecated since Symfony 4.1. Use %s instead.', $deprecatedNotation, $controller), E_USER_DEPRECATED);
4744
}
4845

49-
return $resolvedController;
46+
return parent::createController($controller);
5047
}
5148

5249
/**

EventListener/ResolveControllerNameSubscriber.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
* Guarantees that the _controller key is parsed into its final format.
2121
*
2222
* @author Ryan Weaver <[email protected]>
23+
*
24+
* @deprecated since Symfony 4.1
2325
*/
2426
class ResolveControllerNameSubscriber implements EventSubscriberInterface
2527
{
@@ -35,7 +37,7 @@ public function onKernelRequest(GetResponseEvent $event)
3537
$controller = $event->getRequest()->attributes->get('_controller');
3638
if (is_string($controller) && false === strpos($controller, '::') && 2 === substr_count($controller, ':')) {
3739
// controller in the a:b:c notation then
38-
$event->getRequest()->attributes->set('_controller', $this->parser->parse($controller));
40+
$event->getRequest()->attributes->set('_controller', $this->parser->parse($controller, false));
3941
}
4042
}
4143

Kernel/MicroKernelTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public function registerContainerConfiguration(LoaderInterface $loader)
6464
$loader->load(function (ContainerBuilder $container) use ($loader) {
6565
$container->loadFromExtension('framework', array(
6666
'router' => array(
67-
'resource' => 'kernel:loadRoutes',
67+
'resource' => 'kernel::loadRoutes',
6868
'type' => 'service',
6969
),
7070
));

Routing/DelegatingLoader.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,29 @@ public function load($resource, $type = null)
7373
}
7474

7575
foreach ($collection->all() as $route) {
76-
if (!is_string($controller = $route->getDefault('_controller')) || !$controller) {
76+
if (!is_string($controller = $route->getDefault('_controller'))) {
7777
continue;
7878
}
7979

80-
try {
81-
$controller = $this->parser->parse($controller);
82-
} catch (\InvalidArgumentException $e) {
83-
// unable to optimize unknown notation
80+
if (false !== strpos($controller, '::')) {
81+
continue;
82+
}
83+
84+
if (2 === substr_count($controller, ':')) {
85+
$deprecatedNotation = $controller;
86+
87+
try {
88+
$controller = $this->parser->parse($controller, false);
89+
90+
@trigger_error(sprintf('Referencing controllers with %s is deprecated since Symfony 4.1. Use %s instead.', $deprecatedNotation, $controller), E_USER_DEPRECATED);
91+
} catch (\InvalidArgumentException $e) {
92+
// unable to optimize unknown notation
93+
}
94+
}
95+
96+
if (1 === substr_count($controller, ':')) {
97+
$controller = str_replace(':', '::', $controller);
98+
@trigger_error(sprintf('Referencing controllers with a single colon is deprecated since Symfony 4.1. Use %s instead.', $controller), E_USER_DEPRECATED);
8499
}
85100

86101
$route->setDefault('_controller', $controller);

Tests/Controller/ControllerNameParserTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
1717
use Symfony\Component\HttpKernel\Kernel;
1818

19+
/**
20+
* @group legacy
21+
*/
1922
class ControllerNameParserTest extends TestCase
2023
{
2124
protected $loader;

Tests/Controller/ControllerResolverTest.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
2121
use Symfony\Component\DependencyInjection\ContainerInterface;
2222
use Symfony\Component\HttpFoundation\Request;
23+
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
2324
use Symfony\Component\HttpKernel\Tests\Controller\ContainerControllerResolverTest;
2425

2526
class ControllerResolverTest extends ContainerControllerResolverTest
@@ -32,6 +33,7 @@ public function testGetControllerOnContainerAware()
3233

3334
$controller = $resolver->getController($request);
3435

36+
$this->assertInstanceOf('Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController', $controller[0]);
3537
$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerInterface', $controller[0]->getContainer());
3638
$this->assertSame('testAction', $controller[1]);
3739
}
@@ -48,6 +50,10 @@ public function testGetControllerOnContainerAwareInvokable()
4850
$this->assertInstanceOf('Symfony\Component\DependencyInjection\ContainerInterface', $controller->getContainer());
4951
}
5052

53+
/**
54+
* @group legacy
55+
* @expectedDeprecation Referencing controllers with FooBundle:Default:test is deprecated since Symfony 4.1. Use Symfony\Bundle\FrameworkBundle\Tests\Controller\ContainerAwareController::testAction instead.
56+
*/
5157
public function testGetControllerWithBundleNotation()
5258
{
5359
$shortName = 'FooBundle:Default:test';
@@ -81,7 +87,7 @@ class_exists(AbstractControllerTest::class);
8187
$resolver = $this->createControllerResolver(null, $container);
8288

8389
$request = Request::create('/');
84-
$request->attributes->set('_controller', TestAbstractController::class.':testAction');
90+
$request->attributes->set('_controller', TestAbstractController::class.'::testAction');
8591

8692
$this->assertSame(array($controller, 'testAction'), $resolver->getController($request));
8793
$this->assertSame($container, $controller->getContainer());
@@ -117,7 +123,7 @@ class_exists(AbstractControllerTest::class);
117123
$resolver = $this->createControllerResolver(null, $container);
118124

119125
$request = Request::create('/');
120-
$request->attributes->set('_controller', DummyController::class.':fooAction');
126+
$request->attributes->set('_controller', DummyController::class.'::fooAction');
121127

122128
$this->assertSame(array($controller, 'fooAction'), $resolver->getController($request));
123129
$this->assertSame($container, $controller->getContainer());
@@ -157,13 +163,13 @@ class_exists(AbstractControllerTest::class);
157163
$resolver = $this->createControllerResolver(null, $container);
158164

159165
$request = Request::create('/');
160-
$request->attributes->set('_controller', DummyController::class.':fooAction');
166+
$request->attributes->set('_controller', DummyController::class.'::fooAction');
161167

162168
$this->assertSame(array($controller, 'fooAction'), $resolver->getController($request));
163169
$this->assertSame($controllerContainer, $controller->getContainer());
164170
}
165171

166-
protected function createControllerResolver(LoggerInterface $logger = null, Psr11ContainerInterface $container = null, ControllerNameParser $parser = null)
172+
protected function createControllerResolver(LoggerInterface $logger = null, Psr11ContainerInterface $container = null, ControllerNameParser $parser = null): ControllerResolverInterface
167173
{
168174
if (!$parser) {
169175
$parser = $this->createMockParser();

Tests/Functional/Bundle/TestBundle/Controller/SubRequestController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function indexAction($handler)
3333
// ...to check that the FragmentListener still references the right Request
3434
// when rendering another fragment after the error occurred
3535
// should render en/html instead of fr/json
36-
$content .= $handler->render(new ControllerReference('TestBundle:SubRequest:fragment'));
36+
$content .= $handler->render(new ControllerReference(self::class.'::fragmentAction'));
3737

3838
// forces the LocaleListener to set fr for the locale...
3939
// should render fr/json

Tests/Functional/Bundle/TestBundle/Controller/SubRequestServiceResolutionController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class SubRequestServiceResolutionController implements ContainerAwareInterface
2424
public function indexAction()
2525
{
2626
$request = $this->container->get('request_stack')->getCurrentRequest();
27-
$path['_controller'] = 'TestBundle:SubRequestServiceResolution:fragment';
27+
$path['_controller'] = self::class.'::fragmentAction';
2828
$subRequest = $request->duplicate(array(), null, $path);
2929

3030
return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);

Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,49 @@
11
session_welcome:
22
path: /session
3-
defaults: { _controller: TestBundle:Session:welcome }
3+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SessionController::welcomeAction }
44

55
session_welcome_name:
66
path: /session/{name}
7-
defaults: { _controller: TestBundle:Session:welcome }
7+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SessionController::welcomeAction }
88

99
session_logout:
1010
path: /session_logout
11-
defaults: { _controller: TestBundle:Session:logout}
11+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SessionController::logoutAction }
1212

1313
session_setflash:
1414
path: /session_setflash/{message}
15-
defaults: { _controller: TestBundle:Session:setFlash}
15+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SessionController::setFlashAction }
1616

1717
session_showflash:
1818
path: /session_showflash
19-
defaults: { _controller: TestBundle:Session:showFlash}
19+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SessionController::showFlashAction }
2020

2121
profiler:
2222
path: /profiler
23-
defaults: { _controller: TestBundle:Profiler:index }
23+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\ProfilerController::indexAction }
2424

2525
subrequest_index:
2626
path: /subrequest/{_locale}.{_format}
27-
defaults: { _controller: TestBundle:SubRequest:index, _format: "html" }
27+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SubRequestController::indexAction, _format: html }
2828
schemes: [https]
2929

3030
subrequest_fragment_error:
3131
path: /subrequest/fragment/error/{_locale}.{_format}
32-
defaults: { _controller: TestBundle:SubRequest:fragmentError, _format: "html" }
32+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SubRequestController::fragmentErrorAction, _format: html }
3333
schemes: [http]
3434

3535
subrequest_fragment:
3636
path: /subrequest/fragment/{_locale}.{_format}
37-
defaults: { _controller: TestBundle:SubRequest:fragment, _format: "html" }
37+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SubRequestController::fragmentAction, _format: html }
3838
schemes: [http]
3939

4040
fragment_home:
4141
path: /fragment_home
42-
defaults: { _controller: TestBundle:Fragment:index, _format: txt }
42+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\FragmentController::indexAction, _format: txt }
4343

4444
fragment_inlined:
4545
path: /fragment_inlined
46-
defaults: { _controller: TestBundle:Fragment:inlined }
46+
defaults: { _controller: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\FragmentController::inlinedAction }
4747

4848
array_controller:
4949
path: /array_controller
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
sub_request_page:
22
path: /subrequest
33
defaults:
4-
_controller: 'TestBundle:SubRequestServiceResolution:index'
4+
_controller: 'Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SubRequestServiceResolutionController::indexAction'
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
<?php echo $this->get('actions')->render($this->get('actions')->controller('TestBundle:Fragment:inlined', array(
1+
<?php echo $this->get('actions')->render($this->get('actions')->controller('Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\FragmentController::inlinedAction', array(
22
'options' => array(
33
'bar' => $bar,
44
'eleven' => 11,
55
),
66
)));
77
?>--<?php
8-
echo $this->get('actions')->render($this->get('actions')->controller('TestBundle:Fragment:customformat', array('_format' => 'html')));
8+
echo $this->get('actions')->render($this->get('actions')->controller('Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\FragmentController::customformatAction', array('_format' => 'html')));
99
?>--<?php
10-
echo $this->get('actions')->render($this->get('actions')->controller('TestBundle:Fragment:customlocale', array('_locale' => 'es')));
10+
echo $this->get('actions')->render($this->get('actions')->controller('Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\FragmentController::customlocaleAction', array('_locale' => 'es')));
1111
?>--<?php
1212
$app->getRequest()->setLocale('fr');
13-
echo $this->get('actions')->render($this->get('actions')->controller('TestBundle:Fragment:forwardlocale'));
13+
echo $this->get('actions')->render($this->get('actions')->controller('Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\FragmentController::forwardlocaleAction'));
1414
?>

Tests/Kernel/ConcreteMicroKernel.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ public function __destruct()
7272

7373
protected function configureRoutes(RouteCollectionBuilder $routes)
7474
{
75-
$routes->add('/', 'kernel:halloweenAction');
76-
$routes->add('/danger', 'kernel:dangerousAction');
75+
$routes->add('/', 'kernel::halloweenAction');
76+
$routes->add('/danger', 'kernel::dangerousAction');
7777
}
7878

7979
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)

0 commit comments

Comments
 (0)