[message Uncaught PDOException: You cannot serialize or unserialize PDO instances

Ich bekomme folgende Fehlermeldung beim Einlösen eines Gutscheines:

[25 Jan 17:20:25.206823 2021] [uncaught error] [type E_ERROR] [file /app/vendor/oxid-esales/oxideshop-ce/source/Core/Session.php] [line 435] [code ] [message Uncaught PDOException: You cannot serialize or unserialize PDO instances in /app/vendor/oxid-esales/oxideshop-ce/source/Core/Session.php:435
Stack trace:
#0 [internal function]: PDO->__sleep()
#1 /app/vendor/oxid-esales/oxideshop-ce/source/Core/Session.php(435): session_write_close()
#2 /app/vendor/oxid-esales/oxideshop-ce/source/Application/Controller/OxidStartController.php(75): OxidEsales\EshopCommunity\Core\Session->freeze()
#3 /app/vendor/oxid-esales/oxideshop-ce/source/Core/Config.php(667): OxidEsales\EshopCommunity\Application\Controller\OxidStartController->pageClose()
#4 /app/vendor/oxid-esales/oxideshop-ce/source/Core/ShopControl.php(306): OxidEsales\EshopCommunity\Core\Config->pageClose()
#5 /app/vendor/oxid-esales/oxideshop-ce/source/Core/ShopControl.php(142): OxidEsales\EshopCommunity\Core\ShopControl->_process(‘OxidEsales\Esho…’, ‘addVoucher’, NULL, NULL)
#6 /app/vendor/oxid-esales/oxideshop-ce/source/Core/Oxid.php(27): OxidEsales\EshopCommunity\Core\ShopControl->start()
#7 /app/source/index.]

Ich habe das mal gesehen in OXID Bugtracker

https://bugs.oxid-esales.com/view.php?id=6792

Ist das mittlerweile behoben?

Welche Shop Version und welche PHP Version kommt zum Einsatz?

Oxid 6.2.2 (Enterprise) und PHP 7.1 (Wir migrieren demnächst nach PHP 7.4)

Ich werde es demnächst testen, da ich an der Stelle Gutscheine bald arbeite.

Was probiert werden könnte ob ab PHP Version 7.2 Fehlermeldung verschwindet, weil die interne PHP Funktion session_write_close() sich mit dieser Version der Rückgabewert geändert hat. Könnte sein, dass das OXID Framework bereits an den neuen Rückgabewert orientiert. Aber ein erster Blick in Code spricht dagegen.

Quelle: PHP: session_write_close - Manual

Sollte eigentlich nicht so sein, weil OXID 6.2.2 auf PHP 7.1 getestet wurde: OXID eShop version 6.2.2 • OXIDforge. Falls doch, ist es offenbar ein Bug.

Ich habe die Lösung von usenff wie im OXID Bugtracker beschrieben (0006792: [Enterprise Edition] exception - when adding a newly created model to session - OXID eShop bugtrack) ausprobiert und es hat funktioniert

in \app\vendor\oxid-esales\oxideshop-ee\Core\Element2ShopRelationsDbGateway.php

class Element2ShopRelationsDbGateway {

public function __sleep()
{
    $_oDb = null;
}

}

Dieser Fehler wird im Bugtracker als acknowledged markiert. Gibt es einen Grund, warum OXID diese Lösung nicht übernommen hat?

Der Bug wurde noch nicht bearbeitet. Cool, dass es bei Dir so funktioniert!

Aber wenn ich das richtig im Bug verstehe, wäre eigentlich nur die EE betroffen. Lese ich Deine Fehlermeldung, scheint es auch in der CE so zu sein, oder?

class Element2ShopRelationsDbGateway {

public function __sleep()
{
$_oDb = null;
}
}

Kann ich diese Lösung bedenkenlos übernehmen? Welche Auswirkungen könnte es auf andere Module haben, wenn ich $_oDb im Session-Objekt auf null setze?

Damit werden nur die Verbindungsdaten “rausgesiebt”, weil sie nicht serialisiert werden können. Dürfte auch mit

unset($_oDb);

gehen. Auswirkungen auf die Verarbeitung dürfte es IMHO nicht haben.

Ich habe eine zusätzliche Klasse in einem bestehenden Modul hinzugefügt, um OxidEsales\Eshop\Core\Element2ShopRelations zu überschreiben

source\modules-xxx\abc\Vouchers\Core\Element2ShopRelations.php

namespace Xxx\Abc\Vouchers\Core;

class Element2ShopRelations extends Element2ShopRelations_parent {

public function __sleep()
{
    $_oDb = null;
}

}

source\modules-xxx\abc\metadata.php

'extend'        => array(
    \OxidEsales\Eshop\Core\Element2ShopRelations::class  => \Xxx\Abc\Vouchers\Core\Element2ShopRelations::class
), 

Es funktioniert alles wie gewünscht (PDOException: You cannot serialize or unserialize PDO instances Meldung ist behoben)

Mir fällt auf, dass Element2ShopRelations den folgenden Hinweis hat:

/**

  • Class Article2ShopRelations
  • IMPORTANT:
  • This class has been generated by a script and is not meant to be edited.
  • Any changes will get lost during the next script run.
  • @package OxidEsales\Eshop\Core
    */

Kann mir jemand sagen ob ich richtig vorgegangen bin? Wie würdet ihr die Klasse Element2ShopRelations um die Methode _sleep() erweitern?

Ich würde es anders lösen, weil in Deiner überladenen Klasse Article2ShopRelations steht oben im Kopf ausdrücklich drin, dass die Klasse nicht überladen sollst!

/**
 * This class handles multi-shop item relations with shops.
 *
 * For example: article is available in one or few shops or sub shops.
 *
 * @internal Do not make a module extension for this class.
 * @see      http://wiki.oxidforge.org/Tutorials/Core_OXID_eShop_classes:_must_not_be_extended
 */
class Element2ShopRelations

In Deinem Eingangspost sieht man ja die Ablaufverfolgung knallen tut es bei $config->pageClose(); Aufruf in der ShopControll Klasse.

Landen tut man im OxidStartController Klasse bei der Methode pageClose() und von dort springt er in die Session Klasse Methode freeze().

Dort würde ich mir den Rückgabewert von session_write_close(); einmal mitloggen was dort zurück kommt.

Ich würde wahrscheinlich die freeze() Methode überladen und prüfen ob ich das Problem an dieser Stelle fixen kann.

Update:
Ein Gedanke aus PHP: session_write_close - Manual

Session-Daten werden normalerweise nach Beenden eines Scripts gespeichert, ohne dass session_write_close() aufgerufen werden muss, aber da Session-Daten gesperrt werden, um gleichzeitiges Schreiben zu verhindern, kann jeweils immer nur ein Script auf eine Session einwirken. Bei der Verwendung von Framesets zusammen mit Sessions werden Sie merken, dass wegen dieser Sperrung ein Frame nach dem anderen geladen wird. Sie können die Zeit zum Laden aller Frames reduzieren, indem Sie die Session beenden, sobald alle Änderungen an den Session-Variablen durchgeführt sind.

Vielleicht wird die Session einfach zulangsam geschlossen, dass dann anschließend und/oder vorab die Datenbank Verbindung knallt. Problem könnte sein, dass ja versucht wird die Warenkorb Session in der Datenbank vorab zu speichern bevor die Session beendet wird.

Die ursprüngliche Fehlermeldung ist: [[message Uncaught PDOException: You cannot serialize or unserialize PDO instances]

Aus meiner Sicht nur ein Folgefehler.

Update:
Was ich noch zusätzlich testen würde wie es sich mit der Performance Einstellung

Warenkörbe von angemeldeten Benutzern nicht speichern

verhält mit dieser Fehlermeldung.

Das hat leider nichts gebracht

Zurück zum Thema @internal, dieser Satz hat mich neugierig gemacht:

https://docs.oxid-esales.com/developer/en/6.1/modules/using_namespaces_in_modules.html

Immerhin weiß man dadurch nun, dass die gespeicherten Warenkörbe in der Datenbank nicht schuld sein können. Das es sich ausschließlich um den Warenkorb in der Session handelt.

Da steht nun im Raum warum man dafür eine Datenbank Objekt benötigt?

Wahrscheinlich die aufwendigste Prozessdur im Shop die Warenkorbberechnung betroffen die ja bei einem eingelösten Gutschein erneut durchgeführt werden muss. Wo im Hintergrund diverse Datenbankabfragen laufen.

Das Kernproblem könnte sein, dass das Basket Objekt als Referenz an die Session übergeben wird, besser wäre ab PHP 7 mit einem Clone damit man Konflikte vermeiden kann.

Ja dies gilt es zu Beginn immer zu prüfen.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.