[ZF2] What's the proper way to register global MVC plugins?

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

[ZF2] What's the proper way to register global MVC plugins?

juhasuni
This post has NOT been accepted by the mailing list yet.
Hello,

Is there a correct way to register custom MVC plugins that should be accessible from all controllers implementing the Pluggable interface?

ZF introduces few plugins by default and those are hardcoded to Zend\Mvc\Controller\PluginLoader. When neither PluginBroker or PluginLoader is instantiated using DI, it seems difficult to register new plugins.

An example in documentation would be nice.
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

cmple
juhasuni, did you find the solution?
I'd also like to know
Thanks,
juhasuni wrote
Hello,

Is there a correct way to register custom MVC plugins that should be accessible from all controllers implementing the Pluggable interface?

ZF introduces few plugins by default and those are hardcoded to Zend\Mvc\Controller\PluginLoader. When neither PluginBroker or PluginLoader is instantiated using DI, it seems difficult to register new plugins.

An example in documentation would be nice.
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

HHGAG
Here's a tutorial: http://akrabat.com/getting-started-with-zend-framework-2/
Hasan H. Gürsoy (HHGAG)
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

cmple
Its a great tutorial but it has nothing to do with plugins
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

Marco Pivetta
You can check
https://github.com/ZF-Commons/ZfcUser/blob/master/src/ZfcUser/Controller/Plugin/ZfcUserAuthentication.php
and
https://github.com/ZF-Commons/ZfcUser/blob/master/config/module.config.php#L63

Marco Pivetta

http://twitter.com/Ocramius

http://marco-pivetta.com



On 26 February 2012 03:13, cmple <[hidden email]> wrote:

>
> HHGAG wrote
> >
> > Here's a tutorial:
> > http://akrabat.com/getting-started-with-zend-framework-2/
> >
> Its a great tutorial but it has nothing to do with plugins
>
> --
> View this message in context:
> http://zend-framework-community.634137.n4.nabble.com/ZF2-What-s-the-proper-way-to-register-global-MVC-plugins-tp4265227p4421465.html
> Sent from the Zend Framework mailing list archive at Nabble.com.
>
> --
> List: [hidden email]
> Info: http://framework.zend.com/archives
> Unsubscribe: [hidden email]
>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

cmple
Marco Pivetta wrote
You can check
https://github.com/ZF-Commons/ZfcUser/blob/master/src/ZfcUser/Controller/Plugin/ZfcUserAuthentication.php
and
https://github.com/ZF-Commons/ZfcUser/blob/master/config/module.config.php#L63

Marco Pivetta

http://twitter.com/Ocramius

http://marco-pivetta.com



On 26 February 2012 03:13, cmple <[hidden email]> wrote:

>
> HHGAG wrote
> >
> > Here's a tutorial:
> > http://akrabat.com/getting-started-with-zend-framework-2/
> >
> Its a great tutorial but it has nothing to do with plugins
>
> --
> View this message in context:
> http://zend-framework-community.634137.n4.nabble.com/ZF2-What-s-the-proper-way-to-register-global-MVC-plugins-tp4265227p4421465.html
> Sent from the Zend Framework mailing list archive at Nabble.com.
>
> --
> List: [hidden email]
> Info: http://framework.zend.com/archives
> Unsubscribe: [hidden email]
>
>
>
Thanks Marco!
It looks like the plugin functionality has moved to a controller level ?
or there is another way to add plugins to the module ?
for instance if I want to use the ACL library, where do i put the $acl->isAllowed($role, $resource, $action) method ?
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

Marco Pivetta
As you can see from the plugin I've linked, plugins are just registered in the pluginLoader.
I would just create a new plugin class extending the AbstractPlugin as ZfcUserAuthentication does and then map it to "myAcl" for examle.
Then you should be able to use it with $this->myAcl()->isAllowed() in your controllers :)
Marco Pivetta

http://twitter.com/Ocramius     

http://marco-pivetta.com    



On 26 February 2012 20:13, cmple [via Zend Framework Community] <[hidden email]> wrote:
Marco Pivetta wrote
On 26 February 2012 03:13, cmple <[hidden email]> wrote:

>
> HHGAG wrote
> >
> > Here's a tutorial:
> > http://akrabat.com/getting-started-with-zend-framework-2/
> >
> Its a great tutorial but it has nothing to do with plugins
>
> --
> View this message in context:
> http://zend-framework-community.634137.n4.nabble.com/ZF2-What-s-the-proper-way-to-register-global-MVC-plugins-tp4265227p4421465.html
> Sent from the Zend Framework mailing list archive at Nabble.com.
>
> --
> List: [hidden email]
> Info: http://framework.zend.com/archives
> Unsubscribe: [hidden email]
>
>
>
Thanks Marco!
It looks like the plugin functionality has moved to a controller level ?
or there is another way to add plugins to the module ?
for instance if I want to use the ACL library, where do i put the $acl->isAllowed($role, $resource, $action) method ?


To unsubscribe from Zend Framework Community, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

cmple
Marco Pivetta wrote
As you can see from the plugin I've linked, plugins are just registered in
the pluginLoader.
I would just create a new plugin class extending the AbstractPlugin as
ZfcUserAuthentication does and then map it to "myAcl" for examle.
Then you should be able to use it with $this->myAcl()->isAllowed() in your
controllers :)
Marco Pivetta

http://twitter.com/Ocramius

http://marco-pivetta.com



On 26 February 2012 20:13, cmple [via Zend Framework Community] <
[hidden email]> wrote:

>  Marco Pivetta wrote
> You can check
>
> https://github.com/ZF-Commons/ZfcUser/blob/master/src/ZfcUser/Controller/Plugin/ZfcUserAuthentication.php
> and
>
> https://github.com/ZF-Commons/ZfcUser/blob/master/config/module.config.php#L63
>
> Marco Pivetta
>
> http://twitter.com/Ocramius
>
> http://marco-pivetta.com
>
>
>
> On 26 February 2012 03:13, cmple <[hidden email]<http://user/SendEmail.jtp?type=node&node=4422729&i=0>>
> wrote:
>
> >
> > HHGAG wrote
> > >
> > > Here's a tutorial:
> > > http://akrabat.com/getting-started-with-zend-framework-2/
> > >
> > Its a great tutorial but it has nothing to do with plugins
> >
> > --
> > View this message in context:
> >
> http://zend-framework-community.634137.n4.nabble.com/ZF2-What-s-the-proper-way-to-register-global-MVC-plugins-tp4265227p4421465.html
> > Sent from the Zend Framework mailing list archive at Nabble.com.
> >
> > --
> > List: [hidden email]<http://user/SendEmail.jtp?type=node&node=4422729&i=1>
> > Info: http://framework.zend.com/archives
> > Unsubscribe: [hidden email]<http://user/SendEmail.jtp?type=node&node=4422729&i=2>
> >
> >
> >
>
> Thanks Marco!
> It looks like the plugin functionality has moved to a controller level ?
> or there is another way to add plugins to the module ?
> for instance if I want to use the ACL library, where do i put the *$acl->isAllowed($role,
> $resource, $action)* method ?
>
> ------------------------------
>  If you reply to this email, your message will be added to the discussion
> below:
>
> http://zend-framework-community.634137.n4.nabble.com/ZF2-What-s-the-proper-way-to-register-global-MVC-plugins-tp4265227p4422729.html
>  To unsubscribe from Zend Framework Community, click here<http://zend-framework-community.634137.n4.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=634137&code=b2NyYW1pdXNAZ21haWwuY29tfDYzNDEzN3wxNzE0OTI1MTk4>
> .
> NAML<http://zend-framework-community.634137.n4.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
But this means that I'll have to add "$this->myAcl()->isAllowed()" in every controller which makes my code redundant.
Is there a way to use it globally(a single class available to all) ? maybe via DI instead of plugins ?
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

Marco Pivetta
You can still define your Acl "service" and put it in your Di config with all of its requirements.
Then you can inject it into your controller either as hard dependency (constructor parameter) or via setter injection.

Marco Pivetta

http://twitter.com/Ocramius     

http://marco-pivetta.com    



On 27 February 2012 04:32, cmple [via Zend Framework Community] <[hidden email]> wrote:
Marco Pivetta wrote
As you can see from the plugin I've linked, plugins are just registered in
the pluginLoader.
I would just create a new plugin class extending the AbstractPlugin as
ZfcUserAuthentication does and then map it to "myAcl" for examle.
Then you should be able to use it with $this->myAcl()->isAllowed() in your
controllers :)
Marco Pivetta

http://twitter.com/Ocramius

http://marco-pivetta.com



On 26 February 2012 20:13, cmple [via Zend Framework Community] <
> On 26 February 2012 03:13, cmple <[hidden email]<http://user/SendEmail.jtp?type=node&node=4422729&i=0>>
> wrote:

>
> >
> > HHGAG wrote
> > >
> > > Here's a tutorial:
> > > http://akrabat.com/getting-started-with-zend-framework-2/
> > >
> > Its a great tutorial but it has nothing to do with plugins
> >
> > --
> > View this message in context:
> >
> http://zend-framework-community.634137.n4.nabble.com/ZF2-What-s-the-proper-way-to-register-global-MVC-plugins-tp4265227p4421465.html
> > Sent from the Zend Framework mailing list archive at Nabble.com.
> >
> > --
> > List: [hidden email]<http://user/SendEmail.jtp?type=node&node=4422729&i=1>
> > Info: http://framework.zend.com/archives
> > Unsubscribe: [hidden email]<http://user/SendEmail.jtp?type=node&node=4422729&i=2>

> >
> >
> >
>
> Thanks Marco!
> It looks like the plugin functionality has moved to a controller level ?
> or there is another way to add plugins to the module ?
> for instance if I want to use the ACL library, where do i put the *$acl->isAllowed($role,
> $resource, $action)* method ?
>
> ------------------------------
>  If you reply to this email, your message will be added to the discussion
> below:
>
> http://zend-framework-community.634137.n4.nabble.com/ZF2-What-s-the-proper-way-to-register-global-MVC-plugins-tp4265227p4422729.html
But this means that I'll have to add "$this->myAcl()->isAllowed()" in every controller which makes my code redundant.
Is there a way to use it globally(a single class available to all) ? maybe via DI instead of plugins ?


To unsubscribe from Zend Framework Community, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

weierophinney
Administrator
In reply to this post by cmple
-- cmple <[hidden email]> wrote
(on Sunday, 26 February 2012, 07:32 PM -0800):
> But this means that I'll have to add "$this->myAcl()->isAllowed()" in
> every controller which makes my code redundant.  Is there a way to use
> it globally(a single class available to all) ? maybe via DI instead of
> plugins ?

There are two ways to do this.

First, you can inject your ACL and user objects into your controllers or
service layer via DI. This then means you need to do the "isAllowed()"
check within the controllers themselves, or within your service layer
code. I actually prefer the latter method, as it makes re-using my code
within the various server classes fairly trivial.

The second approach is to create a listener that listens on the dispatch
event, and does automated checking of ACLs based on the current
controller and action (though the latter gets a bit squidgy when you
consider the RestfulController, when an action parameter may not be
present).

    namespace AclChecker;

    use Zend\EventManager\StaticEventManager;

    class Module
    {
        public function init($manager)
        {
            // Register a bootstrap event
            $events = StaticEventManager::getInstance();
            $events->attach('bootstrap', 'bootstrap', array($this, 'bootstrap'));
        }

        public function bootstrap($e)
        {
            // Register a dispatch event, at high priority
            $app = $e->getParam('application');
            $app->events()->attach('dispatch', array($this, 'checkAcl'), 100);
        }

        public function checkAcl($e)
        {
            $app          = $e->getTarget();
            $locator      = $app->getLocator();
            $acl          = $locator->get('AclChecker\Acl'); // or whatever Acl class you
                                                            // define in your app

            $matches      = $e->getRouteMatch();
            $controller   = $matches->getParam('controller');
            $action       = $matches->getParam('action', 'index');

            // get the current user somehow...

            if ($acl->isAllowed($user, $controller, $action)) {
                // Passes ACL check; do nothing
                return;
            }

            // return a 401 response
            // or a redirect response (e.g., to a login page)
        }
    }

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

cmple
In reply to this post by Marco Pivetta
Marco Pivetta wrote
You can still define your Acl "service" and put it in your Di config with
all of its requirements.
Then you can inject it into your controller either as hard dependency
(constructor parameter) or via setter injection.

Marco Pivetta

http://twitter.com/Ocramius

http://marco-pivetta.com
So I'd have to add something similar in every controller ?

 public function editAction(){
    if ( !$this->myAcl()->isAllowed('user-role','userController','edit') ) {
    return $this->forward()->dispatch('user', array('action' => 'authenticate'));
    }
    }

or something like this:

class UserController extends ActionController {

 public function __construct(){
      $request = $this->getRequest();
      $resource = $request->????(); // How can i get the requested resource out of the request ?
      $action = $request->????();

    if ( !$this->myAcl()->isAllowed('user-role',$resource,$action) ) {
    return $this->forward()->dispatch('user', array('action' => 'authenticate'));
    }
    }

Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

Marco Pivetta
Nope, what I gave you is a service you could inject to check your ACL within the controllers. If you want to restrict acces in your application, then use Matthew's example, which is an event happening at 'dispatch' and which does exactly that, without copy/paste in every example.

Marco Pivetta

http://twitter.com/Ocramius     

http://marco-pivetta.com    



On 27 February 2012 15:42, cmple [via Zend Framework Community] <[hidden email]> wrote:
Marco Pivetta wrote
You can still define your Acl "service" and put it in your Di config with
all of its requirements.
Then you can inject it into your controller either as hard dependency
(constructor parameter) or via setter injection.

Marco Pivetta

http://twitter.com/Ocramius

http://marco-pivetta.com
So I'd have to add something similar in every controller ?

 public function editAction(){
    if ( !$this->myAcl()->isAllowed('user-role','userController','edit') ) {
    return $this->forward()->dispatch('user', array('action' => 'authenticate'));
    }
    }

or something like this:

class UserController extends ActionController {

 public function __construct(){
      $request = $this->getRequest();
      $resource = $request->????(); // How can i get the requested resource out of the request ?
      $action = $request->????();

    if ( !$this->myAcl()->isAllowed('user-role',$resource,$action) ) {
    return $this->forward()->dispatch('user', array('action' => 'authenticate'));
    }
    }

Thanks!


To unsubscribe from Zend Framework Community, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

cmple
This post was updated on .
In reply to this post by weierophinney
weierophinney wrote
-- cmple <[hidden email]> wrote
(on Sunday, 26 February 2012, 07:32 PM -0800):
> But this means that I'll have to add "$this->myAcl()->isAllowed()" in
> every controller which makes my code redundant.  Is there a way to use
> it globally(a single class available to all) ? maybe via DI instead of
> plugins ?

There are two ways to do this.

First, you can inject your ACL and user objects into your controllers or
service layer via DI. This then means you need to do the "isAllowed()"
check within the controllers themselves, or within your service layer
code. I actually prefer the latter method, as it makes re-using my code
within the various server classes fairly trivial.

The second approach is to create a listener that listens on the dispatch
event, and does automated checking of ACLs based on the current
controller and action (though the latter gets a bit squidgy when you
consider the RestfulController, when an action parameter may not be
present).

    namespace AclChecker;

    use Zend\EventManager\StaticEventManager;

    class Module
    {
        public function init($manager)
        {
            // Register a bootstrap event
            $events = StaticEventManager::getInstance();
            $events->attach('bootstrap', 'bootstrap', array($this, 'bootstrap'));
        }

        public function bootstrap($e)
        {
            // Register a dispatch event, at high priority
            $app = $e->getParam('application');
            $app->events()->attach('dispatch', array($this, 'checkAcl'), 100);
        }

        public function checkAcl($e)
        {
            $app          = $e->getTarget();
            $locator      = $app->getLocator();
            $acl          = $locator->get('AclChecker\Acl'); // or whatever Acl class you
                                                            // define in your app

            $matches      = $e->getRouteMatch();
            $controller   = $matches->getParam('controller');
            $action       = $matches->getParam('action', 'index');

            // get the current user somehow...

            if ($acl->isAllowed($user, $controller, $action)) {
                // Passes ACL check; do nothing
                return;
            }

            // return a 401 response
            // or a redirect response (e.g., to a login page)
        }
    }

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]
Thanks Matthew!
The second approach is exactly what I've been looking for.
But I get the following error:
PHP Fatal error:  Call to undefined method Zend\EventManager\Event::getRouteMatch()

Could it be my version? "2.0.0beta2"
Thanks!

Edit:
My bad, I was using EventManager instead of dispatch event =)
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

weierophinney
Administrator
-- cmple <[hidden email]> wrote
(on Monday, 27 February 2012, 08:17 AM -0800):

> weierophinney wrote
> > -- cmple &lt;roman.vidyayev@&gt; wrote
> > (on Sunday, 26 February 2012, 07:32 PM -0800):
> >> But this means that I'll have to add "$this->myAcl()->isAllowed()" in
> >> every controller which makes my code redundant.  Is there a way to use
> >> it globally(a single class available to all) ? maybe via DI instead of
> >> plugins ?
> >
> > There are two ways to do this.
> >
> > First, you can inject your ACL and user objects into your controllers or
> > service layer via DI. This then means you need to do the "isAllowed()"
> > check within the controllers themselves, or within your service layer
> > code. I actually prefer the latter method, as it makes re-using my code
> > within the various server classes fairly trivial.
> >
> > The second approach is to create a listener that listens on the dispatch
> > event, and does automated checking of ACLs based on the current
> > controller and action (though the latter gets a bit squidgy when you
> > consider the RestfulController, when an action parameter may not be
> > present).
> >
> >     namespace AclChecker;
> >
> >     use Zend\EventManager\StaticEventManager;
> >
> >     class Module
> >     {
> >         public function init($manager)
> >         {
> >             // Register a bootstrap event
> >             $events = StaticEventManager::getInstance();
> >             $events->attach('bootstrap', 'bootstrap', array($this,
> > 'bootstrap'));
> >         }
> >
> >         public function bootstrap($e)
> >         {
> >             // Register a dispatch event, at high priority
> >             $app = $e->getParam('application');
> >             $app->events()->attach('dispatch', array($this, 'checkAcl'),
> > 100);
> >         }
> >
> >         public function checkAcl($e)
> >         {
> >             $app          = $e->getTarget();
> >             $locator      = $app->getLocator();
> >             $acl          = $locator->get('AclChecker\Acl'); // or
> > whatever Acl class you
> >                                                             // define in
> > your app
> >
> >             $matches      = $e->getRouteMatch();
> >             $controller   = $matches->getParam('controller');
> >             $action       = $matches->getParam('action', 'index');
> >
> >             // get the current user somehow...
> >
> >             if ($acl->isAllowed($user, $controller, $action)) {
> >                 // Passes ACL check; do nothing
> >                 return;
> >             }
> >
> >             // return a 401 response
> >             // or a redirect response (e.g., to a login page)
> >         }
> >     }
> The second approach is exactly what I've been looking for.
> But I get the following error:
> PHP Fatal error:  Call to undefined method
> Zend\EventManager\Event::getRouteMatch()
>
> Could it be my version? "2.0.0beta2"

The fact that you're getting an Event object and not an MvcEvent tells
me that you didn't registe where/when you thought you did.

I say this because, since the listener is registered with the "dispatch"
event on the Application instance, you _should_ have the route match by
that point -- "route" will have already triggered, which is when the
RouteMatch is injected. Additionally, the "route" and "dispatch" events
both are happening in the Application scope, which uses an MvcEvent
instance.  Are you sure you used it exactly as written above?

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

cmple
weierophinney wrote
-- cmple <[hidden email]> wrote
(on Monday, 27 February 2012, 08:17 AM -0800):
> weierophinney wrote
> > -- cmple <roman.vidyayev@> wrote
> > (on Sunday, 26 February 2012, 07:32 PM -0800):
> >> But this means that I'll have to add "$this->myAcl()->isAllowed()" in
> >> every controller which makes my code redundant.  Is there a way to use
> >> it globally(a single class available to all) ? maybe via DI instead of
> >> plugins ?
> >
> > There are two ways to do this.
> >
> > First, you can inject your ACL and user objects into your controllers or
> > service layer via DI. This then means you need to do the "isAllowed()"
> > check within the controllers themselves, or within your service layer
> > code. I actually prefer the latter method, as it makes re-using my code
> > within the various server classes fairly trivial.
> >
> > The second approach is to create a listener that listens on the dispatch
> > event, and does automated checking of ACLs based on the current
> > controller and action (though the latter gets a bit squidgy when you
> > consider the RestfulController, when an action parameter may not be
> > present).
> >
> >     namespace AclChecker;
> >
> >     use Zend\EventManager\StaticEventManager;
> >
> >     class Module
> >     {
> >         public function init($manager)
> >         {
> >             // Register a bootstrap event
> >             $events = StaticEventManager::getInstance();
> >             $events->attach('bootstrap', 'bootstrap', array($this,
> > 'bootstrap'));
> >         }
> >
> >         public function bootstrap($e)
> >         {
> >             // Register a dispatch event, at high priority
> >             $app = $e->getParam('application');
> >             $app->events()->attach('dispatch', array($this, 'checkAcl'),
> > 100);
> >         }
> >
> >         public function checkAcl($e)
> >         {
> >             $app          = $e->getTarget();
> >             $locator      = $app->getLocator();
> >             $acl          = $locator->get('AclChecker\Acl'); // or
> > whatever Acl class you
> >                                                             // define in
> > your app
> >
> >             $matches      = $e->getRouteMatch();
> >             $controller   = $matches->getParam('controller');
> >             $action       = $matches->getParam('action', 'index');
> >
> >             // get the current user somehow...
> >
> >             if ($acl->isAllowed($user, $controller, $action)) {
> >                 // Passes ACL check; do nothing
> >                 return;
> >             }
> >
> >             // return a 401 response
> >             // or a redirect response (e.g., to a login page)
> >         }
> >     }
> The second approach is exactly what I've been looking for.
> But I get the following error:
> PHP Fatal error:  Call to undefined method
> Zend\EventManager\Event::getRouteMatch()
>
> Could it be my version? "2.0.0beta2"

The fact that you're getting an Event object and not an MvcEvent tells
me that you didn't registe where/when you thought you did.

I say this because, since the listener is registered with the "dispatch"
event on the Application instance, you _should_ have the route match by
that point -- "route" will have already triggered, which is when the
RouteMatch is injected. Additionally, the "route" and "dispatch" events
both are happening in the Application scope, which uses an MvcEvent
instance.  Are you sure you used it exactly as written above?

--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]
Thanks Matthew!
I got it to work now :)
as per my edit above I was using the EventManager instead of the dispatch event.

Although I still can't figure out is how to reset the controller/action or redirect within the Module -> checkAcl($e) function, similar to controller's:

$this->forward()->dispatch('user', array('action' => 'authenticate'))
or
$this->redirect()->toRoute('home/login');

I've tried to do:

$app = $e->getTarget();
$app->dispatch('user', array('action' => 'authenticate'));

PHP Catchable fatal error:  Argument 1 passed to Zend\Mvc\Application::dispatch() must be an instance of Zend\Mvc\MvcEvent
Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

weierophinney
Administrator
-- cmple <[hidden email]> wrote
(on Monday, 27 February 2012, 12:13 PM -0800):

> weierophinney wrote
> > -- cmple &lt;roman.vidyayev@&gt; wrote
> > (on Monday, 27 February 2012, 08:17 AM -0800):
> > > weierophinney wrote
> > > > -- cmple &lt;roman.vidyayev@&gt; wrote
> > > > (on Sunday, 26 February 2012, 07:32 PM -0800):
> > > > > But this means that I'll have to add "$this->myAcl()->isAllowed()" in
> > > > > every controller which makes my code redundant.  Is there a way to use
> > > > > it globally(a single class available to all) ? maybe via DI instead of
> > > > > plugins ?
> > > >
> > > > There are two ways to do this.
> > > >
> > > > First, you can inject your ACL and user objects into your
> > > > controllers or service layer via DI. This then means you need to
> > > > do the "isAllowed()" check within the controllers themselves, or
> > > > within your service layer code. I actually prefer the latter
> > > > method, as it makes re-using my code within the various server
> > > > classes fairly trivial.
> > > >
> > > > The second approach is to create a listener that listens on the
> > > > dispatch event, and does automated checking of ACLs based on the
> > > > current controller and action (though the latter gets a bit
> > > > squidgy when you consider the RestfulController, when an action
> > > > parameter may not be present).
> > > >
> > > >     namespace AclChecker;
> > > >
> > > >     use Zend\EventManager\StaticEventManager;
> > > >
> > > >     class Module
> > > >     {
> > > >         public function init($manager)
> > > >         {
> > > >             // Register a bootstrap event
> > > >             $events = StaticEventManager::getInstance();
> > > >             $events->attach('bootstrap', 'bootstrap', array($this,
> > > > 'bootstrap'));
> > > >         }
> > > >
> > > >         public function bootstrap($e)
> > > >         {
> > > >             // Register a dispatch event, at high priority
> > > >             $app = $e->getParam('application');
> > > >             $app->events()->attach('dispatch', array($this,
> > > 'checkAcl'),
> > > > 100);
> > > >         }
> > > >
> > > >         public function checkAcl($e)
> > > >         {
> > > >             $app          = $e->getTarget();
> > > >             $locator      = $app->getLocator();
> > > >             $acl          = $locator->get('AclChecker\Acl'); // or
> > > > whatever Acl class you
> > > >                                                             // define
> > > in
> > > > your app
> > > >
> > > >             $matches      = $e->getRouteMatch();
> > > >             $controller   = $matches->getParam('controller');
> > > >             $action       = $matches->getParam('action', 'index');
> > > >
> > > >             // get the current user somehow...
> > > >
> > > >             if ($acl->isAllowed($user, $controller, $action)) {
> > > >                 // Passes ACL check; do nothing
> > > >                 return;
> > > >             }
> > > >
> > > >             // return a 401 response
> > > >             // or a redirect response (e.g., to a login page)
> > > >         }
> > > >     }
> > > The second approach is exactly what I've been looking for.
> > > But I get the following error:
> > > PHP Fatal error:  Call to undefined method
> > > Zend\EventManager\Event::getRouteMatch()
> > >
> > > Could it be my version? "2.0.0beta2"
> >
> > The fact that you're getting an Event object and not an MvcEvent tells
> > me that you didn't registe where/when you thought you did.
> >
> > I say this because, since the listener is registered with the "dispatch"
> > event on the Application instance, you _should_ have the route match by
> > that point -- "route" will have already triggered, which is when the
> > RouteMatch is injected. Additionally, the "route" and "dispatch" events
> > both are happening in the Application scope, which uses an MvcEvent
> > instance.  Are you sure you used it exactly as written above?
> >
> Thanks Matthew!
> I got it to work now :)
> as per my edit above I was using the EventManager instead of the dispatch
> event.

:) Thought it might be something like that.

> Although I still can't figure out is how to reset the controller/action or
> redirect within the Module ->checkAcl($e) function, similar to
> controller's:
>
> $this->forward()->dispatch('user', array('action' => 'authenticate'))
> or
> $this->redirect()->toRoute('home/login');
>
> I've tried to do:
>
> $app = $e->getTarget();
> $app->dispatch('user', array('action' => 'authenticate'));
>
> PHP Catchable fatal error:  Argument 1 passed to
> Zend\Mvc\Application::dispatch() must be an instance of Zend\Mvc\MvcEvent

Simply alter the RouteMatch -- since you're doing this as a
high-priority dispatch listener, the controller hasn't yet been
retrieved from the locator. This means you can do something like this:

    $matches->setParam('controller', 'Alternate\Controller\Classname');
    $matches->setParam('action', 'someOtherAction');

If you want to redirect, simply grab the response object and set the
status code and location header, and return it:

    // Assemble the URL
    $router = $e->getRouter();
    $url    = $router->assemble((), array('name' => 'home/login'));

    // Populate and return the response
    $response = $e->getResponse();
    $response->setStatusCode(302);
    $response->headers()->addHeaderLine('Location', $url);
    return $response;


--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: [ZF2] What's the proper way to register global MVC plugins?

cmple
weierophinney wrote
Simply alter the RouteMatch -- since you're doing this as a
high-priority dispatch listener, the controller hasn't yet been
retrieved from the locator. This means you can do something like this:

    $matches->setParam('controller', 'Alternate\Controller\Classname');
    $matches->setParam('action', 'someOtherAction');

If you want to redirect, simply grab the response object and set the
status code and location header, and return it:

    // Assemble the URL
    $router = $e->getRouter();
    $url    = $router->assemble(array(), array('name' => 'home/login'));

    // Populate and return the response
    $response = $e->getResponse();
    $response->setStatusCode(302);
    $response->headers()->addHeaderLine('Location', $url);
    return $response;


--
Matthew Weier O'Phinney
Project Lead            | [hidden email]
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

--
List: [hidden email]
Info: http://framework.zend.com/archives
Unsubscribe: [hidden email]
That worked !
Thanks Matthew!