$moduleManager->getEventManager()->getSharedManager()->attach is not working in stable zf2 - php

namespace Auth;
use Zend\ModuleManager\ModuleManager;
class Module
{
public function init(ModuleManager $moduleManager)
{
$sharedEvents = $moduleManager->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
echo "I am init module dispatch";
exit();
}, 100);
}
}
$moduleManager->getEventManager()->getSharedManager()->attach() is working fine in ZF2 BETA5 but it is not working in stable final release.
Has this functionality taken off in final release?
How can I make this work in ZF2 final release?

public function onBootstrap(MvcEvent $e)
{
$application = $e->getApplication();
$sharedManager = $application->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
echo "I am init module dispatch";
exit();
}, 100);
}

In Beta Series of zend framework2
Auth\src\User\Controller\UserController.php
but in final release of zf2 this does not work. Main namespace folder should match exactly same as under src folder. so above will work only like this
Auth\src\Auth\Controller\UserController.php
or
User\src\User\Controller\UserController.php
Don't forget to change your namespaces and paths in module.php and module.config.php and controller file.

There are two ways,
You can get it from Module.php init method, by passing ModuleManger object into it and then modulemanager->getEventManager.
Or from onBootstrap method again in Module.php but not from ModuleManager but by the application object as Abdul did.
Remember, init and onBoostrap methods run for every page request. Registering Event there is okay but do not put heavy stuff there. I prefer sharedEventManager, as it is available even if the service is initializes in future.
Cheers!

Related

Figuring out Laravel 5 app namespace from a package

I'm developing a package for Laravel 5 and need to know the application namespace, how can I get it?
I saw there is Illuminate\Console\AppNamespaceDetectorTrait but it needs some Foundation helpers as well as an instance of the application container to make them work and it's tricky to test during the development of a package.
Edit: for the time being I'm wrapping that trait into an interface to create isolation, but wondering if there is a better solution.
I don't know what's supposed to not work with the AppNamespaceDetectorTrait. Just use it and call getAppNamespace():
class Foo {
use Illuminate\Console\AppNamespaceDetectorTrait;
public function bar(){
echo $this->getAppNamespace();
}
}
Try copying in getAppNamespace() function into a generic helpers file that can be accessed anywhere in your app. Then, you don't need to tie the AppNamespaceDetectorTrait trait to your class.
helpers.php
function getAppNamespace()
{
$composer = json_decode(file_get_contents(base_path().'/composer.json'), true);
foreach ((array) data_get($composer, 'autoload.psr-4') as $namespace => $path)
{
foreach ((array) $path as $pathChoice)
{
if (realpath(app_path()) == realpath(base_path().'/'.$pathChoice)) return $namespace;
}
}
throw new RuntimeException("Unable to detect application namespace.");
}
And then in YourClass.php
$namespace = getAppNamespace(); // App\

Zend Framework 2: Registering multiple custom view helpers externally

ZF2 has a nice way to register it's own Form View Helpers.
Let's say I've got my own external library and have a folder with several custom view helpers. In which way could I use such a "HelperConfig"-file as Zend Form does (see above)? How would I register it in my Application?
If you have a class that implements Zend\ServiceManager\ConfigInterface (just like the example you provided) all you need is to pass in a ServiceManager instance.
This could easily be done in the onBootstrap in a Module class.
namespace MyModule;
use Some\Other\Namespace\MyCustomViewHelperConfig;
use Zend\EventManager\EventInterface;
use Zend\ModuleManager\Feature\BootstrapListenerInterface;
class Module implements BootstrapListenerInterface
{
public function onBootstrap(EventInterface $event)
{
$application = $event->getApplication();
$serviceManager = $application->getServiceManager();
$viewHelperManager = $serviceManager->get('ViewHelperManager');
$viewHelperConfig = new MyCustomViewHelperConfig();
$viewHelperConfig->configureServiceManager($viewHelperManager);
}
}

zend framework 2 trigger event on a single module upon request (not on dispatch)

My app has multiple modules, among these are 2 CMS modules and a front module. I want to trigger the identity validation method only on the CMS modules on all actions. I want to do this in something like a front controller plugin (ZF1 refference) and the way I see it it should be in Module.php of the module in cause, but everything in here gets triggered across the entire app on dispatch.
Although your event handler will affect all modules, you can filter your CMS modules by their namespace. For example, if all controllers in your CMS module are named like 'CMSModule\Controller\IndexController', you can test if the namespace is CMSModule and do the identity validation, like in example below:
class Module {
public function onBootstrap(\Zend\Mvc\MvcEvent $e){
// ...
$em = $e->getApplication()->getEventManager();
$em->attach(\Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this, 'onDispatch'));
}
public function onDispatch(\Zend\Mvc\MvcEvent $e){
$match = $e->getRouteMatch();
$controller = $match->getParam('controller');
$segments = explode('\\', $controller);
$namespace = array_shift($segments);
if(!$namespace=='CMSModule1' && !$namespace=='CMSModule2' && ...)
return;
// Check the identity here
}
}

Log each request in ZF2

We are using zend framework 2 for a new application, i would like to have the same logging system of Rails or similar, i would like have a log for each request, is possible to do this in Zend?
It depends what you want to log. If it is just an access log, you should try to use the webserver's log. The logs from Apache/nginx/IIS etc perform better than you will achieve in your ZF2 app.
If you need to log inside the ZF2 application, you have two choices. First option is at bootstrap. It's one of the earliest options you can use, so probably therefore the best. However, you can also look at route or dispatch. Those two events are called during the "run" phase of the application. With these events, you have for example a route match available and therefore you know (or not) if your request did match any controller (or in case you don't have the match, it's a 404).
Some examples. Let's assume you have a logger configured in the ServiceManager under the logger key. Then to log at bootstrap:
namespace Application;
class Module
{
public function onBootstrap($e)
{
$app = $e->getApplication();
$sm = $app->getServiceManager();
$logger = $sm->get('logger');
$logger->debug('Log here!');
}
}
Or for example if you wait for route, you attach a listener for the route event:
namespace Application;
use Zend\Mvc\MvcEvent;
use Zend\Mvc\Router\RouteMatch;
class Module
{
public function onBootstrap($e)
{
$app = $e->getApplication();
$em = $app->getEventManager();
$sm = $app->getServiceManager();
$logger = $sm->get('logger');
$em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($logger) {
$match = $e->getRouteMatch();
// No route, this is a 404
if (!$match instanceof RouteMatch) {
return;
}
$logger->debug(sprintf(
'Route event with route %s',
$match->getMatchedRouteName()
));
});
}
}
Sounds like you could attach a listener to the dispatch event on Zend\Mvc\Application.
For reference, Rob Allen has created a handy list of ZF2 events.

Controller specific layout in ZendFramework 2

I have a module in my zendframework 2 application which contains two controllers.
I want to set a different layout for one of the controller's actions.
Is there a way to set it inside module config file?
P.s: I just tried to set it inside controller's __CONSTRUCT method using the following commands but it just didnt worked!
$event = $this->getEvent();
$event->getViewModel()->setTemplate('layout/MYLAYOUT');
But if i use the above commands inside each action of my controller it just works fine.
See akrabat's examples for a number of nice ways that layouts, views, etcetera can be tweaked easily.
Specifically what you're looking for can be found on his github here.
Here is a cut-paste of the controller's action method that sets/uses the alternate layout:
public function differentLayoutAction()
{
// Use a different layout
$this->layout('layout/different');
return new ViewModel();
}
Edit: It looks like akrabat has an example that says Change the layout for every action within a module, which might give the best pointers for setting the layout in the config; but I just had a look at the code, and the example is currently unfinished, it's not changing the layout.
I can just point you into the right direction, since currently i'm unable to open a sample project. Evan Coury has posted a method for Module specific layouts. See the following links:
Module Specific Layouts in Zend Framework 2
<?php
namespace MyModule;
use Zend\ModuleManager\ModuleManager;
class Module
{
public function init(ModuleManager $moduleManager)
{
$sharedEvents = $moduleManager->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
// This event will only be fired when an ActionController under the MyModule namespace is dispatched.
$controller = $e->getTarget();
$controller->layout('layout/alternativelayout');
}, 100);
}
}
Now how would this help you?: Well, $controller should have both the called controller and action stored. I'm sure you can check the $controller for the called action and then assign the layout accordingly.
I'm sorry i can currently only hint you into the direction, but i'm sure this can get you started.
#Sam's answer pretty much answers the question. As stated it just needs a check on which controller is called, which can be done like this:
<?php
namespace MyModule;
use Zend\ModuleManager\ModuleManager;
class Module
{
public function init(ModuleManager $moduleManager){
$sharedEvents = $moduleManager->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
$controller = $e->getTarget();
if ($controller instanceof Controller\AltLayoutController) {
$controller->layout('layout/alternativelayout');
}
}, 100);
}
I

Categories