Simple page rendering class

I have created a simple CPage class, which I use in my non-Yii projects for easily rendering views, templates and whole pages using object-oriented approach. This class can render given contents into given view and embeded it in a selected layout file. These are very limited versions of Yii framework’s view and layout rendering mechanisms. I have also added a simple alerting system, this time taken from Twitter Bootstrap.

To not to mess up, I moved class definition to the end of this post. First, let’s take a look, how to use i:

$page = new CPage;

$page->alert = array
(
    'type'=>'info', //error, success, info or NULL
    'title'=>'Information',
    'message'=>'Example of alerting funtion'
);

$page->title = 'MyApp 1.00';
$page->header = 'Welcome to MyApp application, version 1.00';
$page->footer = 'Copyright (c) 2012 by Me!';
$page->template = 'views/template.html';

$page->render('views/index.php', array
(
    'intro'=>'Some text that comes from engine code, not embeded into a view...'
));

Your view file, mentioned above, can look like this:

<?php echo($intro); ?>

This text comes from a view file, which in fact is a HTML file.

Template file is also a regular HTML file, where you just have to echo (exactly like in above example) title, header, footer, contents and possible alert. Since these elements are extracted out of template, you can modify them directly in PHP code, whenever this is necessary, and you can keep your template (and view) files clean out of all unnecessary PHP code, which makes them far easier to edit by non-PHP people, like designers for example. This is the simplest possible example of code and layout separation.

I think that example with adding alert is quite self-explanatory. You just have to set title, message and type. If these are set, alert will be added on top of any contents (at least in my example, because actually it will be rendered wherever you put <?php echo($alert) ?> in your layout file).

For alerting mechanism to be properly styled, you have to add these (or similar) styles to any of your CSS files, used in your template:

/* Alerts */
.alert
{
    padding: 8px 14px;
    margin-bottom: 20px;
    color: #C09853;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
    background-color: #FCF8E3;
    border: 1px solid #FBEED5;
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
}

.alert-block
{
padding-top: 14px;
padding-bottom: 14px;
}

.alert-success
{
    color: #468847;
    background-color: #DFF0D8;
    border-color: #D6E9C6;
}

.alert-info
{
    color: #3A87AD;
    background-color: #D9EDF7;
    border-color: #BCE8F1;
}

.alert-error
{
    color: #B94A48;
    background-color: #F2DEDE;
    border-color: #EED3D7;
}

.alert-close
{
    float: right;
    font-size: 20px;
    font-weight: bold;
    line-height: 20px;
    color: black;
    text-shadow: 0 1px 0 white;
    opacity: 0.2;
    filter: alpha(opacity=20);
    cursor: pointer;
}

By default, alerts uses an “x” buttons to close them. These buttons are referenced by alert-close class. To add basic behaviour you can use for example this jQuery code:

$(document).ready(function()
{
    $('.alert-close').on('click', function()
    {
        $(this).parent().fadeOut('slow');
    });
});

You’ll have to think yourself a little bit, if your such geek (maniac) to not use jQuery at all. Or if you’re using different Javascript library.

Finally, here goes class definition:

/**
 * Page drawing class.
 */
class CPage
{
    public $alert;
    public $title;
    public $header;
    public $footer;
    public $template;

    /**
     * Renders page, using provided view file, layout and set of variables.
     * 
     * @param boolean $_return_ Whether page should be rendered and echoed or only returned.
     * 
     * @return string           Rendered page contents, filled with variables or throws it to browser.
     */
    public function render($view, $viewData = array(), $return = FALSE)
    {
        $contents = $this->renderPartial($view, $viewData);
        
        $pageData = array
        (
            'contents'=>$contents,
            'header'=>$this->header,
            'footer'=>$this->footer,
            'title'=>($this->title != '') ? $this->title : $this->header,
            'alert'=>(is_array($this->alert)) ? $this->_renderAlert() : ''
        );
        
        $page = $this->renderPartial($this->template, $pageData);
        
        if($return) 
        {
            return $page;
        }
        else echo($page);
    }

    /**
     * Renders view based on given view file and feeds it with passed variables.
     * 
     * @return string   View contents, filled with variables.
     */
    public static function renderPartial($view, $data = array())
    {
        if(is_file($view))
        {
            if(is_array($data)) extract($data, EXTR_PREFIX_SAME, 'data');

            ob_start(); 
            ob_implicit_flush(false); 

            require($view);

            return ob_get_clean();
        }
        else die('File <strong>"'.$view.'"</strong> does not exist!');
    }

    /**
     * Renders alert div, if it is set.
     * 
     * @return string   View contents, filled with variables.
     */
    private function _renderAlert()
    {
        if(is_array($this->alert))
        {
            $aData = $this->alert;
            
            $aText = 
            '
                <div class="alert alert-block alert-'.$aData['type'].'">
                    <a class="alert-close">×</a>
                    <strong>'.$aData['title'].'</strong> '.$aData['message'].'
                </div>
            ';
        }
        else $aText = '';
        
        return $aText;
    }
}

I often use above class with my nifty function for rendering dropdown lists. But, only in non-Yii applications, which I try to limit to the minimum. Because… coding web applications or web pages with Yii is a dream!

Leave a Reply