Connection hashing fails with "Serialization of 'Closure' is not allowed"
Steveb-p opened this issue · 0 comments
In cases where a custom Platform is provided into Doctrine configuration, Connection hashing will fail due to an attempt to serialize a closure.
This happens because in such a case $params
argument contains Platform service instance, which in turn contains event listeners that may make use of Service Subscribers (as it is for me).
Normally, if platform option is not specified, it is created by Doctrine on it's own when it is first requested, which happens later than creation of the Connection object.
Exception stacktrace (application code omitted):
Exception : Serialization of 'Closure' is not allowed
/.../vendor/dama/doctrine-test-bundle/src/DAMA/DoctrineTestBundle/Doctrine/DBAL/AbstractStaticDriverV2.php:24
/.../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:411
/.../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1951
/.../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1289
/.../vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php:212
If the platform
is unset
before passing it to create hash, everything works normally.
public function connect(array $params, $username = null, $password = null, array $driverOptions = []): Connection
{
if (!self::$keepStaticConnections) {
return $this->underlyingDriver->connect($params, $username, $password, $driverOptions);
}
$serializationParams = $params;
unset($serializationParams['platform']);
$key = sha1(serialize($serializationParams).$username.$password);
if (!isset(self::$connections[$key])) {
self::$connections[$key] = $this->underlyingDriver->connect($params, $username, $password, $driverOptions);
self::$connections[$key]->beginTransaction();
}
return new StaticConnection(self::$connections[$key]);
}
Alternatively, using json_encode
in place of serialize
also does seem to work:
public function connect(array $params, $username = null, $password = null, array $driverOptions = []): Connection
{
if (!self::$keepStaticConnections) {
return $this->underlyingDriver->connect($params, $username, $password, $driverOptions);
}
$key = sha1(json_encode($params).$username.$password);
if (!isset(self::$connections[$key])) {
self::$connections[$key] = $this->underlyingDriver->connect($params, $username, $password, $driverOptions);
self::$connections[$key]->beginTransaction();
}
return new StaticConnection(self::$connections[$key]);
}
Although this makes it so Platform object is encoded as {}
, so Connections differing only by Platform class would share the same hash - but I don't think that is an issue.