Views

View Templates

Bei den Views in CakePHP dreht sich alles um die Kommunikation mit Deinem Nutzer. Meistens werden Deine Views (X)HTML-Dokumente für einen Browser sein. Es ist aber ebenso möglich AMF-Daten für Flash-Objekte zu schicken, einer Remote-Anwendung per SOAP zu antworten oder auch eine CSV-Datei für Deinen Nutzer auszugeben.

CakePHP View-Dateien sind im reinen PHP geschrieben und haben standardmäßig als Dateiendung .ctp (CakePHP Template). Die Dateien enthalten jegliche Logik für die Anzeige der Daten, die sie vom Controller bekommen. Sie sind dafür zuständig diese Daten in einem brauchbaren Format für den Nutzer zu präsentieren.

View-Dateien sind normalerweise in /app/views/ gespeichert, in einem nach dem zuständigen Controller benannten Ordner. Weiterhin repräsentiert der Dateiname die dazugehörige Aktion des Controllers. Beispiel: Die View-Datei für die Aktion „view()“ des „Products“-Controllers befindet sich normalerweise in /app/views/products/view.ctp.

Die View-Ebene in CakePHP besteht aus verschiedenen Teilen. Jeder Teil hat andere Verwendungsmöglichkeiten, die in diesem Kapitel besprochen werden:

  • Layouts: View-Dateien, die Präsentations-Code enthalten, der von vielen Schnittstellen in Deiner Anwendung genutzt wird. Die meisten Views sind in einem Layout gerendert.

  • Elemente: Kleine, wiederverwendbare Codeschnipsel. Sie werden normalerweise innerhalb eines Views gerendert.

  • Helpers (Helfer): Diese Klassen kapseln eine bestimmte Logik, die an vielen Stellen in View-Ebene gebraucht werden. Diese „Helper“ dienen u.a. dazu Formulare zu erstellen, AJAX-Funktionen in Deinen Anwendung zu integrieren, Model-Daten auf verschiedene Seiten aufzuteilen, oder auch RSS-Feeds aus Deiner Anwendung zu liefern.

Layouts

A layout contains presentation code that wraps around a view. Anything you want to see in all of your views should be placed in a layout.

Layout files should be placed in /app/views/layouts. CakePHP’s default layout can be overridden by creating a new default layout at /app/views/layouts/default.ctp. Once a new default layout has been created, controller-rendered view code is placed inside of the default layout when the page is rendered.

When you create a layout, you need to tell CakePHP where to place the code for your views. To do so, make sure your layout includes a place for $content_for_layout (and optionally, $title_for_layout). Here’s an example of what a default layout might look like:

<!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>
<title><?php echo $title_for_layout?></title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<!-- Include external files and scripts here (See HTML helper for more info.) -->
<?php echo $scripts_for_layout ?>
</head>
<body>

<!-- If you'd like some sort of menu to
show up on all of your views, include it here -->
<div id="header">
    <div id="menu">...</div>
</div>

<!-- Here's where I want my views to be displayed -->
<?php echo $content_for_layout ?>

<!-- Add a footer to each displayed page -->
<div id="footer">...</div>

</body>
</html>

$scripts_for_layout contains any external files and scripts included with the built-in HTML helper. Useful for including javascript and CSS files from views.

When using $html->css() or $javascript->link() in view files, specify ‚false‘ for the ‚in-line‘ argument to place the html source in $scripts_for_layout. (See API for more details on usage).

$content_for_layout contains the view. This is where the view code will be placed.

$title_for_layout contains the page title.

To set the title for the layout, it’s easiest to do so in the controller, using the $pageTitle controller variable.

<?php

class UsersController extends AppController {
    function viewActive() {
        $this->pageTitle = 'View Active Users';
    }
}
?>

You can create as many layouts as you wish: just place them in the app/views/layouts directory, and switch between them inside of your controller actions using the controller’s $layout variable, or setLayout() function.

For example, if a section of my site included a smaller ad banner space, I might create a new layout with the smaller advertising space and specify it as the layout for all controller’s actions using something like:

var $layout = 'default_small_ad';

<?php
class UsersController extends AppController {
    function viewActive() {
        $this->pageTitle = 'View Active Users';
        $this->layout = 'default_small_ad';
    }

    function viewImage() {
        $this->layout = 'image';
        //output user image
    }
}
?>

CakePHP features two core layouts (besides CakePHP’s default layout) you can use in your own application: ‘ajax’ and ‘flash’. The Ajax layout is handy for crafting Ajax responses - it’s an empty layout (most ajax calls only require a bit of markup in return, rather than a fully-rendered interface). The flash layout is used for messages shown by the controllers flash() method.

Three other layouts xml, js, and rss exist in the core for a quick and easy way to serve up content that isn’t text/html.

Elements

Many applications have small blocks of presentation code that need to be repeated from page to page, sometimes in different places in the layout. CakePHP can help you repeat parts of your website that need to be reused. These reusable parts are called Elements. Ads, help boxes, navigational controls, extra menus, login forms, and callouts are often implemented in CakePHP as elements. An element is basically a mini-view that can be included in other views, in layouts, and even within other elements. Elements can be used to make a view more readable, placing the rendering of repeating elements in its own file. They can also help you re-use content fragments in your application.

Elements live in the /app/views/elements/ folder, and have the .ctp filename extension. They are output using the element method of the view.

<?php echo $this->element('helpbox'); ?>

Passing Variables into an Element

You can pass data to an element through the element’s second argument:

<?php echo
$this->element('helpbox',
    array("helptext" => "Oh, this text is very helpful."));
?>

Inside the element file, all the passed variables are available as members of the parameter array (in the same way that set() in the controller works with view files). In the above example, the /app/views/elements/helpbox.ctp file can use the $helptext variable.

<?php
echo $helptext; //outputs "Oh, this text is very helpful."
?>

The element() function combines options for the element with the data for the element to pass. The two options are ‚cache‘ and ‚plugin‘. An example:

<?php echo
$this->element('helpbox',
    array(
        "helptext" => "This is passed to the element as $helptext",
        "foobar" => "This is passed to the element as $foobar",
        "cache" => "+2 days", //sets the caching to +2 days.
        "plugin" => "" //to render an element from a plugin
    )
);
?>

To cache different versions of the same element in an application, provide a unique cache key value using the following format:

<?php
$this->element('helpbox',
    array(
        "cache" => array('time'=> "+7 days",'key'=>'unique value')
    )
);
?>

You can take full advantage of elements by using requestAction(). The requestAction() function fetches view variables from a controller action and returns them as an array. This enables your elements to perform in true MVC style. Create a controller action that prepares the view variables for your elements, then call requestAction() inside the second parameter of element() to feed the element the view variables from your controller.

To do this, in your controller add something like the following for the Post example.

<?php
class PostsController extends AppController {
    ...
    function index() {
        $posts = $this->paginate();
        if (isset($this->params['requested'])) {
            return $posts;
        } else {
            $this->set('posts', $posts);
        }
    }
}
?>

And then in the element we can access the paginated posts model. To get the latest five posts in an ordered list we would do something like the following:

<h2>Latest Posts</h2>
<?php $posts = $this->requestAction('posts/index/sort:created/direction:asc/limit:5'); ?>
<?php foreach($posts as $post): ?>
<ol>
    <li><?php echo $post['Post']['title']; ?></li>
</ol>
<?php endforeach; ?>

Caching Elements

You can take advantage of CakePHP view caching if you supply a cache parameter. If set to true, it will cache for 1 day. Otherwise, you can set alternative expiration times. See Caching for more information on setting expiration.

<?php echo $this->element('helpbox', array('cache' => true)); ?>

If you render the same element more than once in a view and have caching enabled be sure to set the ‚key‘ parameter to a different name each time. This will prevent each succesive call from overwriting the previous element() call’s cached result. E.g.

<?php
echo $this->element('helpbox', array('cache' => array('key' => 'first_use', 'time' => '+1 day'), 'var' => $var));

echo $this->element('helpbox', array('cache' => array('key' => 'second_use', 'time' => '+1 day'), 'var' => $differentVar));
?>

The above will ensure that both element results are cached separately.

Requesting Elements from a Plugin

If you are using a plugin and wish to use elements from within the plugin, just specify the plugin parameter. If the view is being rendered for a plugin controller/action, it will automatically point to the element for the plugin. If the element doesn’t exist in the plugin, it will look in the main APP folder.

<?php echo $this->element('helpbox', array('plugin' => 'pluginname')); ?>

The plugin name should be specified in under_score convention.

Viewmethoden

Auf Viewmethoden können von jeder View-, Element- und Layoutdatei aus zugegriffen werden. Um sie zu benutzten wird das Schema $this->method() benutzt.

set()

set(string $var, mixed $value)

Views haben eine set()-Methode, die analog zu set() in Controller-Objekten ist. Diese Methode erlaubt dass Hinzufügen von Variablen zu den viewVars. Das Benutzen von set() in einer eigenen View-Datei fügt diese Variable zum Layout und den Elementen hinzu, die später gerendert werden. Siehe unter Controller::set() für weitere Informationen über set().

In der View-Datei kann folgendes gemacht haben

$this->set('activeMenuButton', 'posts');

Dadurch ist im Layout die Variable $activeMenuButton verfügbar und enthält den Wert ‚posts‘.

getVar()

getVar(string $var)

Liest den Wert der viewVar namens $var aus.

getVars()

getVars()

Liest eine Liste aller View-Variablen im aktuellen Renderiung-Bereich aus. Zurückgegeben wird ein Array der Variablennamen.

error()

error(int $code, string $name, string $message)

Displays an error page to the user. Uses layouts/error.ctp to render the page.

$this->error(404, 'Not found', 'This page was not found, sorry');

This will render an error page with the title and messages specified. Its important to note that script execution is not stopped by View::error() So you will have to stop code execution yourself if you want to halt the script.

element()

element(string $elementPath, array $data, bool $loadHelpers)

Renders an element or view partial. See the section on View Elements for more information and examples.

uuid()

uuid(string $object, mixed $url)

Generates a unique non-random DOM ID for an object, based on the object type and url. This method is often used by helpers that need to generate unique DOM ID’s for elements such as the AjaxHelper.

$uuid = $this->uuid('form', array('controller' => 'posts', 'action' => 'index'));
//$uuid contains 'form0425fe3bad'

addScript()

addScript(string $name, string $content)

Adds content to the internal scripts buffer. This buffer is made available in the layout as $scripts_for_layout. This method is helpful when creating helpers that need to add javascript or css directly to the layout. Keep in mind that scripts added from the layout, or elements in the layout will not be added to $scripts_for_layout. This method is most often used from inside helpers, like the Javascript and Html Helpers.

Themes

You can take advantage of themes, making it easy to switch the look and feel of your page quickly and easily.

To use themes, you need to tell your controller to use the ThemeView class instead of the default View class.

class ExampleController extends AppController {
    var $view = 'Theme';
}

To declare which theme to use by default, specify the theme name in your controller.

class ExampleController extends AppController {
    var $view = 'Theme';
    var $theme = 'example';
}

You can also set or change the theme name within an action or within the beforeFilter or beforeRender callback functions.

$this->theme = 'another_example';

Theme view files need to be within the /app/views/themed/ folder. Within the themed folder, create a folder using the same name as your theme name. Beyond that, the folder structure within the /app/views/themed/example/ folder is exactly the same as /app/views/.

For example, the view file for an edit action of a Posts controller would reside at /app/views/themed/example/posts/edit.ctp. Layout files would reside in /app/views/themed/example/layouts/.

If a view file can’t be found in the theme, CakePHP will try to locate the view file in the /app/views/ folder. This way, you can create master view files and simply override them on a case-by-case basis within your theme folder.

If you have CSS or JavaScript files that are specific to your theme, you can store them in a themed folder within webroot. For example, your stylesheets would be stored in /app/webroot/themed/example/css/ and your JavaScript files would be stored in /app/webroot/themed/example/js/.

All of CakePHP’s built-in helpers are aware of themes and will create the correct paths automatically. Like view files, if a file isn’t in the theme folder, it’ll default to the main webroot folder.

Media Views

Media views allow you to send binary files to the user. For example, you may wish to have a directory of files outside of the webroot to prevent users from direct linking them. You can use the Media view to pull the file from a special folder within /app/, allowing you to perform authentication before delivering the file to the user.

To use the Media view, you need to tell your controller to use the MediaView class instead of the default View class. After that, just pass in additional parameters to specify where your file is located.

class ExampleController extends AppController {
    function download () {
        $this->view = 'Media';
        $params = array(
              'id' => 'example.zip',
              'name' => 'example',
              'download' => true,
              'extension' => 'zip',
              'path' => APP . 'files' . DS
       );
       $this->set($params);
    }
}

Here’s an example of rendering a file whose mime type is not included in the MediaView’s $mimeType array.

function download () {
    $this->view = 'Media';
    $params = array(
          'id' => 'example.docx',
          'name' => 'example',
          'extension' => 'docx',
          'mimeType' => array('docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'),
          'path' => APP . 'files' . DS
   );
   $this->set($params);
}

Parameters

Description

id

The ID is the file name as it resides on the file server including the file extension.

name

The name allows you to specify an alternate file name to be sent to the user. Specify the name without the file extension.

download

A boolean value indicating whether headers should be set to force download. Note that your controller’s autoRender option should be set to false for this to work correctly.

extension

The file extension. This is matched against an internal list of acceptable mime types. If the mime type specified is not in the list (or sent in the mimeType parameter array), the file will not be downloaded.

path

The folder name, including the final directory separator. The path should be absolute, but can be relative to the APP/webroot folder.

mimeType

An array with additional mime types to be merged with MediaView internal list of acceptable mime types.

cache

A boolean or integer value - If set to true it will allow browsers to cache the file (defaults to false if not set); otherwise set it to the number of seconds in the future for when the cache should expire.

modified

Last modified date/time of the file in a format compatible with strtotime(). Defaults to the current time if not set. Example: ‚modified‘ => ‚@‘ . filemtime($filepath)