Am 30. Dezember ist ein kleines Contao Update auf Version 2.10.4 erschienen. Es ist behebt einige Fehler im Cron- und Cache-Handling. Eine komplette Liste kann im Changelog eingesehen werden.
Spam-Kommentare
Na wunderbar. Heute über 50 neue Kommentare mit kurzen schmeichelhaften Sätzen inklusive Rechtschreibfehler. Bei genauem Hinsehen, kommen einige Kommentare von der gleichen IP-Adresse, aber mit komplett anderen Namen und E-Mail-Adressen. Teilweise finden sich bei Google die gleichen Kommentare auch in anderen Blogs…
Mir erschließt sich leider nicht, wozu das gut sein soll. Hier zwei der besagten Kommentare:
- “That’s the best asewnr of all time! JMHO”
- “You rlaely saved my skin with this information. Thanks!”
Typo3 4.6.2 erschienen
Ein Sicherheitsupdate ist heute erschienen, die eine “Remote Code Execution” verhindert. Unter gewissen Umständen kann also PHP-Code ins System eingeschleust werden. Alle Infos dazu auf der Typo-Seite.
Mehrsprachige Inhalte kennzeichen
Google unterstützt die Kennzeichnung von inhaltlich ähnlichen bzw. gleichen Inhalten, die aber in verschiedenen Sprachen vorliegen mit einem zusätzlichen Attribute.
<link rel="alternate" hreflang="de" href="http://www.example.de/page-de.html" />
<link rel="alternate" hreflang="en" href="http://www.example.de/page-en.html" />
Das Attribute hreflang kennzeichnet die verwendete Sprache. Für Inhalte, die nicht als HTML-Seite zur Verfügung stehen, dann dies über einen HTTP-Header gekennzeichnet werden:
Link: ; rel="alternate"; hreflang="es"
Die möglichen Werte müssen sich an der ISO 6391-1 und optional für Regionen an ISO 3166-1 Alpha 2 orientieren.
Hilfsklassen unter Extbase
Eine Hilfsklasse kann in einer Extbase Extension im Classes Verzeichnis platziert werden. Ich empfehle die Klasse in einem Unterverzeichnis zu platzieren. Der Autoloader ist bei richtiger Bennenung in der Lage die Klasse zu laden.
Beispiel:
myextension/Classes/Helper/MyClass.php (Erster Buchstabe im Dateinamen groß schreiben).
Name der Klasse: Tx_Myextension_Helper_MyClass
Ein Datum mit Javascript
Javascript bietet das Date-Objekt an, um mit einem Datum arbeiten zu können. Wir können leicht ein solches Objekt erstellen:
var myDate1 = new Date(2011, 12, 13, 21, 30, 00); var myDate2 = new Date(2011, 12, 13);
Das Objekt selbst bietet Funktionen an, um Eigenschaften des Objekts auszulesen oder zu manipulieren:
- getDate() liefert den Monatstag
- getDay() liefert den Wochentag
- getMonth() liefert den Monat
- getFullYear() liefert das Jahr (vierstellig)
- getHours() liefert die Stunden der Uhrzeit
- getMinutes() liefert die Minuten der Uhrzeit
- …
Eine vollständige Liste findet sich z. B. auf der SELFHTML Referenz. Nun möchte man vielleicht mit einem Datum rechnen oder Vergleiche anstellen, eine Benutzereingabe validieren oder ähnliches. Dazu müssen wir in der Regel noch einiges “drumherum” programmieren. Unterstützung kann hier eine Datumsbibiothek bringen.
Datejs
Das Projekt ist schon älter und das letzte “offizielle” Release wurde 2007 veröffentlicht. Auf der Projektseite wurde die Bibliothek weiter über 1.000.000 mal heruntergeladen. Datejs erweitert das Date-Objekt selbst, d. h. es stehen zusätzliche Funktionen zur Verfügung. Nachfolgend ein kleiner Auszug:
- Date.today() liefert das aktuelle Datum.
- Date.today().next().friday() liefert das Datum des nächsten Freitags
- Date.last().week() liefert das Datum vor einer Woche
- Date.today().addDays(n) addiert n Tage zu dem aktuellen Datum.
- …
Mehr Beispiele finden sich der Projektseite.
Außerdem kann man das Datumsobjekt auch komfortabel setzen:
var time = {hour:18, minute:15};
Date.today().at(time); // heute um 18:15 Uhr
var mydate = {month: 1, day: 20, hour: 20, minute: 30};
Date.today().set(mydate); // aktuelles Jahr, 20. Januar um 20:30 Uhr
Die Bibliothek bietet noch viel mehr Funktionen z. B. für das Parsen von Strings oder für Datumsvergleiche. Wenn wir beispielsweise ein Anfangs- und Enddatum haben und prüfen wollen, ob ein bestimmtes Datum innerhalb dieser Zeitspanne liegt, so kann das mit folgender Zeile geprüft werden:
Date.today().between(startDate, endDate) // true|false
Eine Lokalisierung von Ausgaben ist möglich. Es gibt bereits fertige Spracherweiterungen
<!-- de-DE (deutsch) --> <script type="text/javascript" src="date-de-DE.js"></script>
Moment.js
Eine weitere, relative junge “Date Library” ist Moment.js. Anstatt das Date-Objekt zu erweitern, wird hier mit einem Wrapper gearbeitet.
var mydate = moment(new Date(2011, 12, 13));
Mit diesem Objekt kann ähnlich wie unter Datejs gearbeitet werden:
mydate.add('days', 11); // addiert 11 Tage mydate.subtract('months', 1); // ein Monat zurück mydate.year(2012); // setzt das Jahr auf 2012
Eine Differenz kann folgendermaßen berechnet werden:
var a = moment([2011, 12, 24]); var b = moment([2011, 12, 25]); a.diff(b);
Ab und zu braucht man vielleicht auch wieder das Date-Objekt:
mydate.native();
In der Dokumentation habe ich leider keinen Hinweis gefunden, um zu prüfen, ob ein Datum zwischen zwei Zeiträumen liegt. Vom Umfang her ist diese Bibliothek natürlich schön schlank. Eine Lokalisierung ist auch möglich.
Formular unter Zend validieren
Ich nehme mal an, dass wir den Rumpf eines Formulars vorliegen haben (zf create form…) und eines der Felder validieren wollen:
class Application_Form_MyForm extends Zend_Form { // initialization public function init() { $this->setMethod('post'); $this->addElement( 'text', 'myelement', array( 'label' => 'Mein Element*:', 'required' => true, 'filters' => array('StringTrim'), 'validators' => array(array('stringLength', false, array(8, 8)), array('digits'), array(new Application_Form_Validator_MyValidator())) ) );
Dem Element myelement werden unterschiedliche Validatoren hinzugefügt z. B. das nur Zahlen erlaubt sind (digits). Die Validatoren, die das Zend Framework bereits mitbringt, findet man im Verzeichnis Validate. Interessant ist an dieser Stelle der eigene Validator. Damit das ZF den Validator findet muß man zuerst den Autoloader anpassen. Bei mir liegt die Klasse Application_Form_Validator_MyValidator im Verzeichnis application/forms/validators und ist als MyValidator.php abgespeichert. Die Autoloader-Anweisung in der Bootstrap-Klasse lautet wie folgt:
$loader=$this->getResourceLoader(); $loader->addResourceType('validators', 'forms/validators', 'Form_Validator');
Der Validator selbst leitet von der abstrakten Klasse Zend_Validate_Abstract ab und sieht exemplarisch folgendermaßen aus:
class Application_Form_Validator_MyValidator extends Zend_Validate_Abstract { // consts const INVALID='invalid'; //---- // properties protected $_messageTemplates = array(self::INVALID=> "'%value%' ist kein gültiger Wert"); //---- // validation public function isValid($value, $context = null) { $this->_setValue($value); // validierung if(true) // pseudo code return true; $this->_error(self::INVALID); return false; } }
Zugriff auf mehrere Datenbanken unter Zend
Wenn man innerhalb einer Zend Anwendung auf verschiedenen Datenbanken (mysql, mssql, etc.) zugreifen möchte, kann die Verbindungen in der application.ini hinterlegen:
resources.db.adapter = "pdo_mysql" resources.db.params.host = "localhost" resources.db.params.username = "xxx" resources.db.params.password = "yyy" resources.db.params.dbname = "zzz" resources.db.isDefaultTableAdapter = true resources.multidb.db1.adapter = "Sqlsrv" resources.multidb.db1.host = "server-1" resources.multidb.db1.dbname = "xxx" resources.multidb.db1.username = "yyy" resources.multidb.db1.password = "zzz" resources.multidb.db1.charset = utf8 ...
Anschließend kann die Instanz des Adapters geholt werden:
$front=Zend_Controller_Front::getInstance(); $bootstrap=$front->getParam('bootstrap'); $resource=$bootstrap->getPluginResource('multidb'); /** * @var Zend_Db_Adapter_Sqlsrv */ $db=$resource->getDb('db1');
Super, oder?
Interoperabilität zwischen Typo3 und MSSQL
Wer sich schon einmal den Wiki-Eintrag zu MSSQL durchgelesen hat, wird schnell merken, dass Typo3 an der einen oder anderen Stelle nicht wirklich rund mit der Microsoft Datenbank zusammenarbeiten wird. Ob diese Info aus dem Wiki noch aktuell ist, steht auf einem anderen Blatt… dort aufgeführte Bugmeldungen wurden jedoch bereits behoben. Ich habe jedoch einige Blog-Einträge (siehe Links unten), gefunden, die von “großem” Aufwand sprechen, ein Typo3 unter MSSQL zu installieren. Die Unterstützung scheint jedoch besser zu werden. Zumindest stellt eine PHP Installation unter Windows kein Problem mehr da. Wer den Typo-Source gern wie unter Linux mittels symbolischen Link in sein Projekt einbinden will, kann das auch unter Windows mit einem kleinen Tool Junction von Microsoft ermöglichen.
Für die Bildgenerierung muß ImageMagick und Ghostscript installiert werden. Auch dies ist für Windows verfügbar.
Das “Rewrite” von URLs erfordert Zusatzaufwand ist jedoch auch in einem Typo3-Wiki-Eintrag beschrieben.
Das größtes Problem, das ich sehe, sind jedoch die Erweiterungen, die nicht unbedingt mit MSSQL kompatibel sein müssen. Diese sind dann entsprechend zu testen.
Wer seine Webseite unter Typo3 betreiben will und Daten von einem Microsoft SQL Server benötigt, könnte auch das Typo3 auf MySQL betreiben. MySQL läuft problemlos auf einem Windows-Server und ist (mitterweile) auch dort nicht wesentlich langsamer als unter Linux. Die Daten des MSSQL-Servers können in einer eigenen (Extbase-)Extension verarbeitet und dargestellt werden. Ich denke da z. B. an ein Produktmodul, dass die Produkteinformationen aus dem ERP-System erhält. Leider habe ich die Vermutung, dass Extbase keine komfortables Möglichkeit für den Zugriff auf MSSQL bietet, zumindest habe ich dazu nichts gefunden. Mag sein, dass das mit Typo5 mit Flow besser wird, da dort wohl Doctrine als Abstraktionsschicht verwendet wird, aber bis dahin wird noch etwas Zeit vergehen.
Aber was spricht dagegen den Zugriff auf die Datenbank mit etwas anderem durchzuführen? Nix (naja, ein paar Argumente gibts sicherlich). Und wie? Beispielsweise mit dem Zend Framework. Ich habe dazu eine Extension geschrieben, die den Autoloader des ZF einbindet (Extension an erster Stelle laden “top”). In jeder anderen Extension kann mittels passendem Zend Adapter eine Verbindung aufgebaut werden. Natürlich gibt es auch damit das eine oder andere Problem z. B. funktioniert der für den Microsoft SQL Server benötigte Adapter nur mit der PHP Erweiterung sqlsrv und wird erst aber Microsoft SQL Server 2005 oder höher unterstützt (darunter funktionierte bei mir die limit(Anzahl, Offset) Funktion nicht korrekt… ich hab den Adapter abgeleitet und diese Funktion überschrieben). Ansonst kann man nicht das ORM von Extbase verwenden, aber zumindest kann man sich daran “orientieren”, indem man die Zugriffe auf MSSQL-Daten in einer Repository-Klasse kapselt.
Fazit:
Wenn man ein Typo3-System auf MSSQL betreiben will, kann dies sicherlich mit etwas Aufwand hinbekommen. Wenn man jedoch die Möglichkeit hat MySQL unter Windows zu betreiben, würde ich das auch tun. Meist liegen die Daten im Business-Umfeld auf Windows-Servern und stammen dann wohl von anderen Anwendungen, die sowieso durch eine spezielle Implementierung aufbereitet werden müssen.
Links:
- Ein steiniger Weg: MSSQL 2008 und TYPO3 (2010)
- MSSQL Database (2011)
Zeilenumbrüche mittels Javascript umwandeln
Der folgende Javasript-Code orientiert sich an der nl2br-Funktion der php.js Seite. Ich habe die Funktion nl2html benannt, die noch flexibler verwendet werden kann. Da das Javascript String Objekt erweitert wird, läßt sich die Funktion ganz einfach verwenden:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script type="text/javascript"> //<![CDATA[ String.prototype.nl2html = function() { return (this + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ ((typeof arguments[0] === 'undefined') ? '<br />' : arguments[0]) +'$2'); }; //]]> </script> <style type="text/css"> br.foo { border:1px solid black; } </style> </head> <body> <div id="test"> Das ist ein Text mit Zeilenumbrüchen ... </div> <div id="test2"></div> <script type="text/javascript"> var el=document.getElementById('test'); var val=el.innerHTML; document.getElementById('test').innerHTML=val.nl2html(); document.getElementById('test2').innerHTML=val.nl2html('<hr />'); </script> </body> </html>

