PHP: Objekte rekursiv mit JsonSerializable als JSON ausgeben

Die Funktion json_encode() liefert bei Objekten nur den öffentlichen Teil der Eigenschaften zurück (das dann auch rekursiv). Wenn Eigenschaften in einem protected- oder private-Bereich stehen, dann werden diese Daten nicht zurückgeliefert.

Möchte man nun ein Objekt, dass aus verschiedenen Unterobjekten besteht ausgeben als JSON, dann versagt hier gewollt json_encode().

Umgehen kann man das Problem mit JsonSerializable. Das gewünschte Objekt muss JsonSerializable implementieren und eine öffentliche Methode jsonSerialize() haben.

In dieser Methode wird über ein return der Teil der Daten zurückgegeben, die json_encode verarbeiten soll:

class Demo implements JsonSerializable 
{
    public $id; // würde exportiert werden
    protected $record; // würde nicht exportiert werden
    private $mode; // würde ebenfalls nicht exportiert werden
    private $unwanted;

    public function jsonSerialize()
    {
        return [
            'id' => $this->id,
            'record' => $this->record,
            'mode' => $this->mode
        ];
    }

Statt einer einfachen Zuweisung der Eigenschaften auf der rechten Seite kann natürlich auch eine Methode des Objekt aufgerufen werden, die dann die gewünschten Daten zurückliefert (zB $this->getRecord()).

Wird jetzt das Objekt Demo mit json_encode() ausgegeben, dann würden im oberen Beispiel die Eigenschaften „id“, „record“ und „mode“ ausgegeben.

Hofmann-Menü Essensausgabe simpel

Hofmann Menü-Manufaktur hat zwar ein Online-Abrechnungssystem, doch dafür muss bezahlt werden. Wer die Abrechnung machen muss kann sich aber einfacher Bordmittel bedienen.

Benötigt werden ein (lokaler) Webserver mit MySql/MariaDb und Adminer. Des weiteren wird eine SQL-Datei für den Import benötigt. Die Import-Datei gibt es hier.

Zu jeder Essen gibt es eine zweiteilige Marke. Der obere Teil „Bestellung“ mit dem Loch wird abgegeben und der untere Teil „Abhol-Coupon“ verbleibt beim „Kunden“. Beispiel-Marke.

Vor der Inbetriebnahme müssen die „meals“- und die „users“-Tabelle im Adminer aktualisiert werden. Ein paar Menüs sind bereits in der SQL-Datei enthalten.

Nach der Essensausgabe werden die eingesammelten Bestellungen eingegeben (Tabelle meals_users). Adminer gibt bei jedem neuen Datensatz eine Meldung mit der neu angelegten ID aus.
Diese kann dann auf der Marke notiert werden (im Beispiel „100“). Die Marken werden zum Nachweis abgeheftet und dienen bei Nachfrage als Beweis/Beleg.

Der View „offene_posten“ listet alle offnen Bestellungen mit Namenskürzel, Summe und Zeitraum der Essensausgabe auf.

Lediglich das austragen/bezahlen muss derzeit noch manuell im SQL-Teil des Adminers erfolgen:

UPDATE meals_users SET payment_date = ‚yyymmdd‘ WHERE user_alias=’xy‘ AND payment_date IS NULL AND issue_date <= ‚yyymmdd‘;

preg_replace e-modifier warning in fpdf fixed

Ältere Versionen der fpdf-Library bekommen eine PHP-Warnung, wegen des e-modifiers in der preg_match Funktion. In der Datei fpdi_pdf_parser.php kommt diser Hinweis in der „function desescapeString($s)“ (etwa Zeile 257).

Natürlich macht es Sinn, die Library auf eine neuere Version zu updaten. Da sich aber in der Zwischenzeit einige Funktionalitäten geändert haben, wird das auch ein Anpassen des Quelltextes zur Folge haben. In der Zwischenzeit hält nachfolgender Fix die Logfiles sauber:

    function deescapeString($s) {
        /*
        $torepl = array("/\\\(\d{1,3})/e" => "chr(octdec(\\1))",
                        "/\\\\\(/" => "(",
                        "/\\\\\)/" => ")");
        return preg_replace(array_keys($torepl),$torepl,$s);
        */
        return preg_replace_callback_array(
            [
                "~\\\(\d{1,3})~" => function($match) {
                    return chr(octdec($match));
                },
                "~\\\\\(~" => function($match) {
                    return '(';
                },
                "~\\\\\)~" => function($match) {
                    return ')';
                }
            ], $s
        );
    }

Der auskommentierte Bereich war das Original (und kann gelöscht werden). Der Ersatz nutzt preg_replace_callback_array (PHP 7).

Postgresql: Datenbank mit aktiven Connections löschen

Ein „DROP DATABASE mydb“ wird nicht funktionieren, solange es aktive Verbindungen gibt (pgbouncer, phpmyadmin, etc.). Manchmal können nicht alle Verbindungen identifiziert und geschlossen werden.

Dann hilft folgende SQL-Zeile (mydb durch eigenen Datenbanknamen ersetzen):

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'mydb' AND pid <> pg_backend_pid();

Stackoverflow

Postgres: Zeilen einer Tabelle als Eingabe (INSERT) für ähnliche Tabelle verwenden (mit CTE)

Tabelle 1 (table1):
Hat die Spalten id, name, language, type

Tabelle 2 (table2):
Hat die Spalten id, name, language, type_id (identisch mit Tabelle 1 „type“)

Alle Zeilen mit dem Wert „fr“ als language sollen von der ersten Tabelle in die zweite Tabelle übernommen werden – mit einem SQL.

SET search_path TO 'public';

WITH 
    addressor_types as (SELECT type as type_id, name, language FROM table1 WHERE language='fr')

INSERT INTO table2 (type_id, name, language) (SELECT type_id, name, language FROM addressor_types);

SET search_path TO … = Setzen des Namensraumes, in dem Postgres sucht (kann weggelassen werden, wenn search_path=public)

WITH … = Common Table Expression (CTE), um die zutreffenden Zeilen der ersten Tabelle zwischenzuspeichern für den INSERT. Die Reihenfolge/Namen der Spalten beim INSERT muss/müssen übereinstimmen.

INSERT … = Der Befehl zum Einfügen der zuvor zwischengespeicherten Daten.