Bootstrap Zend_Translate

This entry is part 2 of 4 in the series Working with Zend_Translate and Poedit

A recurring problem for site developers is implementing a solid way to create and maintain multilingual sites, this article series is my feeble attempt to guide you through how to quickly implement the Zend_Translate in an Zend Framework 1.9.x site.

The procedures and best practices for this is unfortunately like training a dog, everyone has a different way of doing it and an opinion, so the methods and code I show here are taken out of applications that are running in production so if you have a better way of doing it please feel free to comment!.

I usually use poedit a gettext editor which is available for most platforms to create my translation files, and after some initial configuration of the catalog paths so it can see your source files please see Part 1 of this article series.

The bootstrap below looks for the language specific gettext .mo files in /application/languages/ for example /application/languages/sv_SE.mo

Bootstrap.php

protected function _initTranslate() {
// We use the Swedish locale as an example
$locale = new Zend_Locale('sv_SE');
Zend_Registry::set('Zend_Locale', $locale);

// Create Session block and save the locale
$session = new Zend_Session_Namespace('session');
$langLocale = isset($session->lang) ? $session->lang : $locale;

// Set up and load the translations (all of them!)
$translate = new Zend_Translate('gettext', APPLICATION_PATH . DIRECTORY_SEPARATOR .'languages', $langLocale,
array('disableNotices' => true));

//$translate->setLocale($langLocale); // Use this if you only want to load the translation matching current locale, experiment.

// Save it for later
$registry = Zend_Registry::getInstance();
$registry->set('Zend_Translate', $translate);
}

Now when you use statements like

translate('Contact Admin'); ?>
in your layout.phtml or view.phtml files it will be picked up by poedit and you will be presented with a string “Contact Admin” to translate, in my case i’ll just enter “Kontakta Administratören”.

There is some debate on what to put in the translate strings as identifiers, I personaly prefer the actual term to translate in a base language, in this case English instead of some convoluted “IDS0001” type strings.

Poedit will keep track of changes, i.e if I would change the “Contact Admin” to “Contact us” it will tell you on synchronization that “Contact Admin” disappeared and a new translation is required for “Contact us”. It’s quite easy to send those strings to your translators.

Thats it for today.

Object-relational mapping with Doctrine, Flash Builder, and PHP

Richard Bates @ Zend Developer Zone wrote a good article on my favorite ORM Doctrine integration in Zend;

Rich Internet applications built with Adobe Flex and Flash Builder have been steadily gaining a foothold in enterprise development for quite some time. As the platform has grown and evolved, PHP has also made amazing progress toward becoming a mature, powerful object-oriented language with rapid adoption and dozens of frameworks and design pattern implementations. As PHP continues to prosper, developers are able to borrow more and more of the things Java has got right, taking one check after another from the “Java-only” column. One outstanding example of this is object-relational mapping (ORM). A few different PHP ORM implementations are available, and all of them have positive attributes. However, after some experimentation, I’ve found that Doctrine is my favorite.

Read the complete story;

Object-relational mapping with Doctrine, Flash Builder, and PHP.

Automate Db Model Creation with Zend_CodeGenerator_Php_Class

Joey Rivera wrote a very interesting and time saving article about the Zend_CodeGenerator complete with a easy to use code snippet that will create the model and DbTable files and classes for you, as it picks the information directly from your database, it’s no way those pesky typos and cut and paste mistakes creep in when you have to do 10 (or 300) almost identical files.

Worth checking out; Joey’s Blog

Console ProgressBar and Text

The query was; How to set the Text Label on the progressbar in console mode.
The answer by Michael “Ray” Rehbein: You want to set the ‘elements’ option of the adapter.

http://framework.zend.com/manual/en/zend.progressbar.html#zend.progressbar.adapter.console


$pbAdapter = new Zend_ProgressBar_Adapter_Console(
array('elements'=>
array(Zend_ProgressBar_Adapter_Console::ELEMENT_PERCENT,
Zend_ProgressBar_Adapter_Console::ELEMENT_BAR,
Zend_ProgressBar_Adapter_Console::ELEMENT_ETA,
Zend_ProgressBar_Adapter_Console::ELEMENT_TEXT)
)
);

$progressBar = new Zend_ProgressBar($pbAdapter, 0, 10);

for ($i = 0; $i < 10; $i++) {
sleep(1);
$progressBar->update($i, "Iteration: {$i}"); } $progressBar->finish();
}

Quite nifty.

ZamfBrowser 1.0

When doing AMF projects especially in AIR it’s good to see what gets returned from your Zend_AMF services, here is the solution; ZamfBrowser allows developers to unit test ZendAMF Service classes via an Adobe AIR application. Implementation requires a simple edit to the ZendAMF gateway file that allows ZamfBrowser to introspect your server set up and provide access for all classes and methods registered with the Zend_Amf_Server object. For version 1.0 the ZamfBrowser AIR source code is still closed, but it is intended to go Open Source as soon as the source code documentation is complete and a couple of features are implemented that are still in the pipeline.

Go and get it: http://www.zamfbrowser.org/

Zend_Acl & Zend_Navigation

Setting up a simple working example of Acl & Navigation in Zend Framework 1.9.x as demonstrated by jscherer26.
Enjoy

models/Acl.php

< ?php class Model_Acl extends Zend_Acl { public function __construct() { // define Roles $this->addRole(new Zend_Acl_Role('guest')); // not authenicated
$this->addRole(new Zend_Acl_Role('member'), 'guest'); // authenticated as member inherit guest privilages
$this->addRole(new Zend_Acl_Role('admin'), 'member'); // authenticated as admin inherit member privilages

// define Resources
$this->add(new Zend_Acl_Resource('error'));
$this->add(new Zend_Acl_Resource('index'));
$this->add(new Zend_Acl_Resource('authentication'));
$this->add(new Zend_Acl_Resource('activity'));

// assign privileges
$this->allow('guest', array('index','error'));
$this->allow('guest', 'authentication', array('index','signin'));

$this->allow('member', 'authentication', array('index','signout'));
$this->deny( 'member', 'authentication', 'signin');
$this->allow('member', 'activity', array('index','list')); // member has list privilages for resource activity

$this->allow('admin', 'activity'); // admin has all privileges for resource activity
}
}

plugins/Authenticated.php

< ?php class Plugin_Authenticated extends Zend_Controller_Plugin_Abstract { private $_acl = null; private $_auth = null; public function __construct(Zend_Acl $acl, Zend_Auth $auth) { $this->_acl = $acl;
$this->_auth = $auth;
}

public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$resource = $request->getControllerName();
$action = $request->getActionName();

$role .= $this->_auth->getStorage()->read()->role;
if(!$this->_acl->isAllowed($role, $resource, $action)) {
$request->setControllerName('authentication')
->setActionName('notauthorized');
}
}
}

Bootstrap.php

< ?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { private $_acl = null; private $_auth = null; protected function _initAutoload() { $modelLoader = new Zend_Application_Module_Autoloader(array( 'namespace' => '',
'basePath' => APPLICATION_PATH));

$this->_acl = new Model_Acl;
$this->_auth = Zend_Auth::getInstance();
if(!$this->_auth->hasIdentity()) {$this->_auth->getStorage()->read()->role = 'guest';}

$fc = Zend_Controller_Front::getInstance();
$fc->registerPlugin(new Plugin_Authenticated($this->_acl, $this->_auth));

return $modelLoader;
}

function _initViewHelpers()
{
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();

$config = new Zend_Config_Ini(APPLICATION_PATH .'/configs/application.ini', APPLICATION_ENV);

$view->doctype('HTML4_STRICT');
$view->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8')
->appendHttpEquiv('Content-Language', 'en-US')
->appendName('keywords', $config->head->meta->keywords)
->appendName('description', $config->head->meta->description);

$view->headLink()->appendStylesheet($config->head->css->site)
->appendStylesheet($config->head->css->menu)
->appendStylesheet($config->head->css->form)
->appendStylesheet($config->head->css->view);

$view->headTitle()->setSeparator(' - ');
$view->headTitle($config->head->title);

}

function _initNavigation()
{
$this->bootstrap('layout');
$layout = $this->getResource('layout');
$view = $layout->getView();

$navConfig = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
$navigation = new Zend_Navigation($navConfig);

$view->navigation($navigation)->setAcl($this->_acl)
->setRole($this->_auth->getStorage()->read()->role);

}

}

configs/Navigation.xml

< ?xml version="1.0" encoding="UTF-8"?>


Custom Flash Messenger for Zend Framework

Mohammed Alsharaf wrote a good working example; FlashMessenger is an action helper in Zend Framework used to pass messages for the users on the next request.
Thats all good, but what about presenting the messages for the users? how to store different type of messages, System, Error, or Success messages?
To achive my goal, i have built two classes, one is an action helper and the other one is view helper.

Action Helper Class

This action helper class act as a factory and singleton pattern. It store the messages in different namespaces of the flash messenger. You can also, retrieve a namesapce by its key to add another message.


/**
* @author Mohammed Alsharaf
* @category Core
* @package Core_ActionHelper
* @copyright Copyright (c) 2008-2009 Mohammed Alsharaf.
* @license http://framework.zend.com/license/new-bsd
*/
class Core_ActionHelper_Messenger extends Zend_Controller_Action_Helper_Abstract
{
protected $_flashMessenger = null;

public function messenger($name='error',$message=null) {
if($name == 'error' &amp;amp; $message === null) {
return $this;
}
if(!isset($this->_flashMessenger[$name])) {
$this->_flashMessenger[$name] = $this->getActionController() ->getHelper('FlashMessenger') ->setNamespace($name.'_message');
}
if($message !== null) {
$this->_flashMessenger[$name]->addMessage($message);
}
return $this->_flashMessenger[$name];
}

public function direct($name='error',$message=null) {
return $this->messenger($name,$message);
}
}

View Helper Class

The view helper loops all the namespaces of the flash messenger and render the messages using the htmlList view helper

/**
* @author Mohammed Alsharaf
* @category Core
* @package Core_ViewHelper
* @copyright Copyright (c) 2008-2009 Mohammed Alsharaf.
* @license http://framework.zend.com/license/new-bsd
*/
class Core_ViewHelper_Messenger extends Zend_View_Helper_Abstract
{
protected $_messageKeys = array(
'msg_message',
'error_message',
'info_message',
'success_message',
'warning_message',
);

public function messenger()
{
foreach($this->_messageKeys as $messageKey) {
if($messages = $this->_getMessages($messageKey)) {
echo $this->_renderMessage($messages,$messageKey);
}
}
}

protected function _getMessages($messageKey)
{
$result = array();
$flashMessenger = Zend_Controller_Action_HelperBroker::getStaticHelper('FlashMessenger');
$flashMessenger->setNamespace($messageKey);

if($flashMessenger->hasMessages()) {
$result = $flashMessenger->getMessages();
}

// check view object
if(isset($this->view->$messageKey)) {
array_push($result, $this->view->$messageKey);
}

//add any messages from this request
if ($flashMessenger->hasCurrentMessages()) {
$result = array_merge($result,
$flashMessenger->getCurrentMessages()
);
//we don’t need to display them twice.
$flashMessenger->clearCurrentMessages();
}
return $result;
}

protected function _renderMessage($message, $name)
{
if(!is_array($message)) {
$message = array($message);
}
return $this->view->htmlList($message, false, array('class'=>$name), true);
}
}

Usage:

In your controller to add a message for the next request

// option one
$this->_helper->messenger('success',"Your message is here.");
// another option to add message
$this->_helper->messenger('success')->addMessage('Your message is here.');

To add a message in the current view:

$this->view->info_message = 'stiky message for the current view';

In your layout file add the following, so if there are messages to view, the helper will print them.

<div id="messages"><?php $this->messenger(); ?></div>

Update:
Carlton Gibson over at noumenal also have a very nice tutorial and view helper that you might want to look at.
http://blog.noumenal.co.uk/2009/08/using-zend-framework-flashmessenger.html

Cloud computing with PHP – Using Amazon EC2 with the Zend Framework

Doug Tidwell is a senior software engineer in IBM’s Emerging Technology group. He just wrote a two part article on Moving data into and out of the cloud with the Zend Framework and Using virtual machines with the Zend Framework.

Summary: The Zend Framework contains several classes that make using cloud-based storage services easy.

Part 1 and Part 2.

Cloud computing with PHP, Part 2: Using Amazon EC2 with the Zend Framework