Zend Acl mit Ini Konfiguration und Resourcen
Ich hatte bereits einmal einen Artikel über eine Acl mit INI Konfiguration. Dort gab es einen Kommentar von evilmonkey, den ich sehr anregend fand und mir nun einmal die Zeit genommen habe diesen umzusetzen.
Die Konfiguration basiert auf einer Zend_Acl und wird mit einer Ini Datei über Zend_Config_Ini befüllt. Das ganze funktioniert als Resource mit dem Bootstrapping. Vielleicht ist es für den ein oder anderen eine Anregung.
Übersetzung ohne ViewHelper
Jeder, der mit Übersetzungen, im Zend Framework arbeitet kennt es. Das lange ungetüm, das es braucht um einen einzelnen String im View zu übersetzen. Dafür gibt es aber eine Lösung, eine Kurzfassung, die ich hier vorstellen will. Das Zend Framework bietet einem Filter für den View. Filter, die nach dem Rendern eines Views ausgeführt werden und zum Ziel haben die Ausgabe im Nachhinein zu verändern. Einen solchen Filter stelle ich hier nun zur Verfügung.
Translate Resource
Oftmals wird hier im Blog das Thema Zend_Translate angesprochen. Die bisherigen Themen dazu sind aber leider entsprechend veraltet und so soll hier auch in diesem Bereich etwas Moderne den Einzug halten. Ich habe für mein kleines Projekt eine eigene Translate Resource mit Modulfähigkeit geschrieben. Im Folgenden will ich ein kurzes Beispiel zur Verwendung der Resource bringen. Es ist dabei unbedingt zu beachten, dass ich in dieser einfachen Version der Resource auf Exceptions verzichtet habe. Diese werden im Laufe der Zeit noch dazu kommen, ebenso wie die nötige Cache Funktionalität. Mein Beispiel basiert auf TMX Dateien, welche ich persönlich empfehle, da sie XML Dateien sind und somit leicht über ein entsprechendes Frontend zu bearbeiten sind. Dieses kann sich zum Beispiel im Adminbereich einer Website finden.
Nun beginnen wir.
Ich will im View einen String ausgeben. Natürlich verwende ich dafür den entsprechenden ViewHelper. Wenn man dies jedoch einbaut, dann wird man feststellen, dass es keine Übersetzung gibt, sondern der String an sich ausgegeben wird.
< ?php echo $this->translate('testMessage'); ?>
Um nun der Applikation die Mehrsprachigkeit hinzuzufügen braucht es einige erst einmal der Resource, die sich am Ende dieses Artikels findet. Ich gehe davon aus, dass hier ein Basiswissen Resourcen besteht und man weiß, wie man sie einbindet. Um die Resource zu aktivieren und zu konfigurieren braucht es in der Konfigurationsdatei der Applikation, bei mir die application.php, einiger Variablen.
Zend_Mail Filestream
Um Zend_Mail zu testen benötigt man keinen Online Mailserver oder einen Webserver auf seinem lokalen Entwicklungssystem. Warum nicht mit einem Transporter arbeiten, der einem die versandten E-Mails in eine Datei schreibt? Und genau das stelle ich hier vor.
Man benötigt zuerst in seiner Library den Transporter
class Zorta_Mail_Transport_File extends Zend_Mail_Transport_Abstract
{
public function _sendMail()
{
$file = APPLICATION_PATH . "/../logs/mails.log";
$fp = fopen($file, 'a');
fwrite($fp, $this->header);
fwrite($fp, "\r\n");
fwrite($fp, $this->body);
fwrite($fp, "\r\n\r\n\r\n#############################################################\r\n\r\n\r\n");
fclose($fp);
}
}
Mit diesem Transporter ist es schon fast erledigt. Was wird hier getan? Ganz einfach. Es gibt ein Verzeichnis logs und darin eine Datei mail.log. Diese öffnet der Transporter und gibt den Header und den Body hinein. Mehr Daten benötigt man normalerweise nicht. Falls doch, so kann man den Transporter durchaus erweitern. Zum Beispiel um die Anhänge einer E-Mail usw.
Um nun automatisiert den Transporteu zuzuordnen kann man in der Bootstrap den folgenden Code verwenden.
protected function _initMail()
{
if(APPLICATION_ENV == "development")
{
$mail_transport = new Zorta_Mail_Transport_File();
Zend_Mail::setDefaultTransport($mail_transport);
}
else
{
$mail_conf = Zend_Registry::get('CONFIG')->mail;
$config = array('auth' => 'login',
'username' => $mail_conf->smtp->user,
'password' => $mail_conf->smtp->pass);
$mail_transport = new Zend_Mail_Transport_Smtp($mail_conf->smtp->host, $config);
Zend_Mail::setDefaultTransport($mail_transport);
}
}
Es wird geprüft, ob man im Entwicklungsstadium ist. Die Konstante “APPLICATION_ENV” beinhaltet dies. Wenn man sich in Entwicklung befindet, dann greift er auf den, so eben erstellten, Datei Transporter zu. Ansonsten wird auf den SMTP Transporter zugegriffen. Wie man die Konfiguration des SMTP Transporters initalisiert ist einem selbst überlassen, daher gehe ich hier nicht weiter auf das obige Beispiel ein. Mittels der Methode “setDefaultTransport” wird für das Zend_Mail global der Transporter gesetzt.
Wenn man nun eine E-Mail erstellt und versendet landet sie in angegebener Textdatei und sieht in etwa so aus:
From: Zorta Dateiemail <test@zorta.de> To: Alberto <denis_zunke@gmx.de> Subject: Testnachricht Date: Thu, 28 May 2009 21:51:40 +0200 Content-Type: multipart/alternative; charset="UTF-8"; boundary="=_5e42e31ef1a7fb8fe32142a32f672f11" MIME-Version: 1.0 --=_5e42e31ef1a7fb8fe32142a32f672f11 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Textinhalt --=_5e42e31ef1a7fb8fe32142a32f672f11 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <b>HTML INHALT</b> --=_5e42e31ef1a7fb8fe32142a32f672f11--
Mehrsprachigkeit mit Zend_Application
Eine Multilinguale Seite mit Zend_Application aufzubauen ist gar nicht so schwer, wie man denkt. Ich gehe hier davon aus, dass man schon Erfahrung mit Zend_Application hat und werde es nicht in jeder Kleinigkeit erklären. Das ganze basiert auf dem Zend Framework 1.8.1
Wenn man am Ende alles richtig eingebaut hat anhang der Beispieldaten, dann sind die Sprachen Deutsch und Englisch verfügbar über die folgenden Adressen:
http://en.domain.tld -> Englisch
http://de.domain.tld -> Deutsch
http://fr.domain.tld -> Deutsch, da dies als Standard gesetzt wird in der Bootstrap
Zuerst einma benötigt man Translate Dateien. Ich habe dafür eine Verzeichnisstruktur angelegt, in der sich ein Ordner für jede Sprache findet. In meinem Fall sind dies “de” und “en”. In diesen liegen dann die verschiedenen PHP Dateien mit Arrays. Hier kurz Beispielhaft für Deutsch und Englisch jeweils die string.php
return array( 'WELCOME' => 'Willkommen zum Test' );
return array( 'WELCOME' => 'Welcome to the Test' );
Über die application.ini setzt man die nötigen Routen, Locale und Translate Einstellungen. Bitte die angegebene Domain im Router auch in die richtige ändern.
resources.router.routes.language.type = "Zend_Controller_Router_Route_Hostname" resources.router.routes.language.route = ":lang.domain.tld" resources.router.routes.language.defaults.controller = "index" resources.router.routes.language.defaults.action = "index" resources.router.routes.language.defaults.lang = "de" resources.router.routes.language.chains.index.type = "Zend_Controller_Router_Route" resources.router.routes.language.chains.index.route = ":controller/:action/*" resources.router.routes.language.chains.index.defaults.module = "default" resources.router.routes.language.chains.index.defaults.controller = "index" resources.router.routes.language.chains.index.defaults.controller = "index" resources.router.routes.language.chains.base.type = "Zend_Controller_Router_Route" resources.router.routes.language.chains.base.route = "/*" resources.router.routes.language.chains.base.defaults.module = "default" resources.router.routes.language.chains.base.defaults.controller = "index" resources.router.routes.language.chains.base.defaults.controller = "index" resources.translate.adapter = "array" resources.translate.data = APPLICATION_PATH "/languages" resources.translate.locale = "en" resources.translate.options.disableNotices = true resources.translate.options.scan = "directory"
Und zuletzt die Bootstrap Klasse
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initRequest()
{
// Nötige Abhängigkeiten auflösen
$this->bootstrap('FrontController');
$this->bootstrap('router');
// Den Frontcontroller holen
$front = $this->getResource('FrontController');
// Ein Request Objekt in den Frontcontroller setzen
$request = new Zend_Controller_Request_Http();
$request->setBaseUrl('/');
$front->setRequest($request);
// Den Request in die Registry des Bootstrap Objekt setzen
return $request;
}
protected function _initLang()
{
// Die nötigen Abhhängigkeiten aufbauen
$this->bootstrap('FrontController');
$this->bootstrap('router');
$this->bootstrap('translate');
// Den Frontcontroller mit dem Request Objekt holen und den Router ausführen
$front = Zend_Controller_Front::getInstance();
$request = $front->getRequest();
$router = $front->getRouter();
$router->route($request);
// Das Translate Objekt holen
$lang = $this->getResource('translate');
// Prüfen, ob die ausgewählte Sprache zur verfügung steht, wenn nicht, dann Standard setzen.
if (!$lang->isAvailable($front->getRequest()->getParam('lang','de'))) {
$front->getRequest()->setParam('lang','de');
}
// Die ausgewählte Sprache in das Translate setzen
$lang->setLocale($front->getRequest()->getParam('lang'));
return;
}
}
Zum Test kann man sich einen String ausgeben lassen in der View
<?=$this->translate('WELCOME')?>
Das ganze ist natürlich noch um einige Features erweiterbar, aber mit diesen Schritten hat man eine gute Basis um weiter zu kommen. Interessant sind für den Einbau wohl noch Zend_Cache, entsprechende andere Router oder das speichern der Standardsprache in der Konfiguration für schnelle Änderungen.
