CakePHP/mod_rewrite: Bestimmten Ordner von RewriteRules ausschließen

Die RewriteRules bei CakePHP sind so eingestellt, dass man an Ordner im root-Verzeichnis nicht dran kommt. Möchte man bspw. einen bestimmten Ordern von der RewriteRule ausschließen, muss folgende Regel in die .htaccess dazugeschrieben werden (im root-Verzeichnis von CakePHP):

RewriteRule ^Ordnername – [L,NC]

wobei – ausdrückt, dass nichts passieren soll
L steht für Last Rule
und NC für no-case, so dass Groß-/Kleinschreibung ignoriert wird (ordnername wird also auch erreicht)

Alles was nun mit “Ordnername” beginnt, betrifft diese Regel.

CakePHP: Input Validierung mit mehreren Regeln

Fast einen Monat ist es her seit dem letzten Post. Nur ein kleiner Tipp und auch kein besonders aufwändiger für multiple Validierungsfeldern pro Eingabefeld. Die Überprüfung eines Eingabefeld für eine deutsche Bankleitzahl könnte beispielsweise so im Model implementiert werden:

var $validate = array(
'blz' => array(
									'minLength' => array(
										'rule' => array('minLength', 8),
										'message' => 'Bitte geben Sie eine gültige Bankleitzahl eines deutschen Bankinstituts ein.'),
									'maxLength' => array(
										'rule' => array('maxLength', 8),
										'message' => 'Bitte geben Sie eine gültige Bankleitzahl eines deutschen Bankinstituts ein.'),
									'numeric' => array(
									'rule' => 'numeric',
									'required' => true,
									'message' => 'Bitte geben Sie nur Zahlen als Bankleitzahl ein.'))
)

CakePHP: This email was sent using the CAKEPHP framework

Um diesen schönen Satz einmal nicht in einer mit der Email-Component versendeten Email zu erhalten, genügt es, das default-layout für die Emails in der App zu überschreiben. Also einfach eine “default.ctp” Datei innerhalb “app/views/layouts/email/html” bzw. “app/views/layouts/email/text” erzeugen mit dem Inhalt:

echo $content_for_layout

Das war’s auch schon.

CakePHP: Validierung ohne zu Speichern

Es kann vorkommen, da möchte man die Nutzereingaben in einem Formular zunächst nur validieren, bevor sie in der Datenbank gespeichert werden. Dies kann zum Beispiel bei einem Bestellvorgang sein, bei dem die eingegebenen Nutzerangaben noch einmal zur Übersicht dem Nutzer angezeigt werden soll und erst nach dieser Prüfung gesichert werden sollen.
Dafür stellt CakePHP die Methode ‘validates()‘ des Models bereit.

In der CakePHP-Dokumentation steht genau dieser Anwendungsfall beschrieben, jedoch überliest man auf die schnelle ggf. eine wichtige Stelle: Vor der Validierung müssen die Daten auf jeden Fall dem Model übergeben werden.

$this->Modelname->set($this->data);
if($this->Modelname->validates()) { #Alles ok, Überprüfungsseite anzeigen
#....
} else { #Daten validieren nicht
#...
}

CakePHP: dateFormat und timeFormat

Mit Hilfe des Form-Helpers lassen sich bequem Eingabefelder für Datums- oder Zeitangaben erstellen. Der Form-Helper erkennt aus der Datenbank heraus, was für ein Input-Feld er generieren muss. Um die Anordnung der entstehenden Select-Felder an das deutsche Format anzupassen, kann dem ‘options’-Array einmal der Schlüssel “dateFormat” für Datumsangaben und der Schlüssel “timeFormat” für Zeitangaben übergeben werden.

Um ein Datum in das deutsche Format zu bringen genügt als Wert die Angabe “DMY”. Bei “timeFormat” gibt man “24″ für die deutsche 24-Stunden Darstellung an.

		echo $form->input('tag', array('label' => 'Tag:', 'dateFormat' => 'DMY'));
		echo $form->input('von', array('label' => 'von:', 'timeFormat' => 24));

CakePHP 1.3.4: Datenvalidierung und eine Warnung

Eventuell kommt die folgende Warnung bei einer Datenvalidierung im Model:

Warning (2): preg_match() [function.preg-match]: Empty regular expression [CORE/cake/libs/model/model.php, line 2596]

Die Warnung trat auf, als zwar der ‘rule’-Schlüssel im Validierungsarray angegeben wurde, er jedoch nur auf ‘false’ stand. Sobald eine Regel angegeben wird, tritt diese Warnung nicht mehr auf.
Es muss also immer eine Regel angegeben werden!

var $validate = array(
						'name' => array(
									'rule' => 'notEmpty',
									'required' => true,
									'message' => 'Bitte gib Deinen Nachnamen ein.'),
						'vorname' => array(
									'rule' => 'notEmpty',
									'required' => true,
									'message' => 'Bitte gib Deinen Vornamen ein.'),
						'email' => array(
									'rule' => array('email', true),
									'message' => 'Bitte gib Deine eMail-Adresse ein.'));

CakePHP: $displayField funktioniert nicht innerhalb von Plugins?!

Es existiert eine $belongsTo-Beziehung, angenommen zwischen einem Impressum und einem Buch. Das Impressum-Model wurde also entsprechend mit dem $belongsTo-Attribut beschrieben. Nun soll ein neues Impressum eines Buches angelegt werden und dafür soll bpsw. nicht der Buchname aus dem Buch-Model, sondern die ISBN-Nummer als Referenz herangezogen werden. Also bekommt das Buch-Model das Model-Attribut $displayField = ‘isbn’. Das scheint aber nicht zu funktionieren. Wenn jemand weiß warum nicht, dann bitte kommentieren! Ich freue mich auf antworten! Bis dahin kann man das natürlich umgehen, indem man das $displayField-Atribut unmittelbar vor dem Aufruf im Controller zur Laufzeit setzen lässt:

#innerhalb des impressum controller
$this->Impressum->Buch->displayField = 'isbn';
$this->set('buch',$this->Impressum->Buch->find('list');

Das Ganze findet innerhalb eines Plugins statt. Nennen wir das Plugin “Bibliothek”…Muss man hier etwas beachten?

Das erdachte Szenario möge man mir verzeihen. Es geht hier nur ums Prinzip ;-)

 

Die Lösung ist gefunden!

Näheres dazu und ergänzt um virtuelle Felder im Blog “CakePHPDoku”

CakePHP: Ajax Layout

Werden Links oder Formulare mittels des AJAX-Helpers erstellt, um die Daten ansynchron zu laden und in einem DIV-Bereich anzuzeigen, wird in diesem DIV ggf. das Default-Layout genutzt. So kommt es dann zum Effekt der “Seite in der Seite”. Um das zu vermeiden, muss das Layout bspw. in der Methode (Action) entsprechend gesetzt werden. Möglich ist ein eigenes AJAX-Layout zu entwerfen oder aber gar kein Layout zu nutzen:

function TuDingeUndZeigeSieDannImDivAn () {
   $this->layout = '';
   $ergebnis = $this->tuWas();
   $this->set('view',$ergebnis);
}

CakePHP: Fatal error: Class ‘ConnectionManager’ not found in … sanitize on line 72

Falls mir jemand den Fehler erklären möchte, ich freue mich über jede Antwort!
Die Lösung zumindest liefert das einbinden des ‘ConnectionsManagers‘ in den Controller, in dem auch eine sanitize-Methode zum Einsatz kommt.

App::Import('ConnectionManager'); 

Diese Zeile muss vor Beginn der Deklaration der Klasse stehen, ganz genauso wie auch der Import der Sanitize-Klasse.
Ich habe keine Ahnung, wieso CakePHP (1.2.6) den ConnectionManager nicht direkt im Core ordentlich mit eingebunden hat.

Also Feuer frei für Kommentare!!!

CakePHP: Fatal error: Call to undefined method stdClass::send()

Wer in das Verlangen kommt, die Email-Component von CakePHP nutzen zu wollen, sollte sich stets eines Schusselfehlers bewußt sein. Die Email-Component bindet man wie gewöhnlich über

$components = array('Email');

in den jeweiligen Controller ein. Wer jedoch bei ‘$components’ das ‘s’ vergisst (Schusselfehler) erhält die im Titel dargestellte Fehlermeldung.

CakePHP: Redirect auf statische Seite

Vermutlich kommt das Problem seltener vor, aber nichts destotrotz verdeutlicht es ganz anschaulich die Funktionsweise der ‘redirect‘-Methode.
Angenommen man befindet sich innerhalb eines Controllers in einem Plugin und möchte nach der Ausführung einer Methode auf eine statische Seite umleiten (redirecten), dann übergibt man dieser Methode mehrere Parameter in der folgenden Form:

$this->redirect(array('controller' => 'pages', 'action'=>'display','ueberuns/kontakt', 'plugin' => null));

Der ‘action‘-Schlüssel muss ‘display‘ als Wert haben, da nur diese Methode im pages_controller existiert. Damit der pages_controller weiß, welche statische Seite aufgerufen werden soll, wird als weiterer Parameter die View übergeben (in diesem Fall die View ‘kontakt‘ im Ordner ‘ueberuns‘. Damit das Ganze nicht innerhalb des momentanen Plugins stattfindet, setzen wir den ‘plugin‘-Schlüssel noch null und schon funktioniert der Redirect.

CakePHP: Breadcrumb-Helper

Einen funktionierenden Breadcrumb-Helper gibt es in der CakePHP bakery. Kann diesen Helper nur empfehlen. Er funktioniert wunderbar. Eine Ausnahme: Die Auto-Analyse (dritter Parameter = ‘auto’) scheint in statischen Seiten (pages_controller) ab der dritten Ebene nicht zu funktionieren. Ist aber nicht weiter schlimm, denn man kann den Parameter ja manuell setzen.

Hier ist der Link!

CakePHP: lastlogin eines Nutzers speichern

Um den letzten erfolgreichen Login eines Nutzers in einem Feld ‘lastlogin‘ zu speichern, muss in der login()-Methode des UsersController folgender Code eingefügt werden:

if ($this->Auth->user()) { 
 $this->User->id = $this->Auth->user('id'); 
 $this->User->saveField('lastlogin', date("Y-m-d H:i:s")); 
 $this->redirect('/controller/action'); 
}

Damit das ganze auch aufgerufen wird, muss im app_controller noch das autoRedirect ausgestellt werden. Dies erklärt auch die redirect()-Methode in der oben dargestellten login()-Methode.

Im app_controller muss also noch folgendes stehen (oder im beforeFilter() des UsersController)

$this->Auth->autoRedirect = false;

CakePHP: Monatsnamen auf Deutsch

Leider funktioniert die Angabe von

setlocale(LC_TIME,"de_DE"); #oder
setlocale(LC_TIME,"deu"); #oder
setlocale(LC_TIME,"ge");

in der ‘bootstrap.php’ nicht, um deutsche Monatsnamen in Formularfeldern mit Datumsangaben zu erhalten.
Daher der Umweg über die Lokalisierungsdatei:

Verzeichnis “deu” im Ordner “app/locale” anlegen.
Verzeichnis “LC_MESSAGES” im grade erstellen “deu” Ordner anlegen.
Datei “default.po” in diesem Ordner anlegen.

In die ‘default.po’ nun die Übersetzungen in der Form

msgid "January"
msgstr "Januar"

msgid "February"
msgstr "Februar"

...

schreiben. Fertig!

CakePHP: Plugins mit AuthComponent schützen oder ‘Wie erstelle ich ein Plugin, welches ebenfalls den UsersController der Hauptanwendung nutzt?’

Normalerweise wird durch die ‘loginAction‘-Variable der AuthComponent die Action definiert, die bei dem Versuch eine geschützte Seite aufzurufen, angezeigt werden soll.

Wenn ein Plugin in eine CakePHP-Anwendung eingebunden und ebenfalls durch die AuthComponent geschützt werden soll, dann wird der Nutzer auf eine Seite in der Form ‘http://www.domain.de/plugin_name/users/login‘ weitergeleitet. Ist letztendlich auch logisch, denn CakePHP geht davon aus, dass der UsersController Teil des Plugins ist.

Um dies zu umgehen und den “richtigen” UsersController der Hauptanwendung aufzurufen, muss der ‘loginAction‘ der AuthComponent eine weitere Variable, nämlich ‘plugin‘, übergeben werden. D.h. normalerweise in der beforeFilter()-Methode des UsersController oder des AppController muss der Aufruf folgendermaßen lauten:

 $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login', 'plugin' => null);

Anschließend nutzt CakePHP den UserController als globalen UserController.

PS: Eine ähnliche Problematik tritt bei

$html->link();

usw. auf. Auch hier muss der Parameter ‘plugin‘ übergeben werden.

YAML, CakePHP und die IE-Kommentare

Das YAML-Framework ermöglicht browserübergreifendes CSS Layout. Die entsprechenden IE Einschränkungen werden, wie so üblich, mit Kommentaren und Bedingungen realisiert. Zu beachten ist, dass die HTML-Kommentare der korrekten HTML-Konvention entsprechen, da sonst Fehler auftreten, wie z.B.

  • Anzeige von <!–[endif]–> im Browserfenster (geringeres Problem)
  • Javascript-Fehler bei CakePHP in Verbindung mit den AJAX-Helpern, Scriptaculous und Protoype. (größeres Problem)

Also immer schön an die Webstandards halten ;-)