I'm working through the book "Zend Framework - A beginners guide".
Part of the third chapter describes working with a masterlayout.
For my navigation I'd like to set the id-attrib of the body dynamically. How can I get a parameter from any controller to this layout-file?
The master-layout is set in application.ini:
resources.layout.layoutPath = APPLICATION_PATH "/layouts"
resources.layout.layout = master
greetings
Frank
You can use view vars for simple variables you need to pass into layout scripts:
In your controller:
function indexAction()
{
$this->view->pageTitle = "Zend Layout Example";
}
In your layout script:
<html>
<head>
<title><?php echo $this->escape($this->pageTitle); ?></title>
</head>
<body></body>
</html>
The best way to do this, is to use placeholders. Here's an example layout:
master.phtml
------------
<html>
<head>
<title>My Master Layout</title>
</head>
<body id="<?= $this->placeholder('my_dynamic_id_attrib'); ?>">
...
</body>
</html>
Note that the value for the "id" attribute starts with "<?=". This is the same as "<?php echo" and it should work correctly if you're using the default .htaccess file which Zend recommends. If "<?=" does not work for you, simply replace it with:
<body id="<?php echo $this->placeholder('my_dynamic_id_attrib'); ?>">
Now, in your controller, you can set your dynamic id using:
IndexController.php
-------------------
public function indexAction(){
//------------------------------------
// Can either be $_GET or $_POST, etc.
$dynamicParam = $this->_getParam('id');
//------------------------------------
// Set the dynamic id
$this->view->placeholder('my_dynamic_id_attrib')->set($dynamicParam);
}
Related
I am new to zendframework . I am trying to implement two step view lay out:
Bootstrap.php(view/Bootstrap.php)
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
public function _initRoutes()
{
$options = array(
'layout' => 'layout',
'layoutPath' => '/layout/layout.phtml',);
$layout = Zend_Layout::startMvc($options);
}
}?>
layout.phtml(application/view/scripts/layout/layout.phtml)
<?php
include "header.php";
?>
// view contents goes here.
<?php
$this->layout()->content;
?>
// footer goes here.
<?php
include "footer.phtml";
?>
i am a absolute beginner step by step explanation is more appreciated .Thanks.
The easiest way to enable layouts is to run the Zend_Tool command from the command line zf enable layout, this will add the line
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
to your application.ini and build the directory for the layout and the default file layout.phtml.
Alternatively you can specify your layout path and default layout name with 2 lines in your application.ini file:
resources.layout.layoutPath = APPLICATION_PATH "/layouts" //path to layout
resources.layout.layout = master //name of layout without extension
other layout/view options may be set in your application.ini to be callled in your view:
;View Settings
;*************
resources.view[]=
resources.view.charset = "UTF-8"
resources.view.encoding = "UTF-8"
resources.view.doctype = "HTML5"
resources.view.language = "en"
resources.view.contentType = "text/html; charset=UTF-8"
then in your bootstrap.php you can call on these resources to initialize your view:
/**
* initialize the registry and asign application.ini to config namespace
*/
protected function _initRegistry() {
//make application.ini configuration available in registry
$config = new Zend_Config($this->getOptions());
Zend_Registry::set('config', $config);
}
/**
* initialize the view and return it
* #return \Zend_View
*/
protected function _initView() {
//Initialize view
$view = new Zend_View();
//add custom view helper path
$view->addHelperPath('/../library/Application/View/Helper');
//set doctype for default layout
$view->doctype(Zend_Registry::get('config')->resources->view->doctype);
//set default title
$view->headTitle('Our Home');
//set head meta data
$view->headMeta()->appendHttpEquiv('Content-Type', Zend_Registry::get(
'config')->resources->view->contentType);
//set css includes
$view->headLink()->setStylesheet('/css/normalize.css');
$view->headLink()->appendStylesheet('/css/blueprint/src/liquid.css');
$view->headLink()->appendStylesheet('/css/blueprint/src/typography.css');
$view->headLink()->appendStylesheet(
'/javascript/mediaelement/build/mediaelementplayer.css');
$view->headLink()->appendStylesheet('/css/main.css');
$view->headLink()->appendStylesheet('/css/nav.css');
$view->headLink()->appendStylesheet('/css/table.css');
//add javascript files
$view->headScript()->setFile('/javascript/mediaelement/build/jquery.js');
//add it to the view renderer
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer');
$viewRenderer->setView($view);
//Return it, so that it can be stored by the bootstrap
return $view;
}
I also included a convenience method _initRegistry() to make config options available everywhere with minimal code.
The layout in ZF is a simple html page with placeholder added for dynamic or configured options:
<?php
echo $this->doctype() . "\n"; //placeholder assigned in bootstrap $view->doctype
?>
<html>
<head>
<title></title>
<?php echo $this->headMeta() . "\n" //placeholder assigned in bootstrap ?>
<?php echo $this->headLink() . "\n" //placeholder assigned in bootstrap ?>
<?php echo $this->headscript(). "\n" //placeholder assigned in bootstrap?>
</head>
<body>
<section class="container">
<header class="block">
<hgroup id="header" class ="column span-24">
<h1>Our Page</h1>
</hgroup>
<nav>
<div id="nav" class="column span-24">
<?php echo $this->layout()->nav //custom placeholder ?>
</div>
</nav>
</header>
<section class="block">
<div id="main" class="column span-18 border">
<div id="flash">
<?php
//flash messenger display location
if (count($this->messages) > 0) {
printf("<h3 id='flash'>%s</h3>", $this->messages[0]);
}
?>
</div>
<?php echo $this->layout()->content; //placeholder for redering views ?>
</div>
<aside id="sidebar" class="column span-4 last">
<?php echo $this->layout()->search //custom placeholder ?>
<div id="subNav">
<?php echo $this->layout()->subNav //custom placeholder ?>
</div>
<div id="adminMenu">
<?php echo $this->layout()->adminMenu //custom placeholder ?>
</div>
</aside>
</section>
<footer class="block">
<div id="footer" class="column span-24">
<p>Created by <em>Your Name</em> with Zend Framework. © </p>
</div>
</footer>
</section>
</body>
</html>
<?php echo $this->inlineScript() ?> //javascript includes at bottom of page
Hope this helps.
Well first off, youre initializing the layout in a method that would seem to be for your routing - probably a bad idea. Secondly if youre using the full stack with Zend_Application then you can use the provided Zend_Application_Resource_Layout and set all your options from configuration.
Additionally you dont want to use a raw include statement to pull in content you should use $this->render('thetemplate.phtml') from within your layout file. Check out the Zend_Layout Quickstart for more info on that.
My zend layout and scripts are detecting fine. but when in init function of my IndexController I write $this->view->render("header.phtml") It does not show anything one the screen, whereas when I write echo ($this->view->render("header.phtml"); it displays my header.phtml file. Here is my IndexController
class IndexController extends Zend_Controller_Action
{
public function init()
{
$layout = $this->_helper->layout();
//$this->view = $this->getResource('View');
echo ($this->view->render("header.phtml"));
//echo"<pre>";
//var_dump($this->view);
//var_dump(APPICATION_PATH);
}
public function indexAction()
{
// action body
echo "In default index con";
}
}
Also when Igive my url to/mypath/index It does not display the simple line "I'm in index controller" which I'm just echoing. In my bootstrap here is my Zend_Layout settings.
Zend_Loader::loadClass('Zend_View');
$this->view = new Zend_View();
$this->view->setEncoding('UTF-8');
$this->view->setScriptPath($this->root .'/application/default/views/scripts');
$viewRenderer=new Zend_Controller_Action_Helper_ViewRenderer();
// Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
// $view->setScriptPath($this->root.'/'.$theme.'/views/scripts/');
//$view->setScriptPath($this->root.'/application/default/views/scripts/');
$this->view->addScriptPath($this->root.'/application/admin/views/scripts');
$this->view->addScriptPath($this->root.'/application/business/views/scripts');
// $this->view->setHelperPath($this->root .'/application/default/views/helpers');
$this->layout = Zend_Layout::startMvc(
array(
'layoutPath' => $this->root . '/application/default/views/'.$crt_theme.'/layouts',
'layout' => 'layout'
)
);
$this->registry->set("theme", $crt_theme);
variable $crt_theme is set to 'default'.
Rob' answer is correct although you may need some more information as you appear to be working hard at making this complicated. ZF when used as an MVC has a place to put layouts and defaults for using them.
If you are using the Zend_Tool command line interface start with the commmand: zf enable layout and the tool will add the default directory and a default layout.phtml to your project.
in the application.ini it will add the line:
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
and at that path it will add the file layout.phtml
If you need to change the name of the default layout add this line with the name of your script without the .phtml
resources.layout.layout = master
There are as many ways as you can think of to use this file, but here is an example of how I use it.
I like to set my project defaults in my application.ini file so if I need to change anything it's easy.
View Settings
;*************
resources.view[]=
resources.view.charset = "UTF-8"
resources.view.encoding = "UTF-8"
resources.view.doctype = "HTML5"
resources.view.language = "en"
resources.view.contentType = "text/html; charset=UTF-8"
then in my bootstrap I setup the view I want use, I do it here so that if I have multiple layouts (i usually do) it's easy to change css or js files in one place.
protected function _initView() {
//Initialize view
$view = new Zend_View();
$view->addHelperPath('/../library/Application/View/Helper');
$view->doctype(Zend_Registry::get('config')->resources->view->doctype);
$view->headTitle('Our Home');
$view->headMeta()->appendHttpEquiv('Content-Type', Zend_Registry::get(
'config')->resources->view->contentType);
$view->headLink()->setStylesheet('/css/normalize.css');
$view->headLink()->appendStylesheet('/css/blueprint/src/liquid.css');
$view->headLink()->appendStylesheet('/css/blueprint/src/typography.css');
$view->headLink()->appendStylesheet(
'/javascript/mediaelement/build/mediaelementplayer.css');
$view->headLink()->appendStylesheet('/css/main.css');
$view->headLink()->appendStylesheet('/css/nav.css');
$view->headLink()->appendStylesheet('/css/table.css');
//add javascript files
$view->headScript()->setFile('/javascript/mediaelement/build/jquery.js');
$view->headScript()->appendFile('/javascript/modernizr.js');
//add it to the view renderer
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
'ViewRenderer');
$viewRenderer->setView($view);
//Return it, so that it can be stored by the bootstrap
return $view;
}
Notice all of those headLink(), headScript() and docType() entries, these are where the data is set for placeholders, that will be used in the layout.
Now the layout, the actual content from your other action based scripts will typically be rendered by the placeholder $this->layout()->content
<?php
echo $this->doctype() . "\n";//placeholder
?>
<html>
<head>
<title></title>
<?php echo $this->headMeta() . "\n" ?><!-- displays all meta data passed -->
<?php echo $this->headLink() . "\n" ?><!-- displays all links passed -->
<?php echo $this->headscript(). "\n"?><!-- displays all scripts passed -->
</head>
<body>
<section class="container">
<header class="block">
<hgroup id="header" class ="column span-24">
<h1>Our Home</h1>
</hgroup>
<nav>
<div id="nav" class="column span-24">
<?php echo $this->layout()->nav ?> <!-- Custom Placeholder -->
</div>
</nav>
</header>
<section class="block">
<div id="main" class="column span-18 border">
<div id="flash">
<?php
//flash messenger display location
if (count($this->messages) > 0) {
printf("<h3 id='flash'>%s</h3>", $this->messages[0]);
}
?>
</div>
<?php echo $this->layout()->content; ?><!-- Default placeholder, where views are rendered -->
</div>
<aside id="sidebar" class="column span-4 last">
<?php echo $this->layout()->search ?><!-- Custom placeholder -->
<div id="subNav">
<?php echo $this->layout()->subNav ?> <!-- Custom placeholder -->
</div>
<div id="adminMenu">
<h4>Administration Links</h4>
<?php echo $this->layout()->adminMenu ?> <!-- Custom placeholder -->
</div>
</aside>
</section>
<footer class="block">
<div id="footer" class="column span-24">
<p>Created with Zend Framework. © </p>
</div>
</footer>
</section>
<?php echo $this->inlineScript() ?><!-- placeholder -->
</body>
</html>
Hope this helps!
[Edit]
One more thing, this always seems to be the next question. "How do I change my layout from the default in my controller/action?"
to change the layout from your controller you would typically do it with a preDispatch() method and just pass the name of your new layout to the layout helper.
$this->_helper->layout->setLayout('myOtherLayout');
doing just this will change the layout for every action in the controller. To be more selective you can use a conditional, like:
if ($this->getRequest()->getActionName() == 'player') {
$this->_helper->layout->setLayout('player');//reset layout
//add 2 new headscripts
$this->view->headScript()->appendFile(
'http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js'
);
$this->view->headScript()->appendFile(
'/javascript/mediaplayer/jwplayer.js'
);
}
render() is working as intended; it returns a string that you should then echo.
It is very unusual to be rendering directly in a controller however. At a minimum, you should be rendering your header and footer from views/scripts/index/index.phtml, though using Zend_Layout would be even better. If you are using Zend_Application, then you can start using Zend_Layout simply by adding:
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
to your application/config/application.ini file. You then need to create a application/layouts/scripts/layout.phtml file which could look something like this:
<?php
$this->headMeta()->appendHttpEquiv('Content-Type', 'text/html;charset=utf-8');
$this->headTitle()->setSeparator(' - ');
$this->headTitle('My website');
?>
<!DOCTYPE html>
<html>
<head>
<?php echo $this->headMeta(); ?>
<?php echo $this->headTitle(); ?>
<!-- Other <head> elements and view helpers here -->
</head>
<body>
<div id="content">
<?php echo $this->layout()->content; ?>
</div>
</body>
</html>
I implemented a Zend project
And its working fine
Now i tried to implement a layout,
Step 1
for that i created a 'layout.phtml' in the folder 'application/layouts'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<?php echo $this->headTitle(); ?>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<?php $this->layout()->content ;?>
</body>
</html>
step2
Modified the application.ini and added the following line
resources.layout.layoutpath = APPLICATION_PATH "/layouts" under [production]
Step3
Modified the Bootstrap.php, and added the function '_initViewHelpers()'
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{
function _initAutoload()
{
$moduleLoader = new Zend_Application_Module_AutoLoader(
array('namespace'=>'','basePath'=>APPLICATION_PATH)
);
return $moduleLoader;
}
function _initViewHelpers()
{
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();
$view->doctype('XHTML1_STRICT');
$view->headMeta()->appendHttpEquiv('Content-Type', 'text/html;charset=utf-8');
$view->headTitle()->setSeparator(' - ');
$view->headTitle('Zend Framework Tutorial');
}
}
?>
Step4
I took the url in the browser http://localhost/zf_tutorial/public/
It showing the content of layout page but $this->layout()->content is not working (ie index action of index controller)
What is wrong with this code
You need to echo your content.
<?= $this->layout()->content ?> will do what you want!
You need to echo your content. Either you can use
<?= $this->layout()->content ?>
OR
<?php echo $this->layout()->content ?>
I have the following problem, using zend framework, specifically zend_nav to create a reusable menu to be passed in via the layout/layout.phtml page. These are the code fragments in their respective files.
first of in application/configs/navigation.xml,
<configdata>
<nav>
<label>Home</label>
<controller>index</controller>
<action>index</action>
<pages>
<add>
<label>Add</label>
<controller>post</controller>
<action>add</action>
</add>
<login>
<label>Admin</label>
<controller>login</controller>
<action>login</action>
</login>
</pages>
</nav>
</configdata>
this is then passed into an object in the Bootstrap.php file(only showing that specific method)
protected function __initNavigation(){
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();
$config = new Zend_Config_Xml(APPLICATION .'/config/navigation.xml', 'nav');
$container = new Zend_Navigation($config);
$view->navigation($container);
}
and then finally in the view layout.phtml, the object should return the menu
<!-- application/layouts/scripts/layout.phtml -->
<?php echo $this->doctype() ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Zend Blog !</title>
<?php echo $this->headLink()->appendStylesheet('/css/global.css')?>
</head>
<body>
<div id="header">
<div id="header-logo">
<b>Blog Me !</b>
</div>
</div>
<div id="menu">
<?php echo $this->navigation()->menu() ?>
</div>
<div id="content">
<?php echo $this->layout()->content ?>
</div>
</body>
</html>
The menu does however not show up when i start up my app in the browser, any ideas as to might have gone wrong, is humbly received.
If you did not name the function __initNavigation with two _ underscores on purpose then you probably expected the code to run automatically. For it to run automatically you need to use a single underscore.
Another possible problem is that _initNavigation runs before _initView as Zend goes through these resources in alphabetical order. But then you need not access $view in this code. You can use the Zend_Registry to store the navigation container:
protected function _initNavigation() {
$config = new Zend_Config_Xml(APPLICATION .'/config/navigation.xml', 'nav');
$container = new Zend_Navigation($config);
Zend_Registry::set('Zend_Navigation', $container);
}
The Zend_Navigation registry entry will be used by default by any navigation helper when no container is specified.
Well i`m impressed, really quick answers, the problem had several aspects, first of you where both right about using a single underscore sign, thanks a lot the both of you !
And as i t turned out, i did misspell,
$config = new Zend_Config_Xml(APPLICATION .'/config/navigation.xml', 'nav');
should be,
$config = new Zend_Config_Xml(APPLICATION_PATH .'/configs/navigation.xml', 'nav');
my fault. And finally a miss in the navigation.xml file, inside the - node, there should be nodes surrounding each of the "page" nodes, that is for instance for the home. It should have
<configdata>
<nav>
<home>
<label>Home</label>
<controller>index</controller>
<action>index</action>
</home>
That was it !
Again, thanks a lot for your hints and tips i the right direction.
Sinc Kalle Johansson
I think your code is correct, just your protected function __initNavigation()
should use just one _ in your _initNavigation()
Then change __initNavigation() to _initNavigation()
So i'm using the standard Zend Layout for my site. I have a number of custom controllers and views, and the content of these pages is displayed, but the details in the head element of the layout.phtml are not shown. Do i need to manually associate the Zend_Layout with each specific controller?. I expected since the layout is loaded via the bootstrap this should be available for free.
My app.ini file has
# layout
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
resources.layout.layout = "layout"
#resources.view[] =
# Views
resources.view.encoding = "UTF-8"
resources.view.basePath = APPLICATION_PATH "/views/"
my layout.phtml
<?php echo $this->doctype() ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php echo $this->headTitle() ?>
<?php echo $this->jQuery();?>
</head>
<!-- application/layouts/scripts/layout.phtml -->
<body>
<div id="content">
<?php echo $this->layout()->content ?>
</div>
</body>
I am using the following in my Initializer.
Zend_Layout::startMvc(array(
'layoutPath' => $this->_root . '/application/phpancake/layouts',
'layout' => 'main'
));
_root is the path to the directory where the application folder resides.
phpancake is the module name (yours is probably default).
layouts is the directory under which resides my layout file main.phtml