10000 [HttpKernel] [DX] Configurable controller layout by scaytrase · Pull Request #25422 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[HttpKernel] [DX] Configurable controller layout #25422

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

scaytrase
Copy link
Contributor
Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets part of #23259
License MIT
Doc PR none

First part of #23259 RFC (cc @iltar @nicolas-grekas).

The general idea is to allow reusing ControllerNameParser for different than original *Bundle\*Controller::*Action layout.

Original layout is now stored in GenericControllerLayout implementation which nicely covers the structure logic from users

  • add unit tests for new classes
  • discuss the interface method names

For me building bundle+controller+action into string looks like build method and parsing string into bundle+controller+action looks like parse method. But it turns out than ControllerNameParser::build uses parse (to build from parsed results) and ControllerNameParser::parse uses build one (to build from exploded parts). Does this makes sence?

@carsonbot carsonbot added Status: Needs Review HttpKernel DX DX = Developer eXperience (anything that improves the experience of using Symfony) Feature labels Dec 10, 2017

$className = $match[1];
$controllerName = $match[2];
$actionName = $match[3];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably be list(, $className, $controllerName, $actionName) = $match;

/** @var string */
public $controller;
/** @var string */
public $action;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be private, otherwise they can be modified afterwards. I think this class should probably be final as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just followed https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Controller/ControllerReference.php here. Can make it final VO to be more protected from modifications

if ($alternative = $this->findAlternative($bundleName)) {
$provider = new AlternativeBundleNameProvider($this->kernel);

if ($alternative = $provider->findAlternative($bundleName)) {
$message .= sprintf(' Did you mean "%s:%s:%s"?', $alternative, $controller, $action);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there only 1 alternative? I can imagine there could be multiple alternatives. Assuming 1 alternative is the status quo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just moved this responsibility (https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php#L107-L132) out to the separate class since it could be reused in many bundle guessing snippets

It's logic is about finding most similar bundle name, so this definetely only 1. We can return prioritized list here leaving formatting to the end-user code

@@ -7,9 +7,14 @@
<services>
<defaults public="false" />

<service id="controller_layout.generic" class="Symfony\Component\HttpKernel\Controller\Layout\GenericControllerLayout">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably be the FQCN as ID, though I'm not sure if this is default for the Symfony Core. If not, I'd like to see an alias for autowiring purposes (perhaps on the interface as well if this is the default).

Copy link
Contributor Author
@scaytrase scaytrase Dec 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no FQCN identifiers in this file, neither did I. I think this is a step for further improvements outside of the scope of this PR

public function __construct(KernelInterface $kernel)
private $layout;

public function __construct(KernelInterface $kernel, ControllerLayoutInterface $layout = null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is (currently) no configuration for this, how would someone change this to resolve it differently? Do you have examples of why it should be solved differently?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General idea is to reuse the class itself for other layouts. So we can use default generic layout for controllers and custom layouts with same logic for something else.

Am not sure that this class should live here, but not in http-kernel component (to be used standalone), but moving a class is a tricky thing, so I haven't suggest it here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be more concrete we have secondary routing for RPC controllers allowing to specify a:b:c notation which points to RPC namespace. Currently we have to copy-paste this class to override layout and keep the resolving process

@nicolas-grekas nicolas-grekas added this to the 4.1 milestone Dec 11, 2017
@scaytrase
Copy link
Contributor Author

Should I add http-kernel:~4.1 as framework-bundle dependency to make lower deps test pass?

@derrabus
Copy link
Member

I still haven't understood the problem that this is going to solve, I must admit. Symfony (as far as I know) offers three ways to specify a controller:

  • FQCN + (optional) Method name,
  • Service ID + (optional) Method name,
  • The bundle-controller-action scheme.

Your PR only generalizes the third way. Symfony 4 encourages developers to write bundle-less applications, so the use-cases of that that third way are supposed to decrease now. Also, bundle-less applications cannot make use of your extension point.

On top of that: Matching requests to controllers can be done with custom request matchers (if the standard router does not fit), resolving arbitrary strings to controllers can be done with custom controller resolvers. So, imho we have extension points to cover such cases already.

Why would I need another way to specify a controller inside a bundle?

@scaytrase
Copy link
Contributor Author

@derrabus

Why would I need another way to specify a controller inside a bundle?

You don't need another way to specify a controller, that fact stands for this patch from it's beginning, the way stands the same

We want to re-use logic of b:c:a matching for another layout also making some classes less coupled and having less responsibilities (is it bad?).

Request matching would make us totally copy-paste all this code, since it's not cachaeble, not configurable, etc (since it's a custom code all the time). We have ready-to-use algorythms, which suits us with little modifications, why should be repeat them instead of proposing a patch?

* Use ~4.1 for http-kernel to fix lower-deps test passing
@Tobion
Copy link
Contributor
Tobion commented Feb 24, 2018

Closing as bundle:controller:action notation is deprecate since #26085. So we won't add new features/refactor this obsolete logic. Thanks for your work on this @scaytrase

About the second part of your issue:

Controller Resolver signature requires the whole Request object, but really it uses only _controller attribute value, can we pass it instead?

This could indeed be refactored. It would be possible to move the logic inside the controller resolver out to a separate class that does not know about Request at all. The existing controller resolver would just read the _controller request attribute and forward to the extracted service.
If you still have a good use-case and need for this, you are welcome to work on this.

@Tobion Tobion closed this Feb 24, 2018
@scaytrase scaytrase deleted the feature/controller-layout branch February 24, 2018 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DX DX = Developer eXperience (anything that improves the experience of using Symfony) Feature HttpKernel Status: Needs Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants
0