28

I want to pass a series of variables to my layout.phtml throughout the whole application(globally). And by that I mean I don't wanna use

$this->layout()->someVar = someValue;

in each and every action I've got, since it would be a lot of extra work and code. So is there a way to do it in just one place? Or What I mentioned is all I got! Hope not :)

Maybe using sessions ? – Remi Thomas

Thanks for the solution. For the time being that's what I'm using. For logged-in user info, system and layout settings and an ACL list. But the problem is that I have to define a new object in the layout.phtml which I don't think is appropriate, is it? I read somewhere that whatever data we need to use in view models should be passed to it using controller actions. And specially I'm not a fan of cutting corners, so if there's a clean way to do this I'd rather not do it this way. And recently I have to get the number of unread messages for each user and use it in layout.phtml. So if I do it in layout.phtml it's a LOT of php script inside a view model or layout.

Thanks

Milad.Nozari
  • 2,243
  • 3
  • 26
  • 47

6 Answers6

43

The best and cleanest way is using a ViewHelper, as Orochi suggests. Here some instructions to create your own ViewHelper: http://framework.zend.com/manual/2.2/en/modules/zend.view.helpers.advanced-usage.html. It's not too complex ;)

However your problem could be resolved also in another way. Supposing the variables you need contain values provided by services already present in your application (and then exposed by ZF2 ServiceManager), you could add some lines on the "onBoostrap" function inside your Module.php (e.g. on Application module).

Here an example:

public function onBootstrap($e) {

    $serviceManager = $e->getApplication()->getServiceManager();
    $viewModel = $e->getApplication()->getMvcEvent()->getViewModel();

    $myService = $serviceManager->get('MyModule\Service\MyService');

    $viewModel->someVar = $myService->getSomeValue();

}

In this way you write the assignment in only one place. The variable is then accessible as usual:

$this->layout()->someVar;
stefanovalle
  • 561
  • 4
  • 3
  • 1
    Thanks Stefan, I really appreciate it. I'm currently busy with another priority part of the application. But in a few days I'll definitely try these solutions. But right now, I guess the onBootstrap is exactly what I need. I'll test it. Thanks again bro :) – Milad.Nozari Sep 01 '13 at 11:07
  • Great post! Works like a charm! – Ron Jan 20 '14 at 09:44
38

This is exactly what you want...

// Do this inside your Controller before you return your ViewModel
$this->layout()->setVariable('stack', 'overflow');

// Then inside your layout.phtml
echo $this->stack;

No view helpers, no event manager, no service manager or other class method juggling. Why do people on Stack make things so darn complicated sometimes?

Timothy Perez
  • 20,154
  • 8
  • 51
  • 39
  • 3
    Thanks dude, but I already knew that. The question is, inside which controller, to do it once and for all! i.e. only do it in one place but accessible everywhere and the correct answer is you don't do it in a controller. Which stefanovalle kindly provided the onBootstrap solution. Thanks anyways :) – Milad.Nozari Dec 16 '13 at 14:11
  • Because your simple solution is not scalable. – Quolonel Questions Mar 05 '15 at 14:12
  • Error with Zend 1.12: Method "layout" does not exist and was not trapped in __call() – Syed Waqas Bukhary Jul 31 '15 at 11:00
3

Create your own ViewHelper for that.

EDIT:

That's how I do it: Inside your Module's src folder, I create new View folder then in this View folder, I create another folder called Helper. In this folder i create my helper classes. So, for example, I create Navigation.php file. In this file I create a class called Navigation, which extends from AbstractHelper (use Zend\View\Helper\AbstractHelper). Then I write code inside public function __invoke(), which also returns some result. You also have to add your view helper class to 'view_helpers' inside module's config/module.config.php, something like that:

'view_helpers' => array(
    'invokables' => array(
        'nav' => 'Application\View\Helper\Navigation',
    ),
),

Then you can call your 'nav' as a method anywhere inside your view's or layout, for example nav();?>

MaTTo
  • 2,326
  • 5
  • 20
  • 24
3

In your Application/Module.php 1) Create an Dispatch event for zend framework like this:

public function onBootstrap(MvcEvent $e)
{ 
    $eventManager        = $e->getApplication()->getEventManager();
    $eventManager->attach('dispatch', array($this, 'loadConfiguration' ));
}    
public function loadConfiguration(MvcEvent $e)
{           
      $controller = $e->getTarget();
      $controller->layout()->YOUR_VARIABLE_NAME = $YOUR_VALUE;
}

2) Now You can access your defined variable in your layout like this: $this->YOUR_VARIABLE_NAME;

chahat561
  • 91
  • 1
  • 5
1

You can pass global variable to your layout from Application/Module.php in ZendFramework 2 using ModuleManager as below:

In your Application/Module.php

Step 1:

use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\Mvc\MvcEvent;

Step 2:

class Module implements AutoloaderProviderInterface, ConfigProviderInterface
{    
    public function onBootstrap(MvcEvent $e)
    { 
        $eventManager        = $e->getApplication()->getEventManager();
        $eventManager->attach('dispatch', array($this, 'loadConfiguration' ));
    }    
    public function loadConfiguration(MvcEvent $e)
    {           
          $controller = $e->getTarget();
          $controller->layout()->YOUR_VARIABLE_NAME = $YOUR_VALUE;
    }


  // Your remaining code here....

}

Step 3:

In your layout.phtml file use your variable as $this->YOUR_VARIABLE_NAME

I hope this helps.

KumarA
  • 1,368
  • 3
  • 18
  • 41
  • Downvoting here since this code is not working and actually not the right approach either. 1) $controller is undefined, it should be taken from the MvcEvent but it's not. 2) you should access the layout via the controller. Get it directly via the view model of the MvcEvent, as the accepted answer on this question suggests. – Jurian Sluiman Feb 14 '14 at 11:57
  • i just define $controller variable here, now the code OK i think. and sometimes you want to add some global variable to every action from your module. just in case you can go for this approach. like you can add authenticated user variable through this tricks to get your user in every action of your module – Shahadat Hossain Khan Mar 31 '15 at 04:48
0

Why not use inheritance to abstract repeatable configuration via a base controller that sets the layout variables. Since reuse is the main concern here, basic OOP should suffice. Zend doesn't have to do everything :).

F.O.O
  • 4,730
  • 4
  • 24
  • 34