Skip to content

Dev.Theme Structure

taiwen edited this page Mar 14, 2013 · 1 revision

Contents

  • Introduction
  • File structure
  • Layout templates
  • Introduction of some useful view helpers
  • Predefine variables

Introduction

Theme is used to define the layout, interaction and css of your site. Pi allows you to create different themes for different modules or Pi application itself. Users can create a theme package and put it into the usr/theme directory where themes can be detected. Theme packages mainly contain several front files such as js, css, phtml, etc. These files are packed in different folders. In this guide, we will introduce how to create a theme package and how to use helpers in Pi and Zend library to achieve your tasks.

The structure of this guide is organized as follows:

  1. Section I introduces the file structure of theme package;
  2. Section II introduces the usage of helpers packed in Pi library;
  3. Section III lists the predefine variables of Pi.

File structure

The theme folder is consists of a series of folders, such as asset, locale, module, template and config.php. The structure is list as follows:

theme
    default {theme package name}
        asset
            css
            image
            js
        locale
            en
         module
            demo {module theme package name}
                asset
                template
        template
            {phtml files}
        config.php
  • asset - contains js, css and image files which will be published to Pi/www folder when installs, these files will override static files of modules.
  • locale - contains translation files.
  • module - contains theme packages for modules, files in these themes will also override that of module when installs.
    • demo - contains asset and template folders, it is the theme for modules.
  • template - contains phtml files for displaying layout. These files mainly include HTML tags.
  • config.php - defines the details of the theme by array.

NOTE: This is a complete structure of a theme package, a theme set at least should includes following files:

  • Template files required for front:
    • template/layout-front.phtml - complete layout template: header, footer, body, blocks, navigation;
    • template/layout-simple.phtml - error page layout: header, footer, body;
    • template/layout-style.phtml - content with stylesheets;
    • template/layout-content.phtml - raw content without stylesheets.
  • Template files required for admin:
    • template/layout-admin.phtml - backoffice layout.
  • Stylesheet files required:
    • asset/css/style.css - main css file;
    • asset/css/form.css - generic form css file.

config.php

As we mentioned above, this file defines basic information of the theme, codes in the file are:

return array(
    'version'       => '1.0.0',
    'title'         => 'Pi Theme',
    'author'        => 'Pi Development Team',
    'screenshot'    => 'image/screenshot.png',
    'license'       => 'Creative Common License http://creativecommons.org/licenses/by/3.0/',
    'active'        => true,
    'type'          => 'both', // Potential value: 'both', 'admin', 'front', default as 'both'
    'description'   => 'Default theme for Pi',
);
  • screenshot - theme thumbnail for user to view;
  • type - defines the type of layouts available in the theme, its potential value can be both, admin and front, if the field is not set, both value will be used as default.

module package

As we know, packages in module folder is used to define theme for modules, therefore, template files in template folder has the same name as that of module templates. These packages should have a structure such as:

module
    {module theme name}
        asset
            js
            image
            css
        template
            {template files}

Layout templates

In the template folder, some template files are needed for displaying pages for this application. These files define themes of front-end, admin-end and error pages.

layout-front.phtml

This template is used to display the homepage of front-end, it's a complete html page which includes doctype, head and body. View helpers that we will introduce later can be used to load HTML tags <head>, <meta> and <script>.

The body of the page is divided into several parts, they are used to display blocks and module. Here we use a table to simple show the body layout of page:

+--------------------+---------------+---------------+---------------+--------------------+
|                    |               |               |               |                    |
|                    |    Zone 2     |    Zone 3     |    Zone 4     |                    |
|                    |               |               |               |                    |
|                    +---------------+---------------+---------------+                    |
|                    |                                               |                    |
|       Zone 1       |                     Module                    |      Zone 8        |
|                    |                                               |                    |
|                    +---------------+---------------+---------------+                    |
|                    |               |               |               |                    |
|                    |    Zone 5     |    Zone 6     |    Zone 7     |                    |
|                    |               |               |               |                    |
+--------------------+---------------+---------------+---------------+--------------------+

This layout can be simply described by the following codes:

<!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" xml:lang="<?php echo $locale ?>" lang="<?php echo $locale ?>">
    <head>
        <?php echo $this->headTitle() ?>
        <?php echo $this->headMeta() ?>
        <?php echo $this->headLink() ?>
        <?php echo $this->headScript() ?>
    </head>
    <body>
        <!-- Header: logo here -->
        <div>...</div>

        <!-- Global navigation -->
        <?php // use navigation() helper to output navigation ?>      

        <!-- Load blocks -->
        <?php $blocks = $this->blocks()?>
        <table cellspacing="0">
            <tr>
                <!-- Left blocks loop -->
                <?php if (isset($blocks['1'])) {?>
                    <td id="Pi-zone-1">
                        <?php // display blocks ?>
                    </td>
                <?php }?>

                <td id="Pi-zone-center">
                    <!-- Display center blocks if any -->
                        <table cellspacing="0">
                            <!-- Display center-center blocks if any --> ...
                            <!-- Display center-left blocks if any --> ...
                            <!-- Display center-right blocks if any --> ...
                        </table>

                    <!-- Content module page -->
                    <?php if (!empty($content) && ($content != ' ')) {?><div id="Pi-content"><?php echo $content?></div><?php }?>

                    <!-- Start center bottom blocks loop --> ...                                     
                </td>

                    <!-- Right blocks loop --> ...
            </tr>
        </table>       

        <!-- Footer -->
        <div>...</div>
    </body>
</html>

Pi provides us a navigation() helper for displaying navigation, all navigation data are stored in database when installs, so this only users need to do is call this helper, and it will output navigation automatically.

<?php $navigation = $this->navigation('front', true);?>
<?php if ($navigation) { ?>
<div class="Pi-topbar">
    <div id="Pi-top-menu"><?php echo $navigation->menu()->setUlClass('jd_menu');?></div>
    <div id="Pi-top-navigation"><?php echo $navigation->breadcrumbs()?></div>
</div>
<?php } ?>

This code will output a navigation with css if you have set class jd_menu.

The contents of blocks are acquired by calling helper blocks(), then the block.phtml template will be included to display blocks. The template block.phtml will be introduced later.

For example:

<?php $blocks = $this->blocks()?>
    <table cellspacing="0">
        <tr>
            <?php if (isset($blocks['1'])) {?>
                <td id="Pi-zone-1">
                <?php foreach ($blocks['1'] as $key => $block) {?>
                    <?php include $this->template('block.phtml');?>
                <?php }?>
                </td>
            ...
        </tr>
    </table>

In the code, the blocks() method helps to load all the blocks' information of this page for later displaying if they are set.

NOTE: it is strongly recommended to use Pi- as prefix for all id's used in theme to avoid conflicts.

layout-admin.phtml

The layout-admin.phtml is used to display homepage of admin-end. This template is also a complete page which is as same as layout-front.phtml. But this page does not be divided into blocks and module.

NOTE: remember to set the parameter of navigation to admin.

<?php $navigation = $this->navigation('admin', true);

block.phtml

The block.phtml template is used to display the content of blocks. It is included in the layout-front.phtml file by the php method include. The codes of this file may be:

<div id="Pi-block-<?php echo $block['name'] ?: $block['id']; ?>" class="block-container<?php if (!empty($block['class'])) { echo ' ' . $block['class']; }?>">
    <fieldset>
        <?php
        if (!empty($block['title'])) {
            if (!empty($block['link'])) {
                $title = sprintf('<a href="%s" title="%s">%s</a>', $block['link'], $block['title'], $block['title']);
            } else {
                $title = $block['title'];
            }
            printf('<legend class="block-title">%s</legend>', $title);
        }
        ?>
        <div class="block-content"><?php echo $block['content']?></div>
    </fieldset>
</div>

The variable $block here is defined in the layout-front.phtml file.

page-zone.phtml

This template is used for block manipulation on a page.

In the default theme package, Pi provides us several templates for displaying simple pages, they are:

layout-content.phtml

This template simply displays content.

<?php echo $content ?> 

layout-simple.phtml

This template displays main content as well as HTML <head> element and page header.

layout-style.phtml

This template displays main content as well as HTML <head> element.

The following templates are used when errors occur.

error-404.phtml

This template is used to list the errors when a 404 error occurs.

error-index.phtml

This template is used to list errors and exceptions when they occur.

denied.phtml

This template displays a deny message when user have no permission to request the page.

Introduction of some useful view helpers

You might found that you have troublesomely wrote scripts in your view page over and over when code without framework, fortunately, Pi provides us with plenty of view helpers to complete your work quickly and conveniently.

A helper is simply a class that implements the interface Zend\View\Helper. Helpers of Pi inherit from that of Zend Framework 2. Helper simply defines two methods, setView(), which accepts a Zend\View\Renderer instance/implementation, and getView(), used to retrieve that instance. Zend\View\PhpRenderer composes a plugin broker, allowing you to retrieve helpers, and also provides some method overloading capabilities that allow proxying method calls to helpers.

For example, if we create a class called js in the Pi/View/Helper/js.php or Zend/View/Helper/js.php and add a __invoke() method, then we can use the method in the phtml file.

$this->js(); 

asset

The asset folder of theme is used to store static file, such as js, css and images. This folder will be published to the www folder of Pi, so the static files can be requested by users. The asset helper helps for building an asset URI, then we can use this URI to request the file. for example, you can write the following codes in your phtml file:

$this->asset('theme/default', 'css/style.css');

This code will return a string such as http://localhost/Pi/www/asset/theme-default/css/style.css if you set your Pi folder's name to Pi.

The first parameter of this helper is a string describes the name of component. This string consists of two parts connected by characters exclude letters (a-z, A-Z), numeral (0-9) and dash (-), a slash (/) is recommended. The previous part of the string should be theme or module which contains asset folder and the later part is the name of theme or module.

The second parameter is the file name you want to build.

echo $this->asset('module/demo', 'js/demo.js');

Output:

'http://localhost/Pi/www/asset/module-demo/js/demo.js'

Other example:

<img src="<?php echo $this->asset('module/demo', 'image/logo.png'); ?>" />

assetLocale

This helper is used to build locale asset URI inside current theme. It takes three parameters: the first one indicates the file name, the second one indicates the locale file to choose, if it is not set, the system locale will be used, and the third one decides whether to append version for file path.

echo $this->assetLocale('style.css');
echo $this->assetLocale('js1.js', 'Zh-CN', false);

If the system locale is gray:'en', and current theme is 'default', the code above will output:

'http://localhost/pi/www/asset/theme-default/locale/en/style.css?1355197213'
'http://localhost/pi/www/asset/theme-default/locale/Zh-CN/js1.js'

NOTE: users should check the Append version checkbox in general configuration page to enable versioning.

assetModule

This helper is more conveniently to build a URI for module, because you can only assign the file name if you want to get a URI for current module. This helper takes two parameters, the first parameter should be assigned with a file name string, and the second parameter is a module name string, this parameter can be ignored if you build a URI for current module. If you want to build a URI of other module, you must assign the module name to the second parameter.

This helper will also return a string contain an asset URI of a module.

For example, supposing you add a phtml file in a module call demo with following code:

echo $this->assetModule('js/demo.js');

It will output the following URI:

'http://localhost/Pi/www/asset/module-demo/js/demo.js'

Now if you want to build a URI of other module, such as article, you should assign the second parameter such as:

echo $this->assetModule('css/style.css', 'article');

The output is:

'http://localhost/Pi/www/asset/module-article/css/style.css'

assetTheme

This helper builds URI for asset folder of theme only. The usage of this function is as same as assetModule, the two parameters are file name and module name, respectively. The second parameter can be ignored if you build a URI of current theme.

For example, the current theme named default:

echo $this->assetTheme('image/logo.png');
echo $this->assetTheme('js/jquery.js', 'dev');

These codes will output:

'http://localhost/Pi/www/asset/theme-default/image/logo.png'
'http://localhost/Pi/www/asset/theme-dev/js/jquery.js'

backbone

This helper is used to load javascript files of backbone. The helper will autoload backbone.min.js and underscore-min.js files, and other static files can also be load if their file name is passed.

$this->backbone();
$this->backbone('js1.js');
$this->backbone(array(
    'backbone.min.js', 'style.css'
));

basePath

This helper is used to get the base path of application.

echo $this->basePath();
echo $this->basePath('asset/image/logo.png');

Output:

'http://localhost/Pi/www/'
'http://localhost/Pi/www/asset/image/logo.png'

blocks

Pi divides a page into a module part and several blocks parts. A block is an independent application relates to current module. Pi encapsulates a helper named blocks**for users to load blocks of specified zones. The blocks()` helper will return an array contains blocks information according to passed parameter.

The blocks helper takes only one parameter that indicates the zone. The value of parameter should be 0 to 8. Blocks of different zones will be loaded according to its first parameter, if the passed parameter is set to null, blocks of all zones will be loaded.

$blocks = $this->blocks();

$blocks = $this->blocks('5');
foreach ($blocks['5'] as $key => $block) {
    ...
}

The code above is used in the .phtml template, if you want to call this helper in general PHP file, you should use the following codes:

$blocksHelper = $this->plugin('blocks')->setEvent($mvcEvent);
$leftBlocks = $blocksHelper('0');
$rightBlcoks = $blocksHelper->load('8');

bootstrap

Pi allows users to use bootstrap to achieve div+css, users only need to include the bootstrap file name and then insert the class name into their HTML tags, the whole front style will come true automatically.

This helper takes two parameters, the first one decides the static files to load, and the second parameter decide whether to load bootstrap.min.css, and the default value is true.

$this->bootstrap();
$this->bootstrap('css/bootstrap.responsive.min.css');
$this->bootstrap(array(
    'css/bootstrap.responsive.css',
    'js/bootstrap.js',
));

css

The HTML <link> element is used for linking varieties of resources for your page, such as stylesheets, feeds, favicons, trackbacks and more. The css is a helper of Pi library, which inherit from Zend helper, and call headLink helper of Zend to create and aggregate those elements mentioned above for later retrieval and output in your layout script.

There is only one parameter of css helper, and it can be string or array which contains file path of resources. This helper will store path information in an AbstractHelper object, and you should add extra codes to output them.

In Pi, js, css resources are stored in static folder, therefore, you may fetch the URI first:

$pathToCss = Pi::url('static') . '/css';
$this->css($pathToCss . '/style.css');
$this->css(array(
    $pathToCss . '/css1.css',
    $pathToCss . '/css2.css',
));
echo $this->headLink();

Then if you click right button to view page source, you will find a HTML <link> element has been added:

'<link href="http://localhost/Pi/www/static/css/style.css" media="screen" rel="stylesheet" type="text/css" >'
'<link href="http://localhost/Pi/www/static/css/css1.css" media="screen" rel="stylesheet" type="text/css" >' 
'<link href="http://localhost/Pi/www/static/css/css2.css" media="screen" rel="stylesheet" type="text/css" >' 

NOTE: you must add echo $this->headLink(); at the end of your code if you want to output a HTML <link> element.

escape

It is strongly recommended to add escape for output variables, the escape helper helps user to escape easily.

echo $this->escape($value);

footScript

ga

This helper is used to add GA code for users to get statistical data of their site. It takes only one parameter which is the GA account. And the default account from configuration will be used if it is not set.

$this->ga();
$this->ga('UA-XXXXX-X');

js

The js helper is a Pi helper which inherit from AbstractHelper, this helper allows you to manage a HTML <script> element for later output, the HTML <script> element is used to either provide inline client-side scripting elements or link to a remote resource containing client-side scripting code.

The js helper has only one parameter, it can be string or array describes the name of js files. This helper do not output HTML <script> element directly, you should add echo $this->headScript(); to output it.

The JavaScript files are also stored in the static folder in Pi. You should fetch a static URI first.

$pathToJs = Pi::url('static') . '/js';
$this->js($pathToJs . '/js1.js');
$this->js(array(     
    $pathToJs . '/js2.js',
    $pathToJs . '/js3.js',
));
echo $this->headScript();

These codes will output:

'<script type="text/javascript" src="http://localhost/Pi/www/static/js/js1.js"></script>'
'<script type="text/javascript" src="http://localhost/Pi/www/static/js/js2.js"></script>'
'<script type="text/javascript" src="http://localhost/Pi/www/static/js/js3.js"></script>'

jQuery

The jQuery is a JavaScript framework, it helps users to deal with HTML documents, events and animation conveniently, it also provides with AJAX. The jQuery helper inherits from AbstractHelper of Zend, it loads js or css files for later output.

The jQuery helper contains only one parameter which can be a string or an array consists of string elements. Strings are name of css or js files, if you do not set its parameter, a js file named jquery.min.js will be loaded.

NOTE: you should add echo $this->headScript(); or echo $this->headLink(); to output your HTML tags.

$this->jQuery();
$this->jQuery('extension.js');
$this->jQuery(array(
    'js1.js',
    'css1.css',
));
echo $this->headScript();
echo $this->headLink();

The outputs are:

'<script type="text/javascript" src="http://localhost/Pi/www/static/js/jquery/jquery.min.js"></script>'
'<script type="text/javascript" src="http://localhost/Pi/www/static/js/jquery/extension.js"></script>'
'<script type="text/javascript" src="http://localhost/Pi/www/static/js/jquery/js1.js">'
'<link href="http://localhost/Pi/www/static/js/jquery/css1.css" rel="stylesheet" type="text/css" >'

meta

The HTML <meta> element is used to provide meta information about your HTML document, such as keywords, document character set, caching pragmas, etc. Meta tags may be either of the http-equiv or name types, must contain a content attribute, and also have either of the lang or scheme modifier attributes.

The meta helper will select the meta category of application's config table, and then return the result according to given parameter. This helper has only one parameter typed string, it is the name of meta element. The value of the parameter can be copyright, description, keywords or author here.

echo $this->meta('keywords');
echo $this->meta()->getMeta('keywords');

Output:

'Pi, Web application'
'Pi, Web application'

If you do not set the parameter, an AbstractHelper containing nothing will be returned, then you can call its method to achieve other function.

// Fetching data of general category from 'config' table
echo $this->meta()->getConfig('sitename');
// Assign meta data to root view model and initialize views
$this->meta()->assign();

The first line will output:

'Web Applications'

template

In Pi, HTML tags are coded in a special file which has an extension named .phtml. The template helper is used to decide which template file to use in current theme. This helper takes only one parameter which is a string containing module and template name data. The full string has a format such as {module name}:{template name}.phtml. If you do not set module name, current module will be used. The templates in theme package have the highest priority.

For example, if you install your Pi in D disc, and current module is system:

echo $this->template('block.phtml');
echo $this->template('module/system:block/login.phtml');

Output:

'D:/wamp/www/Pi/usr/theme/default/template/block.phtml'
'D:/wamp/www/Pi/usr/module/system/template/block/login.phtml'

Using following codes to add a template:

include $this->template('block.phtml');

url

Pi adopts a Module-Controller-Action model, you should set module name, controller name and action name in url to route to right page. The url helper provides the function to generate a URL by given parameters.

The url helper takes four parameters, the first is route name, it allow you to choose your route type, Pi provides four types for user to choose, which are default, admin, home and feed, it will set to default if you give a null value; the second parameter is an array which contain module name, controller name and action name, if you do not give the module name, current module will be used; the third parameter is an option parameter for route and the fourth parameter is a Boolean which decided whether to reuse matched parameters.

$this->url('', array(    
    'module'     => 'system',
    'controller' => 'index',
    'action'     => 'index',
));

$this->url('home');

$this->url('default', array(
    'controller'  => 'index',
    'action'      => 'index',
));

You can also add your parameters to the second parameter of url helper. These parameters will post by GET method, for example:

$this->url('' array(
    'controller'  => 'login',
    'action'      => 'login',
    'param'       => 'hello',
));

The url will be:

'path/to/www/login/login/param-hello'

Then you can use params() method to fetch the value in action method:

$this->params('param');

widget

In Pi, blocks are used to implement a special function in page, you can add or remove a block from you page by coding your pthml file of theme package. The widget helper will allow user to fetch and render a block.

The widget helper inherits from the block helper, it takes two parameters, the first can be a block name string, or a number describes a block. The second parameter is an array.

$this->widget('block-name', array('title_hidden' => 1, 'opt1' => 'val1', 'opt2' => 'val2'));
$this->widget('block-name', array('link' => '/link/to/a/URL', 'opt1' => 'val1', 'opt2' => 'val2'));
$this->widget('block-name', array('style' => 'specified-css-class', 'opt1' => 'val1', 'opt2' => 'val2'));
$this->widget(24, array('opt1' => 'val1', 'opt2' => 'val2'));
$this->widget()->load(24);
$this->widget()->render($blockModel);

These codes will load and display blocks in the indicated position.

navigation

The navigation helper is used to load a navigation for current module of Pi application.

This helper takes two parameters, the first one is name of navigation to load, it can also be comprehended as section in general. In Pi, it can be set to front or admin to load a front navigation or admin navigation, or name indicate custom navigation definded by users. A front navigation will be used if this parameter is not set. The second parameter is an array and its fields will be used to configure cache.

NOTE: the data used to generate navigation are fetched from core_navigation_node table, these data are first defind in the config/navigation.php file.

// load a front navigation
$this->navigation('front');
// load a admin navigation and set cache ttl, level and key
$this->navigation('admin', array(
    'cache_ttl'   => 86400,
    'cache_level' => none,
    'cache_id'    => 'nav_system'));
// render a custom navigation 'cms' if current module is demo
$this->navigation('demo-cms')->render();

Menu

This class is used to operate menu and can be call by $this->navigation()->menu().

this setUIClass(string $ulClass);
this setOnlyActiveBranch(bool $flag = true);
this escapeLabels(bool $flag = true);
this setRenderParent(bool $flag = true);
this setPartial(string|array $partial);
string renderMenu(AbstractContainer $container = null, array $options = array());
array renderPair(AbstractContainer $container = null, array $options = array());
string render($AbstractContainer $container = null);
  • setUIClass()

Set css class to use for the first 'ul' element when rendering.

$this->navigation('front')->menu()->setUIClass('jd_menu');
  • setOnlyActiveBranch()

This method decides whether to render active branch only, the application will only render active branch if set to true.

$this->navigation('front')->menu()->setOnlyActiveBranch();
  • escapeLabels()

Indicating whether to escape labels. Its default value is true.

$this->navigation('front')->menu()->escapeLabels();
  • setRenderParents()

    $this->navigation('front')->menu()->setRenderParents();

  • setPartial()

  • render()

Rendering menu.

$this->navigation('front')->menu()->render();

Breadcrumbs

This class is used to operate breadcrumbs and can be call by $this->navigation()->breadcrumbs().

this setSeparator(string $sepatator);
this setLinkLast(bool $linkLast);
string render(AbstractContainer $container = null);
  • setSepatator()

Set breadcrumb separator.

$this->navigation('front')->breadcrumbs()->setSeparator('<span class="divider">&gt;</span>');
  • setLinkLast()

Deciding whether last page in breadcrumbs should be hyperlinked.

$this->navigation('front')->breadcrumbs()->setLinkLast(true);
  • render()

Rendering breadcrumb.

$this->navigation('front')->breadcrumbs()->render();

nav

This class is used to load a global navigation, it will read navigation name from core_config table, and then render the navigation by calling navigation helper. Therefore by using this helper in template, users can install custom navigation in admin section and then the custom navigation will be displayed.

The value passed to this method can only be front and admin to indicate load front global navigation or adminstration global navigation, respectively.

Its second parameter is an optional array for setting cache.

$this->nav('front');
$this->nav('admin', array(
    'cache_ttl'   => 84600,
    'cache_id'    => 'system_nav',
));

Please refer to http://packages.zendframework.com/docs/latest/manual/en/modules/zend.view.helpers.html for more helps of navigation.

Predefine variables

Predefine variables are variables define by system, users can output they value in phtml file directly without define them. These variables are declared in usr/module/system/config/config.php with they default value.

sitename

The variable sitename is the name of site, and its default value is Web Applications.

Using in template files:

<?php echo $sitename; ?>

Output:

'Web Applications'

slogan

This variable describes the slogan of site, and its set to Powered by Pi. by default.

adminmail

This variable describes administration email address for conveniently contact, it has no default value.

locale

This variable decides which language package to use, its default value set to the locale you choose when you install the Pi.

charset

This variable is charset for page to display.

timezone_server

This variable describes timezone set by server, it has no default value.

timezone_system

This variable is the timezone for application system, it also has no default value.

theme, theme_admin

These two variables describe the theme for front end and admin area, respectively, they have the same default value which is default.

NOTE: parts of definition are refer to Zend Framework 2 manual.

Clone this wiki locally