24

i have a layout used by all my views and i need to assign a variable from a controller to this layout , if i use this method on a controller it doesn't work :

public function indexAction()
{
    return new ViewModel( array(
        'testvar' => 'bla',
    ));
}

anyone can help me ?

thanks

Juck
  • 339
  • 1
  • 3
  • 15
  • it will work, how do you try to access 'testvar'? – Sam Nov 13 '12 at 11:56
  • i use $testvar , but i forgot to say the layout is in the folder Application/view/layout , and my controller is in an other module .. maybe it's the problem .. i thought the layouts in application could be used anywhere . – Juck Nov 13 '12 at 12:03
  • 2
    Ah, you want to use the var at layout.phtml and not inside your action view-scripts? – Sam Nov 13 '12 at 12:15

6 Answers6

67

There are three ways to achieve this in ZF2 (in your controller):

First:

$this->layout()->someVariableName = 'Some value for the variable';

Second:

$this->layout()->setVariable('someVariableName', 'Some value for the variable');

Third:

$this->layout()->setVariables(array(
    'someVariableName' => 'Some value for the variable',
    'anotherVariable'  => 'Some value for another variable',
);
Josias Iquabius
  • 1,219
  • 11
  • 11
38

Rob Allen has posted a great article about how to access view variables in another view model (e.g.: layout)

Basically the following code, placed inside your layout.phtml, will match your needs:

<?php
$children = $this->viewModel()->getCurrent()->getChildren();
$child = $children[0];
?>
<!-- some HTML -->
<?php echo $this->escape($child->myvar);?>
Sam
  • 16,435
  • 6
  • 55
  • 89
  • 4
    Thanks for this suggestion, it works - but still looks complicated :/ *blaming-zf2* – MonkeyMonkey Oct 12 '13 at 14:30
  • 1
    @MonkeyMonkey This is because a thing like this shouldn't usually be neccessary. There's better ways (like ViewHelpers / Widgets), than doing this kind of thing. But it can be usable if you really have a use case. – Sam Oct 12 '13 at 15:00
  • I can see how this shouldn't be necessary, but how would you suggest doing it the right way then? Because accessing viewhelpers through the pluginmanager is also against the semantic rules as you can read all around the web. It's pretty common to set a header description/title action-specific--or load some javascript/dom parts based on what API you might need(facebook) that you only might need on a specific action.. – Zaqwsx Oct 30 '13 at 20:36
  • There is a headTitle() ViewHelper - can you further explain your "against semantic rules as u can read all around the web"? This statement appears quite "wrong" :P – Sam Oct 30 '13 at 20:57
  • hehe. what i meant was, accessing viewhelpers in controllers isn't advised and also considered doing it wrong. but like you said, the head* family is there to change the title and meta, and its quite normal to chance the title and description action-wise, for SEO reasons or whatever.. so if accessing viewhelpers in your controller isn't "semantically right", as i named it, how would you do this? – Zaqwsx Oct 31 '13 at 08:14
  • Aaah, now i understand you, well the ViewHelper is for the View, so ultimately, from the Controller i would pass a Variable to the View `return array('title' => $title')` and inside my ViewScript i'd use the viewHelper `$this->headTitle($this->title);` - for the given example, that is. – Sam Oct 31 '13 at 09:22
8

Have you tried:

$this->layout()->testvar = 'bla';

Using the layout controller plugin you can retrieve the ViewModel object that is used in layout.phtml.

DrBeza
  • 2,241
  • 1
  • 16
  • 18
3

Because ZF2 ViewModel is tree structure, the layout actually is the root node of ViewModel, the ViewModel in your controller will be add as a child node of layout.

You could access layout ViewModel by access MvcEvent, try this in your controller:

public function indexAction()
{
    $events = $this->getServiceLocator()->get('Application')->getEventManager();
    $events->attach(MvcEvent::EVENT_RENDER, array($this, 'setVariableToLayout'), 100);
}

public function setVariableToLayout($event)
{
    $viewModel = $this->getEvent()->getViewModel();
    $viewModel->setVariables(array(
        'testvar' => 'bla',
    ));
}
AlloVince
  • 1,655
  • 11
  • 18
1

See the add View Variable section below

add it in your module.php file.

You can also do this using view helper.

/**
     * Remember to keep the init() method as lightweight as possible
     * 
     * @param \Zend\ModuleManager\ModuleManager $moduleManager
     */
    public function init(ModuleManager $moduleManager) 
    {        
        $events = $moduleManager->getEventManager();
        $events->attach('loadModules.post', array($this, 'modulesLoaded'));
        $events->attach('onBootstrap', array($this, 'bootstrap'));

        $sharedEvents = $events->getSharedManager();
        $sharedEvents->attach(__NAMESPACE__, 'bootstrap', array($this, 'bootstrap'), 100);
        $sharedEvents->attach(__NAMESPACE__, 'bootstrap', array($this, 'initializeView'), 100);
        $sharedEvents->attach(__NAMESPACE__, 'dispatch', array($this, 'addViewVariables'), 201);        
    }


/**
 * 
 * @param \Zend\Mvc\MvcEvent $e
 */
public function loadConfiguration(MvcEvent $e) 
{        
    $e->getApplication()->getServiceManager()
            ->get('ControllerPluginManager')->get('AclPlugin')
            ->checkAcl($e); //Auth/src/Auth/Controller/AclPlugin      
}

/**
 * 
 * @param \Zend\EventManager\EventInterface $e
 */
public function bootstrap(Event $e) {

    $eventManager = $e->getParam('application')->getEventManager();
    //$app->getEventManager()->attach('dispatch', array($this, 'checkAcl'), 100);
}

/**
 * pass variables to layout
 * 
 * @param \Zend\EventManager\EventInterface $e
 */
public function addViewVariables(Event $e) 
{
    $route = $e->getRouteMatch();
    $viewModel = $e->getViewModel();
    $variables = $viewModel->getVariables();
    if (false === isset($variables['controller'])) {
        $viewModel->setVariable('controller', $route->getParam('controller'));
    }
    if (false === isset($variables['action'])) {
        $viewModel->setVariable('action', $route->getParam('action'));
    }

    $viewModel->setVariable('module', strtolower(__NAMESPACE__));        
}

/**
 * 
 * @param \Zend\Mvc\MvcEvent $e
 */
public function initializeView(Event $e) 
{

}

and in your layout you can simply access those variables using their name such as $module, $action, $controller according to above example

Developer
  • 25,073
  • 20
  • 81
  • 128
0

If you want to pass values to your layout globally then you can refer this : https://stackoverflow.com/a/21455737/2190889

Community
  • 1
  • 1
KumarA
  • 1,368
  • 3
  • 18
  • 41