As mentioned in the introduction, layouts are typically shared by
the entire application and wrap around a controller's view. A layout
usually contains common page elements such as the header, footer,
navigation, and the content area where the view's output is
displayed. Layouts are often divided into separate sub-layouts. For example, the head
section of your page may be one sub-layout, the global navigation
another, and so forth. A single, parent layout file contains all the references
to the sub-layouts. Your application can specify this parent layout using
the protected $_layout_default
property.
The graphic below shows the relationship between the parent layout file, represented by the outer, yellow box, and each sub-layout. The positioning of each container is typically accomplished using Cascading Style Sheets (CSS).
Let's make the blog demo created in chapter one look like the example graphic above.
The first thing we need to do is specify which layout our blog
application will use. Remember that the Acme_App_Blog
application extends the Acme_Controller_Page
class.
Browse to the
folder and edit the SYSTEM
/source/acme/Acme/ControllerPage.php
file.
$cd
$SYSTEM
/source/acme/Acme/Controller/vim Page.php
Add the following text to the class so it looks like the code below.
<?php
abstract class Acme_Controller_Page extends Solar_Controller_Page
{
/**
*
* Sets up the Acme_App environment.
*
* @return void
*
*/
protected function _setup()
{
parent::_setup();
// set the default layout for all applications that
// extend Acme_Controller_Page
$this->_layout_default = 'blog';
}
}
?>
Note | |
---|---|
You can also accomplish this by defining the protected
|
The default layout is blog.php
and is located in the
folder.
SYSTEM
/source/acme/Acme/Controller/Page/Layout
$cd
$SYSTEM
/source/acme/Acme/Controller/Page/Layoutvim blog.php
Copy and paste the following into the blog.php
file.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<?php
// generate the <head>
include $this->template('_head.php');
?>
<?php
// generate the <body>
include $this->template('_body.php');
?>
</html>
This is our main layout script. Within this layout are references
to two sub-layouts, namely _head.php
and
_body.php
.
Now you need the _head.php
. Assuming you are still in the
folder,
create the SYSTEM
/source/acme/Acme/Controller/Page/Layout_head.php
file.
$ vim _head.php
Copy and paste the following text into the file and save.
<head>
<?php
// use the Solar_View_Helper_Head::head() helper
// add a base stylesheet, then set any other head elements
echo $this->head()->addStyleBase('Acme/Controller/Page/styles/blog.css')
->fetch();
?>
</head>
This layout script is responsible for the content between the
<head></head>
tags. It relies on the
Solar_View_Helper_Head
view helper to set the main stylesheet, and
display any other head elements. See the API documentation on the
Solar_View_Helper_Head
view helper.
Assuming you are still in the
folder, create the SYSTEM
/source/acme/Acme/Controller/Page/Layout_body.php
file.
$ vim _body.php
Copy and paste the following text into the file and save.
<?php // set the id of the body tag. Handy for css and javascript ?>
<body id="<?php echo "{$this->controller}-page" ?>">
<div id="wrap">
<div id="header">
<?php include $this->template('_header.php'); ?>
</div>
<div id="nav">
<?php include $this->template('_nav.php'); ?>
</div>
<div id="main">
<?php // Add the content from the application controller ?>
<?php echo $this->layout_content; ?>
</div>
<div id="footer">
<?php include $this->template('_footer.php'); ?>
</div>
</div>
</body>
This layout script defines the structure of the page. A cascading
stylesheet will define the styles for each page element. Each
element of the page, such as the header, gets it's own sub-layout script. The
output from an application controller's action is injected into the
layout via the $this->layout_content
property.
Assuming you are still in the
folder, create the SYSTEM
/source/acme/Acme/Controller/Page/Layout_header.php
file.
$ vim _header.php
Copy and paste the following text into the file and save.
<div id="branding">
<h1>The Acme Blog</h1>
</div>
This simple sub-layout creates the header banner at the top.
Now create the _footer.php
file in the same folder.
$ vim _footer.php
Copy and paste the following text into the file and save.
<div id="footer">
<p>Copyright © 2010 Acme</p>
</div>
This simple sub-layout creates the footer at the bottom.
Next, we need some sort of navigation element. Assuming you are still in the
folder, create the SYSTEM
/source/acme/Acme/Controller/Page/Layout_nav.php
file.
$ vim _nav.php
Copy and paste the following text and save.
<div id="nav">
<ul>
<li><?php echo $this->action('blog', 'Blog Home'); ?></li>
<li><?php echo $this->action('blog/add', 'ACTION_ADD'); ?></li>
<li><?php echo $this->action('blog/drafts', 'View Drafts'); ?></li>
</ul>
<?php // allow for extra local navigation
include $this->template('_local.php');
?>
</div>
Notice the reference to the _local.php
sub-layout.
Adding this sub-layout lets us optionally add extra navigation for each
controller. This will become clearer later on in this chapter.
Note | |
---|---|
The second list item in the navigation layout uses a locale key as the link text.
Please see the API documentation on the
|
In the same folder, create the _local.php
file.
$ vim _local.php
Copy and paste the following text and save.
<?php
// placeholder for local navigation
All the layout elements are now in place. A quick view of the
folder should show the following files:
SYSTEM
/source/acme/Acme/Controller/Page/Layout
Acme/Controller/Page/ Layout/ _body.php _footer.php _head.php _header.php _local.php _nav.php blog.php
Note | |
---|---|
Though not a requirement, prefixing partials and nested views/layouts with an underscore helps you easily identify them. |
Browsing to the blog application at this point might leave you
visually disappointed. In the _head.php
file, we referenced a
stylesheet called blog.css
. This style sheet is responsible for positioning our
page elements and setting fonts and colors. Let's create it now.
First, create a folder called 'styles' in the
folder.
SYSTEM
/source/acme/Acme/Controller/Page/Public
$cd ../Public
$mkdir styles
$cd styles
Next, create a css file called blog.css
in that newly created
folder.
$ vim blog.css
Copy and paste the following into the blog.css
file and save.
body, html {
margin: 0;
padding: 0;
color: #000;
background-color: #fff;
font-family: sans-serif;
font-size: 10pt;
}
#wrap {
width: 750px;
margin:0 auto;
background-color: #ccc;
}
#header {
background-color: #666;
margin: 0px;
color: #fff;
margin-top: 10px;
}
#header h1 {
margin: 0;
padding: 10px;
}
#nav {
background-color: #ccc;
width: 150px;
float: left;
}
#main {
float: left;
width: 580px;
background-color: #efefef;
padding: 10px;
min-height: 400px;
}
#main h2 {
margin-top: 0px;
padding-top: 0px;
}
#footer {
background-color: #000;
color: #fff;
font-weight: bold;
clear: both;
padding: 5px;
}
#footer p {
padding: 0px;
margin: 0px;
}
You should now have the following:
Acme/Controller/Page/ Public/ styles/ blog.css
Note | |
---|---|
The |
A quick browse to the blog (http://localhost/blog) should show a screen similar to the image below.
Because layouts are shared, they greatly reduce duplication of
code. However, there may be times when you want to alter a page
element for one particular application. The modular approach to the layout and
Solar's class stack (hierarchy of classes) makes this an easy task.
For example, if we wanted to have application-specific links below the main
navigation, we could easily do this by overriding the _local.php
layout script.
Create a new _local.php
layout file in the
folder.
SYSTEM
/source/acme/Acme/App/Blog/Layout
$cd
$SYSTEM
/source/acme/Acme/App/Blog/Layoutvim _local.php
Add the following text and save.
<ul>
<li><a href="#">Local Item One</a></li>
<li><a href="#">Local Item Two</a></li>
</ul>
Now, refresh the browser and you should notice how the left
navigation has changed. Here, the original _local.php
layout script
in the
folder is overridden by the SYSTEM
/source/acme/Acme/Controller/Page/Layout_local.php
layout script in
.
SYSTEM
/source/acme/Acme/App/Blog/Layout
Solar uses the file that is most closely related to the application, then, if it doesn't find what it's looking for, will work its way up the class stack (hierarchy).
An example of the class stack for layouts would like this:
Array
(
[0] => Acme/App/Blog/Layout
[1] => Acme/Controller/Page/Layout
[2] => Solar/Controller/Page/Layout
)
Note that Acme_App_Blog
extends Acme_Controller_Page
, which
extends Solar_Controller_Page
. Knowing this may help you understand
how the class stack is built.
Note | |
---|---|
You can also turn the layout off by setting |