Can a View in Kohana access its parent View's variables? - php

This applies to Kohana 2.3.2
I've recently started making my Views more dynamic. Using the default template view as a base, now I am doing in the controller
$this->template->innerView = new View('article');
Then, in the middle of my template.php, I have
<?php echo $innerView; ?>
To echo the 'guts' of the article view between my header and footer. This works fine, except all the vars I defined to$this->template are inaccessible from the new view. I know I could probably do
$this->template->innerView->title = 'My Title';
But if there was a way to make child Views inherit their parent's variables, that would be great.
Is there?

The set_global() method only sets the variable to be global across all views. It's not what you think when you hear "Global" in PHP so you got it right, this is exactly what you should use when you want to make a variable available across multiple views.

http://docs.kohanaphp.com/core/view#set_global
I needed this because I use the page title in the normal template (for within <title></title>) and also as the <h2></h2> of the page.
It's as simple as this
$this->template->innerView = new View('article');
$this->template->set_global('title', 'My Title');

Related

How can I propagate a View Helper variable to a distant View child in ZF2, without using pass-through code?

I do not have full ZF2 stack but I rigged my mostly-non-ZF2 code to accept $this->partial() and ViewModel() methods.
I often find a situation where I have a tree of View Helper Partials, to where some distant-from-root child needs a variable someVar.
I manage that variable passing it through each partial from root to the child, even when the in-route partials have no need for it.
Is there a way to not have to manage the var?
Example
//controller.php
echo $this->partial('root.phtml', array('someVar' => $someVar));
//root.phtml
<?
//this variable-pass-through-only step is one I would like to eliminate.
//aka. here someVar is not itself used in root.phtml
//it is only passed onto the child view partial
//I want to eliminate this pass-through-only code.
echo $this->partial('child.phtml', array('someVar' => $this->someVar)):
?>
//child.phtml - leaf child
<?
//variable is actually used for display purpose
echo $this->someVar;
?>
I am open to answers that use non-partial construct, i.e. ViewModel, etc.
Note: when I remove the pass-through code, hoping there is some kind of global scope for vars, it is not the case - the variable does not pass onto the child leaf view partial. I am hoping there is some kind of a better approach in ZF2 for what I want to do.
Goal / Spirit of the Question
To be clear I am seeking a way to make some vars to be a "global" var that extends itself from root of partial/view to the leaf .phtml without pass-through code, or perhaps a different approach altogether to where I do not need to do this, and yet not clutter my code with pass-through vars
You can use nested ViewModel instances to replicate the functionality of the partial view helper. By having the objects independently created there is no need to pass all variables to each of them.
A simple example.
$main = new ViewModel(['var1' => 'xyz', 'var2' => 'xyz']);
$main->setTemplate('main.phtml');
$foo = new ViewModel(['baz' => 'bob']);
$foo->setTemplate('foo.phtml');
$bar = new ViewModel(['test' => 123]);
$bar->setTemplate('bar.phtml');
// foo.phtml should echo $this->barResultHtml
$foo->addChild($bar, 'barResultHtml');
// main.phtml should echo $this->fooResultHtml
$main->addChild($foo, 'fooResultHtml');
// You will need to set this up to render the view model.
$view = new Zend\View\View();
$view->setRenderer(...);
echo $view->render($main);

Different views in one

I´m working on a project using lithium framework and I need to be able to have different views in a "MAIN" view.
For example. I have to be able to see the post and events forms (add a new event and a new post) in the principal view.
I actually have the view for add a new post and a new event. I´m looking the way to include this views in the main one.
Any idea of how to solve this?
Thanks in advance
$this->_render() is used within the views to include elements. Any variables passed from the controller to the parent view are also available in the element. The third argument of $this->_render() can be used to pass additional variables.
<?php
// renders app/views/elements/nav.html.php
echo $this->_render('element', 'nav');
?>
Relative pathing works, so if you want to reuse a template from say app/views/events/add.html.php, you can do this:
<?=$this->_render('element', '../events/add'); ?>

Global component in Symfony

I am currently implementing the navigation of the website (multilevel menu, having current page highlighted).
As navigation part will be included for virtually all modules, I first made it a global partial.
But logic for selection of "current page" is quite complicated in some situations, I am thinking of using a component for the navigation.
The problem is that symfony allows to have global partials, but not global components.
So is there a "nice symfony way" to do this?
There isn't a mechanism for this as such. I usually end up creating an empty module called default and putting stuff like that in there.
What's wrong with:
<?php include_component('someModule', 'navigationComponent') ?>
... where you store it in some general module (e.g. "general") and call it wherever you want, including your layouts. Isn't that global enough?
This is your solution:
Create the yourproject/yourapp/templates/_globalpartial.php with this content:
<?php include_component('yourmodule', 'yourcomponent'); ?>
And use this globalpartial.php in yourproject/yourapp/templates/layout.php

How do you create variables in actions.class.php so that they are accessible in layout.php?

In Symfony 1.2, how do you create variables in actions.class.php so that they are accessible in layout.php?
This page has some information about it: http://trac.symfony-project.org/wiki/Symfony11LayoutUpgrade
It seems you can get the desired effect using this following code:
$this->getResponse()->setSlot('title', 'insert your title here');
And then use this in the layout file:
<title><?php echo get_slot('title') ?></title>
I think, by default, you can't, since it should be against the MVC pattern.
You should better pass variable to your view, but without using global (or kind of).

CakePHP View including other views

I have a CakePHP application that in some moment will show a view with product media (pictures or videos) I want to know if, there is someway to include another view that threats the video or threats the pictures, depending on a flag. I want to use those "small views" to several other purposes, so It should be "like" a cake component, for reutilization.
What you guys suggest to use to be in Cake conventions (and not using a raw include('') command)
In the interest of having the information here in case someone stumbles upon this, it is important to note that the solution varies depending on the CakePHP version.
For CakePHP 1.1
$this->renderElement('display', array('flag' => 'value'));
in your view, and then in /app/views/elements/ you can make a file called display.thtml, where $flag will have the value of whatever you pass to it.
For CakePHP 1.2
$this->element('display', array('flag' => 'value'));
in your view, and then in /app/views/elements/ you can make a file called display.ctp, where $flag will have the value of whatever you pass to it.
In both versions the element will have access to all the data the view has access to + any values you pass to it. Furthermore, as someone pointed out, requestAction() is also an option, but it can take a heavy toll in performance if done without using cache, since it has to go through all the steps a normal action would.
In your controller (in this example the posts controller).
function something() {
return $this->Post->find('all');
}
In your elements directory (app/views/element) create a file called posts.ctp.
In posts.ctp:
$posts = $this->requestAction('posts/something');
foreach($posts as $post):
echo $post['Post']['title'];
endforeach;
Then in your view:
<?php echo $this->element('posts'); ?>
This is mostly taken from the CakePHP book here:
Creating Reusable Elements with requestAction
I do believe that using requestAction is quite expensive, so you will want to look into caching.
Simply use:
<?php include('/<other_view>.ctp'); ?>
in the .ctp your action ends up in.
For example, build an archived function
function archived() {
// do some stuff
// you can even hook the index() function
$myscope = array("archived = 1");
$this->index($myscope);
// coming back, so the archived view will be launched
$this->set("is_archived", true); // e.g. use this in your index.ctp for customization
}
Possibly adjust your index action:
function index($scope = array()) {
// ...
$this->set(items, $this->paginate($scope));
}
Your archive.ctp will be:
<?php include('/index.ctp'); ?>
Ideal reuse of code of controller actions and views.
For CakePHP 2.x
New for Cake 2.x is the abilty to extend a given view. So while elements are great for having little bits of reusable code, extending a view allows you to reuse whole views.
See the manual for more/better information
http://book.cakephp.org/2.0/en/views.html#extending-views
Elements work if you want them to have access to the same data that the calling view has access to.
If you want your embedded view to have access to its own set of data, you might want to use something like requestAction(). This allows you to embed a full-fledged view that would otherwise be stand-alone.
I want to use those "small views" to
several other purposes, so It should
be "like" a cake component, for
reutilization.
This is done with "Helpers", as described here. But I'm not sure that's really what you want. The "Elements" suggestion seems correct too. It heavily depends of what you're trying to accomplish. My two cents...
In CakePHP 3.x you can simple use:
$this->render('view')
This will render the view from the same directory as parent view.

Categories