Skip to content

Instantly share code, notes, and snippets.

@dwayne
Forked from eric1234/README.md
Created June 23, 2013 10:40
Show Gist options
  • Save dwayne/5844572 to your computer and use it in GitHub Desktop.
Save dwayne/5844572 to your computer and use it in GitHub Desktop.
A better way of doing layouts in PHP

Usage

Creating a Layout File

Create a file called layout.php. Where you want the content to appear add <?php echo $content ?>. Here is an example:

<!DOCTYPE html>
<html>

<head>
  <title><?php echo $title ?></title>
</head>

<body>
  <div id="page">
    <?php echo $content ?>
  </div>
</body>
</html>

This should be placed in the same directory a your scripts.

Using the Layout File

Now just add the following to the top of every script (or some include the scripts pull in):

<?php require_once 'layout.php'; ?>

Any content outputted in your script will be placed where $content is outputted.

Configuration

The $title variable is automatically pulled into the layout scope. To set the title simply place the following in your script:

<?php $title = 'Home page' ?>

You can place this before or after the layout require.

If you want to change where the layout file is located just set the $layout variable before calling layout. For example:

<?php
  $layout = __DIR__.'/path/to/layout.php';
  require_once 'layout.php';
?>

Content Filters

This script provides an excellent opportunity to apply a filter to the entire output. Similar to an after_filter in Rails. Simply add a callback function to the global variable $content_filters. You can do this before the call to layout.php (so you are defining $content_filters or after by simply appending. Example:

<?php
  require_once 'layout.php';
  $content_filter[] = 'adjust_markup';
?>

The callback should take the HTML as input and return the final HTML. Content filters only apply to the $content and not the layout. Also if the layout is not used then the content filters are not called.

Handling Redirects

Redirects are automatically handled. If you set the Location header and exit the layout script will automatically avoid rendering the layout and instead just exit.

<?php
# https://gist.github.com/2151128
if( !array_key_exists('layout', get_defined_vars()) )
$layout = realpath('./layout.php');
$use_layout = true;
if(is_null($layout)) $use_layout = false;
function apply_content_filters($in) {
global $content_filters;
foreach($content_filters as $filter) {
$in = call_user_func($filter, $in);
}
return $in;
}
if( !isset($content_filters) ) $content_filters = array();
if( $use_layout ) ob_start();
function layout_shutdown() {
global $layout;
global $use_layout;
global $error_triggered;
if( !$use_layout ) return;
$content = apply_content_filters(ob_get_contents());
ob_end_clean();
if( $error_triggered || is_null($layout) ) {
echo $content;
return;
}
foreach(headers_list() as $header)
if( preg_match('/^Location/', $header) ) return;
global $title;
require $layout;
}
register_shutdown_function('layout_shutdown');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment