-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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
[9.x] Fallback to resolving controller middleware like before #44590
[9.x] Fallback to resolving controller middleware like before #44590
Conversation
Hey @lorisleiva - is there anything we can check to know if a class is an action? Some other interface or trait your package requires on all actions? The change you propose means that POPO controllers that don't extend anything will now be resolved like they were before, which we were trying to avoid. |
Hi @taylorotwell, Thanks for coming back to me. That makes sense. TL;DR; Yes, it uses the Laravel Actions works by hooking some logic into the IoC container and wrapping any classes that use a certain trait into the appropriate Decorator based on where it was resolved (using I used traits instead of interfaces to allow adding features to actions directly (like I tried to resolve and execute all middleware directly within the Since the controller is resolved from the container after middleware are resolved, Laravel Actions has no control over this part of the logic. Do you have any suggestion regarding how we could make that if statement works with Laravel Actions whilst keeping the strong typing? |
Can we do a class_uses_recursive check for your |
Would it make sense to add a second Something like: interface HasInstanceMiddleware
{
/**
* Get the middleware that should be assigned to the controller instance.
*
* @return array
*/
public function getMiddleware();
} Anything that needs this behavior could then implement that interface… |
@inxilpro I could already use the @taylorotwell I'm happy to add a recursive trait check but I assumed this would be coupling the framework too much with an external library. An other approach would be to resolve the controller from the container before that last if statement. Because once the controller is resolved, the real Something like that: // ...
$resolvedController = $this->getController();
if (is_a($resolvedController, Controller::class, true)) {
return $this->controllerDispatcher()->getMiddleware(
$resolvedController, $controllerMethod
);
}
return []; This wouldn’t affect PR #44516 because implementing the What do you think? |
We don't want users to have to implement the Adding a way of being able to define base classes and traits in userland which would be treated in the same way as the |
Hi @X-Coder264! Oh I see, I assumed the In this case, @taylorotwell would it be okay if I updated this PR with a recursive trait check on a new trait, similar to the solution offered by @inxilpro but with a trait instead of an interface. Something like that: if ($this->hasInstanceMiddleware($controllerClass)) {
return $this->controllerDispatcher()->getMiddleware(
$this->getController(), $controllerMethod
);
}
return []; Such that public function hasInstanceMiddleware (string $controllerClass)
{
return is_a($controllerClass, Controller::class, true)
|| in_array(HasInstanceMiddlewareTrait::class, class_uses_recursive($controllerClass));
} And trait HasInstanceMiddlewareTrait {
abstract public function getMiddleware();
} I am conscious an interface would make more sense than a trait here but this would unfortunately not work for Laravel Actions. I am happy to add an additional check for a |
@lorisleiva can we not just check for your existing trait? |
@taylorotwell If you're okay with it, I'm okay with it. I've updated the PR. Let me know what you think. |
@taylorotwell maybe I'm missing something… but isn't this something we want to preserve? Prior to #44516, any class that has a It seems like this change would address @lorisleiva's issue and also just generally be more backwards-compatible: - if (is_a($controllerClass, Controller::class, true)) {
+ if (method_exists($controllerClass, 'getMiddleware')) { The problem with |
@inxilpro That's a great point. Initially, I removed that if statement altogether because the EDIT: I've updated the PR again. |
I'm so confused. All I'm asking is can we not just do: if (is_a($controllerClass, Controller::class, true) ||
CLASS USES SOME TRAIT FROM LARAVEL ACTIONS PACKAGE) {
return $this->controllerDispatcher()->getMiddleware(
$this->getController(), $controllerMethod
);
} |
Will just roll with this PR as is I guess 👍 |
@taylorotwell That's what I did before my last commit (2135794) but I think the merged solution offered by @inxilpro is much better as it avoid coupling the framework with a third party package. |
Context
PR #44516 introduces a new way of resolving controller middleware statically so that they can be resolved before the controller is instantiated.
Problem
The PR itself is fine and fills a need for the community but there's just a small implementation detail that makes it no longer possible for Laravel Actions to use controller middleware in its
ControllerDecorator
.Inside the updated
Route@controllerMiddleware
method, we now check that the controller class is aController
instance and, if not, return an empty array.This is problematic for Laravel Actions since Actions can be used within any class architecture and will likely not want to be tight to a
Controller
abstract class.Solution
The simple solution proposed in this PR is to fall back to resolving controller middleware as we were before.
This change does not cause any side effect because a safety check already exists within the
getMiddleware
method of theControllerDispatcher
.Note that this change does not affect the new feature brought by #44516. It simply relaxes the second if statement so that both solutions can live together.