Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use PDO::FETCH_SERIALIZE correctly?

Tags:

php

pdo

I've tried to implement code that uses PDO::FETCH_SERIALIZE to automatically unserialize php object from database.

I've checked the documentation and the corresponding php test which looks basically the same to what I have:

class foo implements Serializable {
    private $data;
    public function __construct() {
        $this->data = "My private data";
    }
    public function serialize() {
        return serialize($this->data);
    }
    public function unserialize($data) {
        $this->data = unserialize($data);
    }
    public function getData() {
        return $this->data;
    }
}
$foo = new foo;

$stmt = $pdo->prepare('SELECT \'C:3:"foo":23:{s:15:"My private data";}\' foo');
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE, 'foo');
$data = $stmt->fetch();
var_dump($data);

But it still unserializes it into something not what one expects. The result of running of this code is

object(foo)#4 (1) {
  ["data":"foo":private]=>
  object(foo)#5 (1) {
    ["data":"foo":private]=>
    string(15) "My private data"
  }
}

whereas one wouldn't expect an object to be nested. As it should be

object(foo)#2 (1) {
  ["data":"foo":private]=>
  string(15) "My private data"
}

instead.

What am I missing?

UPD 1:

I just tried using a real table instead of hardcoded data. It changed nothing. The current code is crafted especially so that everyone could run it without creating test database/tables to check it.

UPD 2:

Alias name changes nothing and effectively may be completely omitted.

UPD 3:

I have created a bug https://bugs.php.net/bug.php?id=68802, let's see if php dev team accepts it.

like image 423
zerkms Avatar asked Jan 25 '26 00:01

zerkms


1 Answers

You are serializing entire object in your hand crafted query.

$stmt = $pdo->prepare('SELECT \'C:3:"foo":23:{s:15:"My private data";}\' foo');

Should be:

$stmt = $pdo->prepare('SELECT \'s:15:"My private data";\' foo');

Simply because foo::serialize returns s:15:"My private data"; and not entire serialized object, later on, same serialized string gets injected into foo::unserialize, thus in your case, $data instanceof foo instead of string.

Output as you've expected:

object(foo)#4 (1) {
  ["data":"foo":private]=>
  string(15) "My private data"
}
like image 111
Dejan Marjanović Avatar answered Jan 26 '26 14:01

Dejan Marjanović