Eines meiner Projekte habe ich modular mit Zend und Layouts erstellt. Nun habe ich mich für datenbankbasiertes I18N(uebersetzungsstandard) entschieden, da ich meinen Produktmanagern nicht zumuten muss languagefiles zu pflegen, sondern ich setze hierzu eine schickes Adminformular auf.
Sämtliche Nabvigationselemente meiner Seite kommen nun mehrsprachig daher. Damit nicht alle Elemente der Navigationsleiste pro request neu übersetzt werden müssen lesen ich sämtliche Elemente der eingestellten Sprache in den Cache und schreibe diese in die Registry um später aus allen Layouts darauf zugreifen zu können. Das ganze geschieht in meinem Layoutplugin, welches den Predispatcher überschreibt um bei späteren Updates nicht alles neu aufsetzen zu müssen. Am Ende schafft mir das 2 Requests pro Sekunde mehr, als wenn ich die Layoutübersetzungen pro Request neu mache.
So cached man unter zend arrays.
1) Bootstrap erweitern (public/index.php)
hier hab e den Autolader aktiviert und das Verzeichnis für die Cachefiles festgelegt. Anschliessend schreibe ich das Cacheobject in die Registy. Ja Ja werden manche sagen. Registry ist ein anderes Wort für Globals, Welche verpöhnt sind.
Aber nur so kann ich im layout auch auf den cache zugreifen.
/** autoloader aktivieren */
Zend_Loader::loadClass("Zend_Loader_Autoloader");
Zend_Loader_Autoloader::getInstance();
/**
* activate variable caching
**/
$frontendOptions = array('lifetime' => 120,
// cache lifetime of 1 minute
'automatic_serialization' => true
);
//zend cache Verzeichnis festlegen
$backendOptions = array(
'cache_dir' => APPLICATION_PATH.'/cache/');
// getting a Zend_Cache_Core object
$cache = Zend_Cache::factory('Core',
'File',
$frontendOptions,
$backendOptions);
//cache object in die Registry
Zend_Registry::set("zend_cache",$cache);
Dann übersetze ich meine Navielemente mit meinem Language_Plugin und schreibe anschliessend alle in meinem Laxoutplugin in den cache aus dem ich nun die navi laden kann .
Plugin (zend/Plugin/layout.php)
class Zend_Plugin_Layout extends Zend_Controller_Plugin_Abstract {
function __construct() {
$this->view = new Zend_View ( );
//sets current speech
new Zend_Plugin_Language ( );
}
/*
* Run at the beginning of the controller’s response object initialization
*/
public function preDispatch(Zend_Controller_Request_Abstract $request) {
//navigationItems in cache?
if (! $this->NavigationItems = Zend_Registry::get ( 'Zend_Cache' )->load ( 'NavigationItems' ))
{
//get Cacheobject from registry
$cache= Zend_Registry::get ( 'Zend_Cache' );
foreach($this->arr_unsortedItems as $item)
{
$item->label = Zend_Plugin_Language::translate ( $item->label);
$item->shortdescription = Zend_Plugin_Language::translate ( $item->shortdescription );
$this->NavigationItems[$item->type][]=$item;
echo"<br>label:".$item->label;
}
$cache->save($this->NavigationItems,"NavigationItems");
Zend_Registry::set("NavigationItems",$this->NavigationItems);
}else
{
Zend_Registry::set("NavigationItems",$this->NavigationItems);
}
}
und hier das language pluging. Die Datenbankzugriffe habe ich über doctrine realisiert.
Damit ich nicht für jedes Wort im Layout an die Datenbank muss, lade ich alle Strings der eingestellten Sprache als array in den cache.
Ob das Suchen im cache schneller ist als der DB zugriff zeigt ein benchmark.
<?php
/**
* Handles the header / footer by capturing the preDispatch and postDispatch of the
* response object
*
*/
class Zend_Plugin_Language extends Zend_Controller_Plugin_Abstract
{
var $app_strings;
var $lang;
function __construct()
{
if(!session_id())
{
session_start();
}
if(!isset($_SESSION['lang']) && $_SESSION['lang']=="")
{
if(!isset($_REQUEST['lang']) && $_REQUEST['lang']=="")
{
$_SESSION['lang'] = $this->lang = "de";
}
}
else
{
if(isset($_REQUEST['lang']) && $_REQUEST['lang']!="")
{
$_SESSION['lang'] = $this->lang = $_REQUEST['lang'] ;
}else
{
$this->lang=$_SESSION['lang'];
}
}
echo"<br>lang:".$this->lang."/".$_SESSION['lang'];
}
/**
* @desc translates a string on a set lannguage
*/
function translate($LBL)
{
//if onöy if Strings not in cache. No need to stress the Database for each word
if (!$this->app_strings = Zend_Registry::get ( 'Zend_Cache' )->load ( "app_strings_".$this->lang ))
{
$this->setAllStrings($this->lang);
}else
{
echo"cache var exists";
}
//throws a notice if label does not exist
return $this->app_strings[$this->lang][$LBL];
}
/**
* @desc save all translated strings of current language into cache to reduce Databaseload
*/
function setAllStrings()
{
$sql = Doctrine_Query::create()
->select('value')
->from('ShopI18N')
->where("lang='".$this->lang."'");
$arr_language = $sql->execute();
foreach($arr_language as $key=>$obj)
{
$this->app_strings[$this->lang][$obj->label] = $obj->value;
}
$cache= Zend_Registry::get ( 'Zend_Cache' );
$cache->save($this->app_strings,"app_strings_".$this->lang);
Zend_Registry::set ( "app_strings_".$this->lang, $this->app_strings);
}
}
?>
public $arr_unsortedItems=array();
public $NavigationItems=array();
private $view;function __construct() {
$this->view = new Zend_View ( );
//sets current speech
new Zend_Plugin_Language ( );
}
/*
* Run at the beginning of the controller’s response object initialization
*/
public function preDispatch(Zend_Controller_Request_Abstract $request) {
//save current module and action to registry
Zend_Registry::set ( “currentController”, Zend_Controller_Front::getInstance ()->getRequest ()->getControllerName ());
Zend_Registry::set ( “currentModule”, Zend_Controller_Front::getInstance ()->getRequest ()->getModuleName ());
if (true !== $this->getResponse ()->isException ())
{
//navigationItems in cache?
if (! $this->NavigationItems = Zend_Registry::get ( ‘Zend_Cache’ )->load ( ‘NavigationItems’ ))
{
$this->setNavigationItems();
}else
{
Zend_Registry::set(”NavigationItems”,$this->NavigationItems);
}
//standardlayouts
$this->setStandardLayouts ();
}
[] }