[PHP] Hex-Unicode in PHP-String konvertieren

Hier ist mein Lösungsvorschlag, um Hex-Unicode (bswp. \u00F6) in lesbaren Text (hier: ö) zu konvertieren:

/**
 * Convert hex-unicode to text
 * Bsp.: \u00F6 => ö
 * @param string|array $string
 * @return string|array
 */
function fixHexUnicode($string)
{
    $json = json_encode($string);
    $json = str_replace('\\\\u',  '\\u', $json);
    $string  = json_decode($json);

    return $string;
}

PHP Errors und Zend_Log incl. Mail verheiraten

Über die Bootstrap hab ich mir meinen Logger konfiguriert und in die Registry abgelegt. Ungefähr so:

public function _initLogger()
{        
    $configIni = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', $this->getEnvironment());

    // Konsolenlog initialisieren
    $writerStream = new Zend_Log_Writer_Stream('php://output');
    $writerStream->addFilter((int) $configIni->log->console->level);

    // Mail-Logging initialisieren
    $configMail = array(
        'auth'      => 'login',
        'username'  => $configIni->mail->smtp->user,
        'password'  => $configIni->mail->smtp->pass,
        'ssl'       => 'tls',
        'port'      => $configIni->mail->smtp->port
    );

    $smtp = new Zend_Mail_Transport_Smtp($configIni->mail->smtp->host, $configMail);
    $mail = new Zend_Mail('utf-8');
    $mail->setFrom($configIni->log->mail->from)
         ->addTo($configIni->log->mail->to)
         ->addCc($configIni->log->mail->cc)
         ->setSubject('Fehlermeldungen:')
         ->setDefaultTransport($smtp);

    $writerMail = new Zend_Log_Writer_Mail($mail);
    $writerMail->addFilter((int) $configIni->log->mail->level);

    // Writer zum Logger hinzufügen
    $logger = new Zend_Log();
    $logger->addWriter($writerStream);
    $logger->addWriter($writerMail);
    Zend_Registry::set('logger', $logger);
}

Das entsprechende PHP Script required die index.php und bootstrapped so das Zend Framework. Das Script soll im Fehler bzw. Abbruchfall einen Fehler in den Logger schreiben und ebenfalls die Logger-Mail versenden.

require_once __DIR__ . '/index.php';
declare(ticks=1);

function shutdown()
{
    if ($error = error_get_last()) {
        if (isset($error['type']) && ($error['type'] == E_ERROR ||
                $error['type'] == E_PARSE ||
                $error['type'] == E_COMPILE_ERROR)
        ) {
            ob_end_clean();

            $message = 'Es ist ein Fehler aufgetreten: ' . "\n"
                . 'Message: ' . $error['message'] . "\n"
                . 'File: ' . $error['file'] . "\n"
                . 'Line: ' . $error['line'];
            /* @var $logger Zend_Log */
            $logger = Zend_Registry::get('logger');
            $logger->log($message, Zend_Log::CRIT);
            $logger->__destruct();
        }
    }
}

//// signal handler function
function sig_handler($signo)
{
    switch ($signo) {
        case SIGTERM:
        case SIGINT:
        case SIGHUP:
        case SIGUSR1:
            $message = 'Es ist ein Fehler aufgetreten';
            /* @var $logger Zend_Log */
            $logger = Zend_Registry::get('logger');
            $logger->log($message, Zend_Log::CRIT);
            $logger->__destruct();
            exit;
        default:
            // handle all other signals
    }
}

register_shutdown_function('shutdown');

Hervorzuheben und wichtig sind hier die Zeilen declare(ticks=1); sowie $logger->__destruct();. Mit dem Destruktor vom Logger initialisiert ihr das Versenden der Mail, da das Script selber nicht korrekt beendet wurde und die destruct-Funktion vom Logger somit auch nicht aufgerufen wurde.

[PHP] preg_match bei großen Inhalten

Wenn man einen preg_match Befehl auf einen langen String durchführen will, kann es passieren, dass man trotz korrektem regulärem Ausdruck kein Ergebnis oder nur eine Fehlermeldung zurück bekommt.

Falls dies der Fall sein sollte, kann man folgender Befehl evtl. Abhilfe schaffen:

ini_set('pcre.backtrack_limit', 1000000);

Falls eure PHP Version > 5.3.7 sein sollte, so ist euer PCRE Backtracking Limit ebenfalls auf 1000000 eingestellt. Bei älteren PHP Versionen kann dieses Codesnippet allerdings Wunder bewirken.

PHP – Datumsdifferenz sicher ermitteln

Um in PHP die Differenz zwischen zwei Datumsangaben zu ermitteln, gibt es folgende Möglichkeit:

$date1 = '2013-03-01'
$date2 = '2013-05-17'

$dateDiff = gregoriantojd(
                date('m', strtotime($date2)),
                date('d', strtotime($date2)),
                date('Y', strtotime($date2)))
            - gregoriantojd(
                date('m', strtotime($date1)),
                date('d', strtotime($date1)),
                date('Y', strtotime($date1)));

Es erfolgt erst die Umrechnung in das vom gregorianische ins julianische Datumsformat. Danach kann man durch eine einfache Rechenoperation die Differenz zwischen beiden Datumsangaben ermitteln und erhält den Abstand zwischen Datum 1 und Datum 2 in Tagen.

Zend_Form + Autocomplete

Da ich im Netz kein zufriedenstellendes Beispiel für Zend_Form in Verbindung mit Autocomplete finden konnte, möchte ich hier meinen Lösungsansatz zeigen. Vorraussetzungen sind hierfür ein Zend_Form, sowie aktiviertes jQuery + jQueryUI.

Im Formular passiert erstmal nix Besonderes. Es wird ein normales Zend_Form_Element_Text angelegt.

$autoCompleteElement = new Zend_Form_Element_Text('autoCompleteElement');

Der Controller bekommt eine zusätzliche autocompleteAction spendiert, welche wir dann später über jQuery ansprechen wollen, um die Werte zur aktuellen Eingabe zu erhalten. Wichtig ist hier, die Werte JSON-kodiert zu übergeben, um sie später im Javascript-File sauber auslesen zu können. Bei meinem $returnArray soll der Value später ins Formularfeld eingetragen werden, wohingegen das Label als Anzeige für die Auswahl beim Autocomplete gedacht ist.

public function autocompleteAction()
{
    $post = $this->_request->getPost();
    $searchString = $post['searchString'];
    
    // $returnArray zur Demonstration meiner übergebenen Daten
    $returnArray[$row['value']] = $row['label']; 
    $valuesJson = Zend_Json::encode($returnArray);
    echo $valuesJson;
    $this->view->layout()->disableLayout();
    $this->_helper->viewRenderer->setNoRender(true);
}

Das Javascript kümmert sich schlussendlich um das Absenden des Requests und das Mappen der empfangenen Daten.

$(document).ready(function() {
    $("input#autoCompleteElement").autocomplete({
        source : function( request, response) {
            url = "/meinModul/meinController/autocompleteAction";
            data = { 'searchString' : request.term };
            $.post(url, data, function(JSON){
                response($.map(JSON, function (item, value) {
                    return {
                        label: item,
                        value: value,
                        source: item};
                    }));
            }, 'json');
        },
        minLength: 1,
        autoFocus: true
    });
});

Zum Schluss natürlich nicht vergessen das Javascript in euer View-Script mit einzubinden.

PHP – Datum berechnen

Mit PHP das Datum von gestern ermitteln:

$date = date('Y-m-d', time() - 86400);

Die aktuelle Zeit nehmen, davon 86400sec abziehen (entspricht 24h) und dann in das gewünschte Datumsformat casten.

Update: Besser geht das Ganze allerdings über folgendes Codesnippet:

$date = '2012-05-11';
date('Y-m-d', strtotime('-1 days', strtotime($date)));

Update 2:
Wenn ihr auf einen Wochentag bspw. 3 Werktage addieren wollt, funktioniert das analog zur oben beschriebenen Funktion:

$date = '2013-09-05';
date('Y-m-d', strtotime('+3 weekdays', strtotime($date)));

Weitere Funktionalitäten zu strtotime() findet ihr hier:
http://www.php.net/manual/de/datetime.formats.relative.php

PHP Datumsumwandlung von 05.04.12 in 2012-04-05

Beim Konvertieren von Datumsangaben in PHP kann es, vorrausgesetzt man macht es nicht wohlüberlegt, schon einmal zu der einen oder anderen Überraschung kommen.

Möchte man beispielsweise das Datum 05.04.12 einfach per

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

konvertieren, dann bekommt man häufig das aktuelle Datum ausgegeben. Warum ist das so? Meiner Meinung nach, liegt das daran, dass PHP das Datum nicht korrekt in einen Timestamp auflösen kann. Es kann also nicht automatisch ermittelt werden, was hier Tag, Monat und Jahr sein soll. Bei einem Datum 05.04.2012 ist das allerdings kein Problem. Da kann strtotime() den korrekten Timestamp problemlos extrahieren.

Wie sieht ein möglicher Lösungsansatz aus?

$dateTemp = explode('.', '05.04.12');
$date = date('Y-m-d', mktime(0, 0, 0, $dateTemp[1], $dateTemp[0], $dateTemp[2]));

Somit erhält man das gewünschte Datum. Wichtig kann das werden wenn man nicht nur ein statisches Datum, wie in diesem Fall hat, sondern die Datumsangabe bspw. per Variable übergeben wird.