[PHP] Ermitteln des letzten Samstags im Monat

Ich war im Netz auf der Suche nach der Funktionalität „letzter Samstag im Monat“. Das folgende Script/Funktion konnte mein Anliegen lösen.

/**
 * @param string $initial Timestamp des Ausgangsdatums
 * @param string $select Startdatum im Format "first saturday" bzw "last sunday",
 *                       mögliche Optionen sind "first, second, third, fourth, fifth, last"
 * @return array|mixed  Timestamp des gewünschten Datums
 */
function calculateWeekdays($initial = '', $select = '') {
    if(empty($select))$select   = array();
    if(empty($initial)) $initial    = time();

    $target        = array('first'    => 0,
        'second'=> 1,
        'third'    => 2,
        'fourth'=> 3,
        'fifth'    => 4,
        'last'    => 5);

    $s2long        = array('sunday'    => 'sun',
        'monday'    => 'mon',
        'tuesday'    => 'tue',
        'wednesday'    => 'wed',
        'thursday'    => 'thu',
        'friday'    => 'fri',
        'saturday'    => 'sat');

    $pattern    = array('0'    => 'sun',
        '1'    => 'mon',
        '2'    => 'tue',
        '3'    => 'wed',
        '4'    => 'thu',
        '5'    => 'fri',
        '6'    => 'sat');

    $weekdays = array();
    for($i=1;$i<=date('t', $initial);$i++) {
        $temp    = date('Y', $initial).'-'.date('m', $initial).'-'.$i;
        $date    = strtotime($temp);
        for($d=0;$d<7;$d++) {
            if(date('w', $date) == $d) {
                $weekdays[$pattern[$d]][]    =     $date;
            }
        }
    }

    $select    = explode(' ', $select);
    if(count($select)<2) return array();
    $key    = $s2long[strtolower($select[1])];

    $key2    = $target[$select[0]];
    $return    = ($key2 == 5) ? end($weekdays[$key]):$weekdays[$key][$key2];

    if(empty($select)) return $weekdays;

    return $return;
}

Source: Berechnen von Wochentagen

Beliebige Texte in Zend Form integrieren

Um einen beliebigen „HTML“-Text in ein Zend-Formular zu integrieren sind folgende zwei Schritte notwendig:

1. Anlegen einer Klasse welche von Zend_Form_Element_Xhtml ableitet und den ViewHelper ‚formNote‘ implementiert:

/**
 * Lädt den View-Helper Zend_View_Helper_FormNote
 */
class MyClass_Form_Element_Note extends Zend_Form_Element_Xhtml
{
    public $helper = 'formNote';
}

2. Instanzieren der angelegten Form_Element-Klasse innerhalb der Zend_Form:

$note = new MyClass_Form_Element_Note('note');
$note->setValue('<p><b>Ich</b> bin ein beliebiger HTML-Text</p>');
$this->addElement($note);

Decorator können ebenfalls wie gewohnt benutzt werden.

Datumsumwandlungen mit Zend_Date

Um Datumsangaben vom deutschen Datumsformat in das englische Datumsformat umzuwandeln (bspw. für eine Datenbankquery), kann man Zend_Date benutzen. Folgendes Codesnippet zeigt, wie einfach eine solche Datumsumwandlung realisiert werden kann.

$date = new Zend_Date('29.11.2011', 'd.m.Y');
$date->toString('Y-m-d');

Als Output bekommt man ein Datum der Form ‚2011-11-29‘. Klappt natürlich auch andersrum.

Alternativ kann man das Ganze auch über natives PHP umsetzen. Das Ganze sieht dann folgendermaßen aus:

$date = date('Y-m-d', strtotime('29.11.2011'));

Zend Tutorial – Modulabhängiger Wechsel des Layouts

Das Wechseln des Design in Abhängigkeit von eurem Modul kann im Zend Framework über ein Plugin realisiert werden. Legt dazu im Ordner application/Plugin/Layout die Datei Changer.php an und füge folgenden Inhalt in die Datei:

class Plugin_Layout_Changer extends Zend_Controller_Plugin_Abstract
{
    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        //Prüft ob eine Layoutdatei in Abhängigkeit vom Modulnamen existiert
        if(is_file(Zend_Layout::getMvcInstance()->getLayoutPath()
        .$request->getModuleName().'.phtml'))
        {
            //wenn ja, dann diese setzen
            Zend_Layout::getMvcInstance()->setLayout($request->getModuleName());
        }
        else
        {
            //wenn nicht, dann Standardlayout setzen, hier: bibo
            Zend_Layout::getMvcInstance()->setLayout('bibo');
        }
    }
} 

Jetzt müsst ihr noch in eurer Bootstrap-Datei eurer Anwendung das Plugin initialisieren. Fügt dazu einfach folgende Methode eurer Bootstrap-Klasse hinzu:

protected function _initLayoutChanger()
{
	$this->bootstrap('frontController');
	$this->getResource('frontController')
		 ->registerPlugin(new Plugin_Layout_Changer());
}

Überprüft, ob folgende Einträge in eurer application.ini vorhanden sind:

bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
autoloadernamespaces.0 = "Plugin_"

Nun ändert sich automatisch das Layout, in Abhängigkeit von eurem Modulnamen. Achtet darauf, dass die entsprechende Layoutdatei im Ordner application/layouts/scripts/ genauso benannt ist, wie euer Ordnername des Moduls. Bei mir existieren beispielsweise im Ordner application/modules/ die Module „bibo“ und „login“. Demzufolge heißen meine Layoutscripte im Ordner application/layouts/scripts auch „bibo.phtml“ und „login.phtml“. Existiert keine entsprechende Layoutdatei, wird das in der Changer.php im else Zweig angegebene Layout geladen (in meinem Fall das Layoutscript bibo.phtml).

Zend Tutorial – 05 – View Helper

Um Layout- & Viewscripte zu entschlacken und von Programmcode zu befreien (MVC-Prinzip), gibt es in Zend die Möglichkeit View-Helper einzusetzen. View Helper können auch dazu verwendet werden, um wiederkehrenden Code in seperaten Dateien abzulegen und somit doppelten Code zu vermeiden.

Ich erkläre das Prinzip beispielhaft für das Einbinden eines Copyrights incl. Jahreszahl (bspw.: © 2005 – 2011).
Weiterlesen →

XML definierte Zend_Forms – Validierung auf HTML Tags

Problem:
Eine über eine xml-Datei konfiguierte Zend_Form sollte validiert werden. Es sollte u.a. überprüft werden, ob HTML-Tags eingegeben wurden. Falls dies der Fall war, sollte das Formular nicht abgeschickt werden. Dazu wurde folgende Konfiguration (Auszug) verwendet:

<text type="textarea">
	<options required="1">
		<validators>
			<regex validator="Regex">
				<options>
					<pattern>(/[^<].*[>]/)</pattern>
				</options>
			</regex>
		</validators>
	</options>
</text>

Das Pattern ist in diesem Fall noch inkorrekt, da innerhalb von XML keine Zeichen wie „<" und "&" erlaubt sind. Der nächste Versuch war, die Zeichen mittels SQL Entities darzustellen.
Das Pattern sah dann wie folgt aus:

<pattern>(/[^&lt;].*[&gt;]/)</pattern>

Aber selbst dieser Ansatz brachte keine Lösung. Ein nächster Versuch war das einbetten des Codes in einen CDATA-Block.

<pattern><![CDATA["(/[^<].*[>]/)"]]></pattern>

Doch selbst dieser Ansatz lieferte weiterhin keine Lösung. Das Formular wurde nicht korrekt validiert.

Ein anderer Lösungsansatz brachte letztendlich den Erfolg: Das Schreiben einer eigenen Validatorklasse. In der XML-Konfiguration des Formulars muss nun nur noch folgender Aufruf stehen:

<text type="textarea">
	<options required="1">
		<validators>
			<regex validator="HtmlCheck" />
		</validators>
	</options>
</text>

Es wird nun der Validator HtmlCheck aufgerufen. Diesen müssen wir nun noch definieren. Wir legen dazu eine passende Validatorklasse an:

class Validate_HtmlCheck extends Zend_Validate_Abstract
{
	// [...]
	public function isValid($value)
	{
		//Prüfen, ob HTML Tags gesetzt wurden
		if($value!=strip_tags($value))
		{
			return false;
		}

		//Ansonsten true
		return true;
	}
}

Eventuell müsst ihr den Klassennamen entsprechend eurer eigenen Projektstruktur anpassen. Damit funktionierte das Validieren des Formulars auf HTML-Tags, wenn ihr euer Formular über XML definiert habt.

Vielleicht habt ihr ja noch eine elegantere Lösung?