I have several controllers with different actions. Let’s assume that in a few cases I would like for the whole controller to check if the user, based on the passed parameter (let’s assume category_id), can perform actions in it. What is the best method to not duplicate the code in each action, but to check based on the parameter from routing and let’s say a database query, if the user has access to this controller and the actions in it?
Hi!
Well, I am doing exactly what you mentioned (manually querying the ACL at the beginning of each action), but I think that can be replaced with an MvcEvent-Listener for the event ‘route’. (Using the EventManager - tutorials - Laminas Docs)
Thank you for all your suggestions. Everyone has been helpful.
By the way, there was a question: if I check whether the user is the owner of the category, should I return the category object retrieved in the listener under some variable, so that in the controller in the methods I do not duplicate the query?
I suspect the listener is not a good place. Once because of the role, twice because the function has too much responsibility. But on the other hand it’s always fewer database queries.
I’m sorry but your question was to check something based on some parameter from routing and not to retrieve something.
Please provide a code example of your controller to illustrate what you need so we can better understand your use case.
Users, who have accounts in the portal, have access to the content management panel. Due to the nature of the site there are several hundred of them. In the content management panel of their pages there are several controllers. Among them there is a group of say 10 controllers, which are used to manage the content created by the user’s own web pages. And here at the outset in each controller and each method I have a call to a class say websiteBuilder, which currently does two things: it checks access to the method based on the passed routing parameter and if the user has access to it also sets a parameter with the site object - it has to fetch it anyway to check access, so it returns it by the way.
I would like to do the checking in one place - here the listener is perfect. There is still the issue of calling the object retrieval controller in one place. In zend framework 1 there was init() method and here it would be perfect.
class WebsiteController extends AbstractController
{
protected $websiteBuilder;
...
public function __construct(
WebsiteBuilderInterface $websiteBuilder,
...
)
{
$this->websiteBuilder = $websiteBuilder;
...
}
public function indexAction()
{
$websiteBuilder = $this->websiteBuilder;
$websiteBuilder->setWebsiteId((int) $this->params()->fromRoute('website_id'));
$websiteBuilder->run();
$resultWebsiteBuilder = $websiteBuilder->getParams();
if (! $resultWebsiteBuilder->isValid()) {
// set message
$this->flashMessenger()->addErrorMessage($resultWebsiteBuilder->getErrorMessage());
// redirect
return $this->redirect()->toRoute($resultWebsiteBuilder->getRedirect(), $params = $resultSiteBuilder->getRedirectAction());
}
$websiteRow = $resultWebsiteBuilder->getWebsiteObject();
...
[other code]
}
public function otherAction()
{
$websiteBuilder = $this->websiteBuilder;
$websiteBuilder->setWebsiteId((int) $this->params()->fromRoute('website_id'));
$websiteBuilder->run();
$resultWebsiteBuilder = $websiteBuilder->getParams();
if (! $resultWebsiteBuilder->isValid()) {
// set message
$this->flashMessenger()->addErrorMessage($resultWebsiteBuilder->getErrorMessage());
// redirect
return $this->redirect()->toRoute($resultWebsiteBuilder->getRedirect(), $params = $resultSiteBuilder->getRedirectAction());
}
$websiteRow = $resultWebsiteBuilder->getWebsiteObject();
...
[other code]
}
...
The WebsiteController uses a WebsiteControllerFactory to inject dependencies.
There is probably a very simple solution to this case… that I don’t know