OPL port for Zend Framework 0.1
| Copyright © Invenzzia Group 2009 |
| Available under the terms of license: GNU Free Documentation License 1.2 |
| Generated: 17.09.2009 |
Table of Contents
- 1. Preface
- 2. Installation
- 3. Using the port
- 4. Tips and tricks
- 5. Appendix
- Table of Contents
1. Preface - 2. Installation
Next »
1. Preface
Open Power Libs is a set of specialized PHP5 libraries designed to help you developing the applications. They are neither a framework nor a solution created for a certain framework. The libraries provide their own core, error handling or plugin architecture that allows you to extend them, and you can use them either as a standalone product or together with your favourite framework.
The Open Power Libs port for Zend Framework is a official port that allows you to easily integrate these libraries with Zend Framework, a product of Zend Company Ltd. It replaces or extends some of the default framework components so that they make use of the libraries provided by OPL. Currently, the project focuses on providing a complete support for Open Power Template 2 engine, a part of OPL project.
Features
Currently, the port provides the following changes and improvements to the original Zend Framework:
- Introduction of
Opt_Viewclass, the base view class in Open Power Template 2. Invenzzia_Layoutcomponent, a replacement forZend_Layoutdesigned especially for OPT.- New response class, compatible with the OPT output system interface.
Zend_Mailextended in order to generate the message body from a template.Zend_Formextended in order to use the OPT form building tools.- Router functions and instructions for the template engine.
- The access to the original Zend Framework view helpers.
- The original Open Power Libs error handler extended to support Zend Framework exceptions.
- Basic
Zend_Cacheintegration with Open Power Template.
- Table of Contents
2. Installation - 1. Preface
« Previous - 3. Using the port
Next »
2. Installation
System requirements
In order to use OPL port for Zend Framework, your PHP installation must meet all the requirements of both Zend Framework and Open Power Libs. The minimum PHP version is 5.2, but we recommend to use PHP 5.3 and newer, if possible. OPL and the port do not require any database or specific PHP modules installed.
Library requirements
In order to work, this port must be combined with two libraries:
- Zend Framework 1.7 or newer
- Open Power Template 2.0.1 with OPL core
You need to download them from their websites on your own.
Installation procedure
Follow the steps below in order to install and integrate Zend Framework with OPL:
- Download the necessary archives from the project websites.
- Install Zend Framework according to the instructions that can be found on the Zend Framework website.
- Extract the downloaded Open Power Libs archive.
- Copy the content of the
/libdirectory in the extracted archive to/libdirectory in your Zend Framework project structure. - Download and extract the OPL port for Zend Framework. The archive contains the source code together with a sample application - the content is a valid Zend Framework project structure.
- Copy the
/lib/Invenzziadirectory with the contents from the OPL port extracted archive to/lib/Invenzziain your project directory structure. - Configure the
bootstrap.phpfile. - Write some action controllers that use the port.
Bootstrap.php
Below, you can find a sample bootstrap.php file that enables the port and allows to use OPL with Zend Framework.
<?php /** * A sample application bootstrap file */ set_include_path(get_include_path().PATH_SEPARATOR.BASE_PATH.'lib/'); // Load the autoloader. require(BASE_PATH.'lib/Opl/Base.php'); // Autoloader initialization Opl_Loader::addLibrary('Zend', array('directory' => BASE_PATH.'lib/Zend/', 'handler' => null)); Opl_Loader::addLibrary('Invenzzia', array('directory' => BASE_PATH.'lib/Invenzzia/', 'handler' => null)); Opl_Loader::addLibrary('Opl', array('directory' => BASE_PATH.'lib/Opl/')); Opl_Loader::addLibrary('Opt', array('directory' => BASE_PATH.'lib/Opt/')); Opl_Loader::register(); try { // Initialize the front controller. $front = Zend_Controller_Front::getInstance(); $front->setParam('noErrorHandler', true); $front->throwExceptions(true); $front->setControllerDirectory(BASE_PATH.'app/controllers/'); // Create the improved response object. $response = new Invenzzia_Controller_Response_Http; $front->setResponse($response); // Do not forget to disable the default view renderer or we'll get a mess. $front->setParam('noViewRenderer', true); $front->setParam('disableOutputBuffering', true); // Note that OPT is initialized by Invenzzia_Layout, if you haven't done // it manually. You can pass the OPT configuration as an array to the // startMvc() method. $layout = Invenzzia_Layout::startMvc(array('stripWhitespaces'=> false)); $layout->setViewPaths(BASE_PATH.'app/views/', BASE_PATH.'cache/'); // Connect the layout to the Zend response. $layout->setOutput($response); $layout->setLayout('layout'); $front->dispatch(); } catch(Opt_Exception $exception) { $handler = new Opt_ErrorHandler; $handler->display($exception); } catch(Opl_Exception $exception) { $handler = new Opl_ErrorHandler; $handler->display($exception); } catch(Zend_Exception $exception) { $handler = new Invenzzia_ErrorHandler; $handler->displayZend($exception); }
In the beginning, we need to configure the OPL autoloader to handle all the libraries we are going to use. It does not use the include_path, but provides its own methods to specify the paths in order to improve the performance. The OPL port classes may be loaded either by the Zend Framework or OPL autoloader. Later, you need to configure the front controller. We disable the options that are related to the view rendering and set Invenzzia response object. Finally we set up the Invenzzia_Layout component. Contrary to the original Zend_Layout, Invenzzia_Layout is an obligatory component. Open Power Template does not allow to concatenate freely the content parts and the layout component manages the template modularization system provided by OPT. Note that Invenzzia_Layout automatically creates the OPT main class and configures it.
Finally, we capture the exceptions. Of course, we do not have to use the default OPL exception handlers, however they provide a lot of useful information on each exception that helps to find the problem and fix it.
include_path is still necessary due to the Zend Framework structure, where some files are loaded manually.
Using the original Zend autoloader
The original Zend Framework autoloader still can be used with the port and OPL. You must disable handling Zend Framework classes with OPL and ensure that the ZF autoloader will do the same with OPL:
Opl_Loader::setHandleUnknownLibraries(false); Opl_Loader::addLibrary('Invenzzia', array('directory' => BASE_PATH.'lib/Invenzzia/', 'handler' => null)); Opl_Loader::addLibrary('Opl', array('directory' => BASE_PATH.'lib/Opl/')); Opl_Loader::addLibrary('Opt', array('directory' => BASE_PATH.'lib/Opt/')); Opl_Loader::register(); // Init ZF autoloader here.
Conclusion
As you can see, the installation was not very hard and was reduced to copying the files and adding some extra code to the bootstrap.php file. In the next chapters, we will show, how to use all the features of the port.
- Table of Contents
3. Using the port - 2. Installation
« Previous - 3.1. Invenzzia_Cache
Next »
3. Using the port
Here we are going to show, how to use the port and its components.
- 3. Using the port
3.1. Invenzzia_Cache - 3. Using the port
« Previous - 3.2. Invenzzia_Controller
Next »
3.1. Invenzzia_Cache
To be written.
- 3. Using the port
3.2. Invenzzia_Controller - 3.1. Invenzzia_Cache
« Previous - 3.3. Invenzzia_ErrorHandler
Next »
3.2. Invenzzia_Controller
The Invenzzia_Controller component provides the new action class that should be used by your action controllers, if you are going to use Invenzzia_Layout:
class IndexController extends Invenzzia_Controller_Action { public function indexAction() { $this->view->variable = 'foo'; } // end indexAction(); } // end IndexController;
The new base action controller provides the new controller property: $this->view which gives you the access to the view of the currently rendered action. It is created automatically.
- 3. Using the port
3.3. Invenzzia_ErrorHandler - 3.2. Invenzzia_Controller
« Previous - 3.4. Invenzzia_Form
Next »
3.3. Invenzzia_ErrorHandler
To be written.
- 3. Using the port
3.4. Invenzzia_Form - 3.3. Invenzzia_ErrorHandler
« Previous - 3.5. Invenzzia_Layout
Next »
3.4. Invenzzia_Form
Invenzzia_Form is a wrapper to the original Zend_Form that allows to use the Zend forms with the component engine provided by OPT. The support does not have all the planned features yet, but it is suitable for ordinary HTML forms.
Constructing forms
Here we can find a sample form constructed with Invenzzia_Form:
class testForm extends Invenzzia_Form { /** * Form constructor. Note that we do not set any decorators here, * as we are using OPT to define the element layout. * * @param Array $options The form options. */ public function __construct( $options = null ) { parent::__construct($options); $email = $this->createElement( 'text', 'email' ); $email->setLabel( 'E-mail' ) ->setRequired( true ) ->addValidator('NotEmpty') ->addValidator(new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_LOCAL)); $this->addElement($email); $firstname = $this->createElement( 'text', 'firstname' ); $firstname->setLabel( 'First name' ) ->setRequired( true ) ->addValidator('NotEmpty'); $this->addElement($firstname); $surname = $this->createElement( 'text', 'surname' ); $surname->setLabel( 'Last name' ) ->setRequired( true ) ->addValidator('NotEmpty'); $this->addElement($surname); } // end __construct(); } // end testForm;
As we can see, we extend the class Invenzzia_Form instead of Zend_Form. Furthermore, we do not set any element decorators, because this is not a task for this part of the form engine. The layout of the form elements is defined in templates. However, the attributes set with setAttrib() and setAttribs() methods are respected while displaying the element.
Form template
The HTML template for this form looks like this:
<!-- define the CSS classes used by the helpers in the "valid" and "invalid" situations --> {@formStyleTextValid is 'foo'} {@formStyleTextInvalid is 'bar'} <!-- create the form --> <form parse:method="$form.method" parse:action="url($form.action)"> <opt:section name="fields" datasource="$form.fields"> <opt:component from="$fields.component"> <p>{$system.component.label}: <opt:display /></p> <opt:onEvent name="error"> <p>Some errors occured:</p> <opt:section name="componentErrors" datasource="$componentErrors"> <p>{$componentErrors}</p> </opt:section> </opt:onEvent> </opt:component> </opt:section> <p><input type="submit" value="OK" /></p> </form>
The form data are available through a container $form. The elements of the container are:
$form.method- The form method.
$form.action- The form action route data. In order to get the URL, you need to use
url()template function. $form.fields- The list of available form fields that can be used as a data source for the section.
The list of fields can be displayed with a section. The section name is not fixed, but we must select the data source for it. Once we are in the list element, we can access the component with $fields.component. Then we use the standard component engine features built into OPT to define the form element layout.
The components provide the following parameters:
$system.component.label- The label set to the element.
$system.component.description- The extra description set to the element.
$system.component.name- The element name used by the application.
$system.component.id- The HTML id attribute value generated by the component.
$system.component.helperName- The helper name of the element.
The components recognize the following events:
error- Fired on element validation error. The error messages are available in the
$componentErrorsvariable that can be displayed with a section.
The components can manage the attributes of the following tags: <div> and <tr>. Together with the formStyleInvalid, it can be used to change the CSS class of the entire invalid element field:
{@formStyleInvalid is 'error'}
<opt:component from="$fields.component">
<com:div>
</com:div>
</opt:component>
The port does also support the opt:component-attributes attribute introduced in OPT 2.0.2 as an alternative to com:* namespace. The recognized attribute value is error.
Currently, it is not possible to deploy the form elements statically in the component ports. The support for this feature will be added in the future versions of the port.
Thanks to @formStyleHELPERNAMEValid and @formStyleHELPERNAMEInvalid, we can configure the CSS classes applied to the element in certain situations.
Using Invenzzia_Form
Once we have a form, we can use it in the controller:
$form = new testForm; if($_SERVER['REQUEST_METHOD'] == 'POST') { if($form->isValid($_POST)) { // Process the form data here } else { $form->setAction('controller=index&action=form'); $form->populate($_POST); $form->assignForm($this->view); } } else { $form->setAction('controller=index&action=form'); $form->assignForm($this->view); }
Note that the method to assign a form to the view is called assignForm(). Its use is obligatory.
- 3. Using the port
3.5. Invenzzia_Layout - 3.4. Invenzzia_Form
« Previous - 3.5.1. Quick start
Next »
3.5. Invenzzia_Layout
Invenzzia_Layout is a complete replacement for the original Zend_Layout component, designed especially to work with Open Power Template 2 templates. Similarly to the original, it implements a classic Two Step View pattern, where the programmers may wrap the application content within another view. Invenzzia_Layout collects the action views and assigns it to one of the predefined placeholders. They may be rendered later in the other templates with the standard OPT instructions.
- 3.5. Invenzzia_Layout
3.5.1. Quick start - 3.5. Invenzzia_Layout
« Previous - 3.5.2. Advanced use
Next »
3.5.1. Quick start
In this chapter, we are going to show, how to use the Invenzzia_Layout component with Zend Framework.
Layouts
First, you need a main template called layout. Its purpose is to define the basic structure of the output HTML code produced by your application. Invenzzia_Layout creates an Opt_View for it which can be used to assign the data to the template variables and caching. Because the template is parsed by OPT, you may use there anything you have registered in OPT.
Below, you can find a sample layout template, layout.tpl that could go to /app/views directory:
<?xml version="1.0" ?> <opt:root> <opt:prolog version="1.0" ?> <opt:dtd template="xhtml10transitional" /> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>My Site</title> </head> <body> <!-- retrieve various layout variables --> <p>{$foo}</p> <p>{$bar}</p> <!-- fetch the views in the 'content' placeholder --> <opt:section name="content"> <opt:include from="content"> <p class="error">Sorry, the requested template has not been found.</p> </opt:include> </opt:section> </body> </html> </opt:root>
To render the views in the placeholders, we use ordinary OPT sections and opt:include. The second instruction allows us to define a message displayed, if the requested template cannot be loaded. It can be used for debug purposes.
Invenzzia_Layout initialization
Invenzzia_Layout is build upon Open Power Template and initializes the template engine automatically. Invenzzia_Layout::startMvc() creates an instance of Invenzzia_Layout with any extra arguments for Open Power Template. We have to specify the view paths, too: one for the source templates and one for the compiled ones:
$layout = Invenzzia_Layout::startMvc(array('stripWhitespaces'=> false)); $layout->setViewPaths(ROOT_DIR.'app/views/', ROOT_DIR.'cache/compiled/');
To finalize the initialization, we also need to connect the response object and select the layout template.
Open Power Template uses output systems to render the content. Thus, you are allowed to use the response objects that are compatible with the
Opt_Output_Interface. The port provides a ready wrapper for the original Zend Framework's HTTP response class.
$front = Zend_Controller_Front::getInstance(); // Invenzzia_Layout initialization here. $response = new Invenzzia_Controller_Response_Http; $front->setResponse($response); $layout->setOutput($response); $layout->setLayout('layout');
Invenzzia_Layout::setLayout() method sets the used layout template from the /app/views directory. The template name is written without the file extension (.tpl).
Actions
Invenzzia_Layout creates and initializes the view objects for the actions automatically. They are available out-of-the-box and mapped to the /app/view/controllerName/actionName.tpl template by default, and assigned to the content placeholder. If these assumptions suit you, your job is to assign the data to the view:
class someController { public function fooAction() { $this->view->myVariable = 'foo'; } // end fooAction(); public function barAction() { $this->view->myVariable = 'bar'; } // end barAction(); } // end someController;
As the OPT views provide separate variable scopes for each, you do not have worry about the naming collisions between the template variables. A sample template for the first action: /app/views/some/foo.tpl:
<?xml version="1.0" ?> <opt:root> <p>Hi universe!</p> <p>{$myVariable}</p> </opt:root>
- 3.5. Invenzzia_Layout
3.5.2. Advanced use - 3.5.1. Quick start
« Previous - 3.6. Invenzzia_Mail
Next »
3.5.2. Advanced use
Modifying the default action view settings
The default action views are initialized to the controllerName/actionName.tpl file and assigned to the content placeholder. However, we may freely modify these settings:
public function fooAction() { // Change the default template name $this->view->setTemplate('foobar.tpl'); // Change the default placeholder Invenzzia_Layout::getMvcInstance()->appendView($this->view, 'newPlaceholder'); } // end fooAction();
The new placeholders do not need to be initialized, however they need to be displayed somewhere similarly to the default one, for example:
<opt:section name="newPlaceholder"> <div> <opt:include from="newPlaceholder" /> </div> </opt:section>
To prepend the view to the beginning of a placeholder, we have to use the Invenzzia_Layout::prependView() method:
Invenzzia_Layout::getMvcInstance()->prependView($this->view, 'newPlaceholder');
Obtaining the layout view
To assign the data to the main template, we need to have an access for the layout view object. It can be obtained directly from the layout manager:
$layout = Invenzzia_Layout::getMvcInstance(); $layoutView = $layout->getLayout(); $layoutView->someVariable = 'foo';
Disabling the layout
If we do not want to use the layout features, we may simply disable it:
$layout = Invenzzia_Layout::getMvcInstance(); $layout->disableLayout();
If the layout is disabled, you must create action views and render them manually.
- 3. Using the port
3.6. Invenzzia_Mail - 3.5.2. Advanced use
« Previous - 3.7. Invenzzia_View
Next »
3.6. Invenzzia_Mail
To be written.
- 3. Using the port
3.7. Invenzzia_View - 3.6. Invenzzia_Mail
« Previous - 3.7.1. Functions
Next »
3.7. Invenzzia_View
Invenzzia_View provides a set of extra helpers and the managing interface for them. The new helpers are sometimes reimplementations of original Zend_View helpers for Open Power Template 2 or completely new ideas.
- 3.7. Invenzzia_View
3.7.1. Functions - 3.7. Invenzzia_View
« Previous - 3.7.1.1. url()
Next »
3.7.1. Functions
Invenzzia_View provides some extra functions for the template engine. They can be used like ordinary Open Power Template functions.
- 3.7.1. Functions
3.7.1.1. url() - 3.7.1. Functions
« Previous - 3.7.2. Helpers
Next »
3.7.1.1. url()
| Construct | Function |
|---|---|
| Reference | url(mixed $parameters [, string $routeName = null ]) |
| Argument list |
|
| Returned value | The URL constructed from the parameters |
This function is a wrapper for the router. The parameter list can be either an array or a string with the arguments:
<p>{url($arguments)}</p> <p>{url('/some-controller/some-action?otherArg='~$otherArgValue)}</p>
Optionally, you can specify the route name as a second argument.
- 3.7. Invenzzia_View
3.7.2. Helpers - 3.7.1.1. url()
« Previous - 3.7.2.1. flashMessage
Next »
3.7.2. Helpers
In your views, it is often necessary to execute complex functions, operate on complex data sets or provide a convenient interface to manage them. You can use the view helpers to perform these behaviours for you. Contrary to the original helpers from Zend Framework, the OPL port helpers are optimized to work with Open Power Template 2 and its instructions.
What is a helper?
A helper is an object of a class that extends Invenzzia_View_Helper_Abstract. It is up to you, what it is going to do and what interface it should offer to the programmer and the template designer. Unsually, you would like to configure the OPT environment once the helper is registered and this can be done with the initHelper() method:
class MyHelper extends Invenzzia_View_Helper_Abstract { public function initHelper() { Opt_View::setFormat('helper.myHelper', 'Objective', false); } // end initHelper(); } // end MyHelper;
The helper objects are accessible through the $helper.helperName variable. In the example above, we inform the compiler that it should use the Objective data format for the helper data access.
How to manage helpers?
Before a helper could be used in a template, it must be registered within the port. The Invenzzia_View_HelperBroker class provides the helper management features. You can use it to register new helpers and retrieve the existing helper objects:
$helperBroker = Invenzzia_View_HelperBroker::getInstance(); $helperBroker->addHelper('myHelper', new MyHelper);
You can check for existing helpers or remove them with hasHelper() and removeHelper() methods:
if($helperBroker->hasHelper('someHelper')) { $helperBroker->removeHelper('someHelper'); }
Using helpers in actions and views
Usually, the actions would like to use the helper interfaces to configure them. Below, you can find a sample action that uses one of the default helpers to set the page title:
public function indexAction()
{
// Get the "title" helper object
$title = Invenzzia_View_HelperBroker::getInstance()->title;
$title->prependTitle('Index');
} // end indexAction();
The layout template:
<html> <head> <title>{u:$helper.title}</title> </head> ... </html>
- 3.7.2. Helpers
3.7.2.1. flashMessage - 3.7.2. Helpers
« Previous - 3.7.2.2. headScript
Next »
3.7.2.1. flashMessage
| Construct | helper |
|---|
The helper manages the flash messages.
The idea
Web applications often want to inform the user about the success or failure of the actions. Displaying a full-page message is not too good, as the user may try to refresh the page, and moreover - he must click "OK" button to get back to the list of rows. Flash messages simplify this process. The row update action saves the message in the session and redirects the user immediately to the next page. There, the message is read from the session and displayed above the action content.
The flashMessage helper provides a complete implementation for flash messages that allows the programmer to set the messages, redirect the user to other pages and control displaying them through a template engine.
Action usage
In order to make the helper work, we need to have sessions initialized:
Zend_Session::start(); // here the helper can be used Zend_Session::writeClose();
The message is set with setMessage() method:
$flashMessage = Invenzzia_View_HelperBroker::getInstance()->flashMessage; $flashMessage->setMessage('The flash message.', array('controller' => 'someController', 'action' => 'someAction'));
The second argument specifies the new location, where the user should be redirected. The helper accepts both strings with the URL and the arrays, which are transparently converted to the URL-s with the current router. As a third argument, we may specify the route name for the router.
The redirect location is optional. If you do not specify it, the helper does not redirect the user to the new page and the current action continues the execution.
By default, the helper uses the flash session namespace. You can change it with setSessionNamespace() method:
$flashMessage->setSessionNamespace('otherNamespace');
Template usage
It is very easy to display the flash message in the template:
<p opt:if="$helper.flashMessage.hasMessage">{$helper.flashMessage.message}</p>
The $helper.flashMessage.hasMessage variable contains true, if there is a flash message to display, and the message body can be retrieved from $helper.flashMessage.message.
- 3.7.2. Helpers
3.7.2.2. headScript - 3.7.2.1. flashMessage
« Previous - 3.7.2.3. headStyle
Next »
3.7.2.2. headScript
| Construct | helper |
|---|
Manages the list of the scripts loaded by the browser while rendering the page.
Action usage
The helper allows the actions to add external and inline scripts with a simple interface:
$headScript = Invenzzia_View_HelperBroker::getInstance()->headScript; $headScript->appendFile('script.js'); $headScript->appendScript('document.write(\'foo\');');
Similar functions, prependFile() and prependScript() prepend the scripts to the internal script list making them appear in the first place. The programmer may also use offsetSetScript() and offsetSetFile(), where we specify the script location manually:
$headScript = Invenzzia_View_HelperBroker::getInstance()->headScript; $headScript->appendFile('script1.js'); $headScript->appendFile('script2.js'); $headScript->offsetSetFile(1, 'script3.js'); /* produces: script1.js script3.js script2.js
If the specified script already exists on the list, it is replaced on the original position, so it is not possible to add the same file twice.
By default, the helper assumes that the registered scripts are JavaScript documents. You can control the content-type of the registered script with the optional, second argument:
$headScript->appendFile('script.vb', 'text/vbscript');
Another optional argument allows to set extra <script> tag attributes:
$headScript->appendFile('script.vb', 'text/vbscript', array('charset' => 'utf-8'));
Normally, the helper accepts only the attributes that are allowed by HTML format: type, charset, defer, language and src and the others are ignored. However, some scripts may use arbitrary attributes for their own purposes. In order to unlock them, you can use the following code:
$headScript->setAllowArbitraryAttributes(true);
Template use
On the template-side, you can let the helper to generate the necessary HTML code or take over the control over this process. The template below shows these two cases:
<head> <!-- automatic code generation --> {u:$helper.headScript} <!-- manual control --> <opt:selector name="headScript"> <opt:file> <script opt:attributes-build="$headScript.attributes" /> </opt:file> <opt:script> <script opt:attributes-build="$headScript.attributes"><opt:literal type="comment_cdata"> {u:$headScript.script} </opt:literal></script> </opt:script> </opt:selector> </head>
With the opt:attributes-ignore attribute, you can filter the unwanted attributes on the template-side. For details, see the Open Power Template user manual.
Remember to disable the HTML escaping when displaying the contents of
$helper.headScriptwith the u: modifier.
Script groups
Manual control over the script rendering process is not useful for the debug purposes only. The feature that is available only here, are the script groups. Basically speaking, you define the scripts to be loaded in the templates and give them simple identifiers. The actions use these identifiers to inform, what script group they want to use:
$headScript->appendGroup('jslib');
The template:
<head> <opt:selector name="headScript"> <!-- the "jslib" group --> <opt:jslib> <script type="jslib.js" type="text/javascript" /> <script type="jslib_widgets.js" type="text/javascript" /> </opt:jslib> <!-- the standard groups --> <opt:file> <script opt:attributes-build="$headScript.attributes" /> </opt:file> <opt:script> <script opt:attributes-build="$headScript.attributes"><opt:literal type="comment_cdata"> {u:$headScript.script} </opt:literal></script> </opt:script> </opt:selector> </head>
The groups are defined as items in the selector. Such selector group can be saved into a snippet and reused in various layouts without any problems:
<?xml version="1.0" ?> <opt:root> <!-- snippets.tpl --> <opt:snippet name="headScriptDefinition"> <!-- the "jslib" group --> <opt:jslib> <script type="jslib.js" type="text/javascript" /> <script type="jslib_widgets.js" type="text/javascript" /> </opt:jslib> <!-- the standard groups --> <opt:file> <script opt:attributes-build="$headScriptDefinition.attributes" /> </opt:file> <opt:script> <script opt:attributes-build="$headScriptDefinition.attributes"><opt:literal type="comment_cdata"> {u:$headScriptDefinition.script} </opt:literal></script> </opt:script> </opt:snippet> </opt:root>
The layout template:
<?xml version="1.0" ?> <opt:root include="snippets.tpl"> <opt:prolog version="1.0" /> <opt:dtd template="xhtml10transitional" /> <html> <head> <opt:selector name="headScript" opt:use="headScriptDefinition" /> </head> <!-- ... --> </html> </opt:root>
See also:
- 3.7.2. Helpers
3.7.2.3. headStyle - 3.7.2.2. headScript
« Previous - 3.7.2.4. Navigation helpers
Next »
3.7.2.3. headStyle
| Construct | helper |
|---|
Manages the list of the styles loaded by the browser while rendering the page.
Action usage
The helper allows the actions to add external and inline styles with a simple interface:
$headStyle = Invenzzia_View_HelperBroker::getInstance()->headStyle; $headStyle->appendFile('style.css'); $headStyle->appendStyle(' body { color: #ffffff; } ');
Similar functions, prependFile() and prependStyle() prepend the styles to the internal script list making them appear in the first place. The programmer may also use offsetSetStyle() and offsetSetFile(), where we specify the style order manually:
$headStyle = Invenzzia_View_HelperBroker::getInstance()->headStyle; $headStyle->appendFile('style1.css'); $headStyle->appendFile('style2.css'); $headStyle->offsetSetFile(1, 'style3.css'); /* produces: style1.js style3.js style2.js */
If the specified style already exists on the list, it is replaced on the original position, so it is not possible to add the same file twice.
By default, the helper assumes that the registered styles are CSS documents. You can control the content-type of the registered script with the optional, second argument. Another optional argument allows to set extra <style> tag attributes:
$headStyle->appendFile('style.css', 'text/css', array('media' => 'screen'));
Normally, the helper accepts only the attributes that are allowed by HTML format: type, lang, dir, media, title and href and the others are ignored. However, some pages may use arbitrary attributes for their own purposes. In order to unlock them, you can use the following code:
$headStyle->setAllowArbitraryAttributes(true);
Template use
On the template-side, you can let the helper to generate the necessary HTML code or take over the control over this process. The template below shows these two cases:
<head> <!-- automatic code generation --> {u:$helper.headStyle} <!-- manual control --> <opt:selector name="headStyle"> <opt:file> <link rel="stylesheet" opt:attributes-build="$headStyle.attributes" /> </opt:file> <opt:script> <style opt:attributes-build="$headStyle.attributes"><opt:literal type="comment_cdata"> {u:$headStyle.style} </opt:literal></style> </opt:script> </opt:selector> </head>
With the opt:attributes-ignore attribute, you can filter the unwanted attributes on the template-side. For details, see the Open Power Template user manual.
Remember to disable the HTML escaping when displaying the contents of
$helper.headStylewith the u: modifier.
Style groups
Manual control over the script rendering process is not useful for the debug purposes only. The feature that is available only here, are the style groups. Basically speaking, you define the styles to be loaded in the templates and give them simple identifiers. The actions use these identifiers to inform, what style group they want to use:
$headStyle->appendGroup('printable');
The template:
<head> <opt:selector name="headStyle"> <!-- the "printable" group --> <opt:printable> <link rel="stylesheet" type="text/css" media="print" href="print_structure.css" /> <link rel="stylesheet" type="text/css" media="print" href="print_format.css" /> </opt:printable> <!-- the standard groups --> <opt:file> <link rel="stylesheet" opt:attributes-build="$headStyle.attributes" /> </opt:file> <opt:style> <style opt:attributes-build="$headStyle.attributes"><opt:literal type="comment_cdata"> {u:$headStyle.style} </opt:literal></style> </opt:style> </opt:selector> </head>
The groups are defined as items in the selector. Such selector group can be saved into a snippet and reused in various layouts without any problems:
<?xml version="1.0" ?> <opt:root> <!-- snippets.tpl --> <opt:snippet name="headStyleDefinition"> <!-- the "printable" group --> <opt:printable> <link rel="stylesheet" type="text/css" media="print" href="print_structure.css" /> <link rel="stylesheet" type="text/css" media="print" href="print_format.css" /> </opt:printable> <!-- the standard groups --> <opt:file> <link rel="stylesheet" opt:attributes-build="$headStyleDefinition.attributes" /> </opt:file> <opt:style> <style opt:attributes-build="$headStyleDefinition.attributes"><opt:literal type="comment_cdata"> {u:$headStyleDefinition.style} </opt:literal></style> </opt:style> </opt:snippet> </opt:root>
The layout template:
<?xml version="1.0" ?> <opt:root include="snippets.tpl"> <opt:prolog version="1.0" /> <opt:dtd template="xhtml10transitional" /> <html> <head> <opt:selector name="headStyle" opt:use="headStyleDefinition" /> </head> <!-- ... --> </html> </opt:root>
See also:
3.7.2.4. Navigation helpers
This group of helpers uses the Zend_Navigation component to display the navigation elements. They share a common action interface. In order to use the helpers, you need to define a website structure in the Zend_Navigation container and register it in the helpers:
$container = new Zend_Navigation(array( array( 'label' => 'Index', 'controller' => 'index', 'action' => 'index' ), array( 'label' => 'Articles', 'controller' => 'article', 'action' => 'index', 'pages' => array( array( 'label' => 'Using Zend Framework with OPL', 'controller' => 'article', 'action' => 'list', 'params' => array('id' => 34) ) ) ) )); $breadcrumbs = Invenzzia_View_HelperBroker::getInstance()->breadcrumbs; $breadcrumbs->setContainer($container);
Using the helpers with Zend_Translate
The helpers can be used with Zend_Translate to translate the page titles automatically to the specified language during the rendering process:
$translator = new Zend_Translate(...); $breadcrumbs->setTranslator($translator);
Using the helpers with ACL
The helpers may automatically control, if the user is allowed to see the specified page. Such forbidden pages are skipped in the rendering process and are not presented to the user. In order to make use of it, we have to set the ACL object in the helper, define the role and save the information about the resources and privileges in the Zend_Navigation container:
$container = new Zend_Navigation(array( array( 'label' => 'Index', 'controller' => 'index', 'action' => 'index', 'resource' => 'index', 'privilege' => 'view' ), array( 'label' => 'Articles', 'controller' => 'article', 'action' => 'index', 'resource' => 'articles', 'privilege' => 'list' 'pages' => array( array( 'label' => 'Using Zend Framework with OPL', 'controller' => 'article', 'action' => 'list', 'params' => array('id' => 34), 'resource' => 'articles', 'privilege' => 'view/34' ) ) ) )); $acl = new Zend_Acl; $breadcrumbs = Invenzzia_View_HelperBroker::getInstance()->breadcrumbs; $breadcrumbs->setContainer($container); $breadcrumbs->setAcl($acl); $breadcrumbs->setRole('user');
The role can be provided either as a string or object of Zend_Acl_Role_Interface.
Specifying the minimum and maximum depth
You may limit the helpers to display only those pages that are within the minimum and maximum page tree depth limit:
$breadcrumbs->minDepth = 3; $breadcrumbs->maxDepth = 5;
3.7.2.4.1. breadcrumbs
| Construct | helper |
|---|
The helper displays the breadcrumbs from a Zend_Navigation container.
The idea
Breadcrumbs give the users a way to keep track of their location within a website. They are usually displayed in a form of a horizontal bar, showing the most general parts of the website on the left, and the currently viewed document on the right, for example:
Example.com / Articles / Technology / Using Zend Framework with OPL
This helper uses the Zend_Navigation component to recognize the application structure, determine, which page is currently displayed and provide a path from the website root page to it.
Action usage
The basic configuration of the helper is described in Navigation helpers. The breadcrumb helper extends it with setting the item separator:
$breadcrumbs->setSeparator(' / ');
Template usage
The breadcrumb bar can be generated automatically:
<p>{u:$helper.breadcrumbs}</p>
You may also take the control over the process with the breadcrumbs section to use website-specific HTML code:
<opt:selector name="breadcrumbs" str:separator=" / "> <opt:current>{$breadcrumbs.label}</opt:current> <opt:default><a parse:href="$breadcrumbs.attr.href">{$breadcrumbs.label}</a></opt:default> </opt:selector>
The $breadcrumbs.attr container contains a list of link attributes. If you wish to display them all, you may use opt:attributes-build attribute.
See also:
3.7.2.4.2. navigationTree
| Construct | helper |
|---|
This helper can be used to generate a menu or a site map.
Action usage
This helper does not require any extra configuration, except this described in Navigation helpers.
Template usage
It is recommended to use this helper with opt:tree:
<opt:tree name="navigationTree"> <opt:list><ul><opt:content /></ul></opt:list> <opt:node><li><a parse:href="$navigationTree.attr.href">{$navigationTree.label}</a><opt:content /></li></opt:node> </opt:tree>
Different navigation trees on the same site
Sometimes, you may wish to use different instances of this helper with different configurations, for example to display a menu and a site map on the same site. It is very simple - all you have to do is to register this helper again with the new name:
$helperBroker = Invenzzia_View_HelperBroker::getInstance(); $helperBroker->addHelper('sitemap', new Invenzzia_View_Helper_Navigation_NavigationTree); // the action code $siteMap = Invenzzia_View_HelperBroker::getInstance()->sitemap; $siteMap->setContainer($container);
The new helper is available in the template immediately under the new name:
<opt:tree name="sitemap"> <opt:list><ul><opt:content /></ul></opt:list> <opt:node><li><a parse:href="$sitemap.attr.href">{$sitemap.label}</a><opt:content /></li></opt:node> </opt:tree>
See also:
- 3.7.2. Helpers
3.7.2.5. title - 3.7.2.4.2. navigationTree
« Previous - 4. Tips and tricks
Next »
3.7.2.5. title
| Construct | helper |
|---|
Helps managing and displaying the page title. The title is constructed from smaller parts separated with the user-defined string, for example a slash.
Action usage
The title parts can be appended or prepended in the action code with the helper object:
$titleHelper = Invenzzia_View_HelperBroker::getInstance()->title; $titleHelper->appendTitle('Appended title'); $titleHelper->prependTitle('Prepended title');
To set the title separator, we use setSeparator():
$titleHelper->setSeparator(' / ');
The helper allows to set the default title which is presented, if there are no title parts added by the actions:
$titleHelper->setDefaultTitle('This is a default title');
We can also reset the current title parts with reset().
Template usage
The helper is very simple in use on the template-side:
<html> <head> <title>{$helper.title}</title> </head> </html>
- Table of Contents
4. Tips and tricks - 3.7.2.5. title
« Previous - 4.1. Adding pagination
Next »
4. Tips and tricks
This chapter contains a list of useful tips and tricks and explains some commonly encountered problems.
- 4. Tips and tricks
4.1. Adding pagination - 4. Tips and tricks
« Previous - 4.2. Using OPL port with ZF 1.9 autoloader
Next »
4.1. Adding pagination
The port does not integrate the Zend_Pagination component with OPT, as OPL provides its own pagination class with Open Power Classes. Install this library and add it to your project directory tree similarly to OPT and OPL.
PHP part
The paginator is very simple to configure. We may use the global configuration in order to use the same settings in all views and controllers:
$opc = new Opc_Class; $opc->itemsPerPage = 30; $opc->paginatorDecorator = 'slider'; $opc->paginatorDecoratorOptions = array( 'around' => 5, 'chunk' => 3 );
itemsPerPage controls, how many items will be displayed in one result page. paginatorDecorator selects the decorator which responds for how the list of pages will be presented. It may require some extra options specified with the paginatorDecoratorOptions. The exact list of available decorators and their options is described in the OPC documentation.
Each of this settings can be configured for a local instance of paginator independently from the global settings.
In the controller, we create the paginator object and initialize it with the total number of items:
// Specify the number of items per page explicitely $paginator = Opc_Paginator::create($totalItems, $itemsPerPage); // Use the global setting $paginator = Opc_Paginator::create($totalItems);
Then we have to pass either the currently viewed page or item offset from the request:
// Passing the page number $paginator->page = $this->getRequest()->getParam('page', 1); // Passing the offset $paginator->offset = $this->getRequest()->getParam('offset', 1);
Then we can select the data from the database:
$results = $table->select()->limit($paginator->limit, $paginator->offset);
Finally, we pass the paginator object to the view in order to render it:
$this->view->setFormat('paginator', 'Objective/Array'); $this->view->setFormat('paginator.decorator', 'Objective'); $this->view->paginator = $paginator;
Template part
Once the paginator is assigned to the view, we can configure its layout using the standard opt:selector instruction. Each element of the pagination list is defined as a separate "item" to display:
<div class="pagination"> <opt:selector name="paginator"> <opt:number> <a parse:href="url($url~'&page='~$pagination.number)">{$pagination.number}</a> </opt:number> <opt:current> <strong>{$pagination.number}</strong> </opt:current> <opt:gap> ... </opt:gap> </opt:selector> </div>
The template assumes that the default URL is passed with the $url template variable. We concatenate it with the page number and pass to the router in order to form a valid URL. Note that you do not have to repeat this layout over and over in all your views that contain lists. Use snippets to store the paginator definition in one, common template and then simply insert it everywhere you need it:
<opt:root> <!-- snippets.tpl --> <opt:snippet name="pagination"> <opt:number> <a parse:href="url($url~'&page='~$pagination.number)">{$pagination.number}</a> </opt:number> <opt:current> <strong>{$pagination.number}</strong> </opt:current> <opt:gap> ... </opt:gap> </opt:snippet> </opt:root>
The view template:
<opt:root include="snippets.tpl"> ... <div class="pagination"> <opt:selector name="paginator" opt:use="pagination" /> </div> </opt:root>
- 4. Tips and tricks
4.2. Using OPL port with ZF 1.9 autoloader - 4.1. Adding pagination
« Previous - 5. Appendix
Next »
4.2. Using OPL port with ZF 1.9 autoloader
Prior to 1.9 version, Zend Framework provided a very simple autoloader that did not suit most of the needs. However, the newest release changes this situation and introduces a highly configurable autoloader. In this article we show the possible ways to handle the autoloading issue in this version.
Note that you cannot use the bare
Zend_Loaderto load Open Power Libs and Open Power Template files, as the file matching rule is more complex and the autoloader is not able to find some of the classes and interfaces.
Do not use Zend_Loader
The first way is simply not using the Zend_Loader. Open Power Libs autoloader does not have any problems with handling Zend Framework and other libraries that use the Item_Subitem_Class class naming convention. Unless you need the Zend_Application functionality, this is the recommended way.
Combining ZF and OPL autoloaders
Zend Framework 1.9 introduces the new component called Zend_Application which manages the bootstraping process. One of the default functionalitites is setting up the default Zend_Loader, but as we know - we cannot use it for OPL and OPT. The key to make the connection work is to initialize the OPL loader before the Zend one in Bootstrap.php:
<?php // Define path to application directory defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); /** Zend_Application */ require_once 'Zend/Application.php'; require_once 'Opl/Base.php'; // Redirect unknown libraries to Zend Framework Opl_Loader::setHandleUnknownLibraries(false); Opl_Loader::register(); // Create application, bootstrap, and run $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $application->bootstrap()->run();
The paths and libraries for the OPL loader can be configured either in the Bootstrap.php file or one of the bootstraping resources.
Future port releases
Future releases of the port will contain a support for Zend_Application component.
- Table of Contents
5. Appendix - 4.2. Using OPL port with ZF 1.9 autoloader
« Previous - A. Authors and license
Next »
5. Appendix
Extra information about the project.
- 5. Appendix
A. Authors and license - 5. Appendix
« Previous
Appendix A. Authors and license
Zend Framework is a registered trademark and a copyright of Zend Technologies Ltd. Invenzzia Group and the contributors uses the name for information purposes only to indicate, what software this extension pack is written for.
Port authors
- Tomasz "Zyx" Jędrzejewski
Copyright © Invenzzia Group 2008-2009 - www.invenzzia.org
License
OPL port for Zend Framework is available under the terms of new BSD license. It is included in the library archives.
This documentation is available under the terms of GNU Free Documentation License 1.2. Its content is included in the library archives and the source files are available to download on the Invenzzia website.