1. Introduction
    1. About Agavi
    2. MVC in Agavi
    3. Overview of Agavi
    4. Overview of Application Execution Flow
    5. A Word About Actions
    6. Application filesystem layout
    7. Overview of application configuration
  2. Setting Up The Initial Application
    1. Installing Agavi
    2. Creating an Agavi Project
    3. Finishing The Setup
    4. Finishing The Basic Setup
    5. Installing a New Copy of Your Application
  3. Adding First Code
    1. Creating A New module
    2. Creating A New Action
    3. Tying Things Together — An Introduction To Routing
    4. Fixing The Bloggie Routing
    5. Accessing Request Parameters and Validation Basics
    6. Handling Validation Errors
  4. Putting The M in MVC
    1. Creating A New Model
    2. Adapting The Actions and Views
    3. Custom Validators
  5. Polishing It Up
    1. Layers and Layouts
    2. Applying Our Layout
    3. What Are Slots?
    4. Adding The Post's Title To The URL
    5. Routing Callbacks
    6. Using Callbacks for the Title in URLs
  6. Connecting to a database
    1. The Database Manager
  7. Handling Output Variants
    1. Output Types
    2. Exception Templates
    3. Generating an RSS Feed
  8. Form Processing
    1. Adding a Post
    2. Editing a Post
    3. The Form Population Filter (FPF)
  9. Creating a User Authentication System
  10. Adding To The Master Template

Layers and Layouts

Layers are templates that are organized in a matryoshka doll like fashion. Each layer wraps the one a level deeper and has access to the full rendered content and all it's template variables. The innermost layer is the template belonging to the view that was executed. The outer layers are called decorators because it wraps around the output of the inner layer adding content and thus decorating it.

Layers can be created at runtime in the view or predefined. A predefined set of layers is called a layout. Layouts are tied to an output type (we'll explain later what that is) and thus defined in app/config/output_types.xml. Let's go and have a look at the relevant section of our output_types.xml:

<layouts default="standard">
  <!-- standard layout with a content and a decorator layer -->
  <layout name="standard">
    <!-- content layer without further params. this means the standard template is used, i.e. the one with the same name as the current view -->
    <layer name="content" />
    <!-- decorator layer with the HTML skeleton, navigation etc; set to a specific template here -->
    <layer name="decorator">
      <ae:parameter name="directory">%core.template_dir%</ae:parameter>
      <ae:parameter name="template">Master</ae:parameter>
    </layer>
  </layout>
  
  <!-- another example layout that has an intermediate wrapper layer in between content and decorator -->
  <!-- it also shows how to use slots etc -->
  <layout name="wrapped">
    <!-- content layer without further params. this means the standard template is used, i.e. the one with the same name as the current view -->
    <layer name="content" />
    <layer name="wrapper">
      <!-- use CurrentView.wrapper.php instead of CurrentView.php as the template for this one -->
      <ae:parameter name="extension">.wrapper.php</ae:parameter>
    </layer>
    <!-- decorator layer with the HTML skeleton, navigation etc; set to a specific template here -->
    <layer name="decorator">
      <ae:parameter name="directory">%core.template_dir%</ae:parameter>
      <ae:parameter name="template">Master</ae:parameter>
      <!-- an example for a slot -->
      <slot name="nav" module="Default" action="Widgets.Navigation" />
    </layer>
  </layout>
  
  <!-- special layout for slots that only has a content layer to prevent the obvious infinite loop that would otherwise occur if the decorator layer has slots assigned in the layout; this is loaded automatically by ProjectBaseView::setupHtml() in case the current container is run as a slot -->
  <layout name="simple">
    <layer name="content" />
  </layout>
</layouts>

Let's not be confused by the whole block and concentrate on the simplest layout defined in this section.

<layout name="simple">
  <layer name="content" />
</layout>

This layout defines a single layer named "content". It does not pass any other parameters to the layer, most importantly no template is tied to the layer. That means that the template for the current view will be used. This layer would produce only the template's html code as output. We'll use that later on.

The <layouts> tag defines a default layout to use, it's called standard. This is the one we're currently using everywhere, so let's explain what this is about.

<layout name="standard">
  <layer name="content" />
  <layer name="decorator">
    <ae:parameter name="directory">%core.template_dir%</ae:parameter>
    <ae:parameter name="template">Master</ae:parameter>
  </layer>
</layout>
This layout defines two layers, one named "content" that works like the one in the simple layout we've seen above. In addition, it defines a second layer called "decorator" that wraps around the first layer. For this layer we're specifying two parameters - the template's name and the directory to search the template in. The directive %core.template_dir% resolves to app/templates, so let's have a look at app/templates/Master.php.
Tip: Note that the layer's name must be unique within the defined layout but multiple layouts can use the same name. In general it's good practice to use the same name for layers performing the same function.
<!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" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <base href="<?php echo $ro->getBaseHref(); ?>" />
    <title><?php if(isset($t['_title'])) echo htmlspecialchars($t['_title']) . ' - '; echo AgaviConfig::get('core.app_name'); ?></title>
  </head>
  <body>
  <?php if(isset($t['_title'])) echo '<h1>' . htmlspecialchars($t['_title']) . '</h1>'; ?>
  <?php echo $inner; ?>
  </body>
</html>

See how the decorator template accesses the variable _title that we modified ealier - all outer templates can access the the template variables set by the view and the action. Note the special variable $inner - it contains the output of the content-layer. In general $inner contains the output of the previously rendered template with a single exception: for the innermost template ("content" in this case), $inner contains the return value of the view's executeHtml() method.

The last defined layout is a little more complex and we'll only explain it partially. Don't worry, we'll come back later to explain.

<layout name="wrapped">
  <layer name="content" />
  <layer name="wrapper">
    <ae:parameter name="extension">.wrapper.php</ae:parameter>
  </layer>
  <layer name="decorator">
    <ae:parameter name="directory">%core.template_dir%</ae:parameter>
    <ae:parameter name="template">Master</ae:parameter>
    <slot name="nav" module="Default" action="Widgets.Navigation" />
  </layer>
</layout>

Let's forget about the <slot> definition and focus on the rest. We've seen the content and the decorator template before, those should be clear. There's a third layer called "wrapper" that uses the standard template name (the view's name) but a different extension. So in case our view is named PostSuccessView the layer's template will be PostSuccess.wrapper.php.

Loading Layouts

Loading layouts is a simple call to AgaviView::loadLayout(<layoutname>). If you pass "null" as the layout name, the configured default layout will be used. The applications base view that was created when we first created our application does this in it's setupHtml() method.