PHP PDO - cannot serialize or unserialize PDO instances
Asked Answered
P

2

7

I need to pass a PDO connection into a cart class from a controller,

function __construct($connection) 
{
    $this->cart = new cart($connection);
}

but I think the problem is with serialize()

public function render_page() 
{

    if (!isset($_SESSION[SESSION_CART]))
    {
       $cart =  $this->cart;
    }
    else 
    {
       $cart = unserialize($_SESSION[SESSION_CART]);
    }

    $_SESSION[SESSION_CART] = serialize($cart); 

 }

I get this error,

Fatal error: Uncaught exception 'PDOException' with message 'You cannot serialize or unserialize PDO instances' in C:\wamp\www\store_2012_MVC\local\controllers\class_base_extended_cart.php:89 Stack trace: #0 [internal function]: PDO->__sleep() #1 C:\wamp\www\store_2012_MVC\local\controllers\class_base_extended_cart.php(89): serialize(Object(cart)) #2 C:\wamp\www\store_2012_MVC\local\controllers\class_factory.php(75): base_extended_cart->render_page() #3 C:\wamp\www\store_2012_MVC\index.php(69): factory->render() #4 {main} thrown in C:\wamp\www\store_2012_MVC\local\controllers\class_base_extended_cart.php on line 89

How can I fix this?

Or can I use something else instead of serialize()?

EDIT:

I tried it with __sleep and __wakeup magic methods but still get the same error,

class database_pdo
{
    # database handler
    protected $connection = null;

    # make a connection
    public function __construct($dsn,$username,$password)
    {
        try 
        {

            $this->connection = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
            $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

        }
        catch (PDOException $e) 
        {
            # call the get_error function
            $this->get_error($e);
        }
    }

    # don't forget to add getter method to get $this->connection, it's just a good practice.
    public function get_connection()
    {
        return $this->connection;
    }

    public function __sleep()
    {
        return array('connection');
    }

    public function __wakeup()
    {
        $this->connection;
    }

}
Picrite answered 7/6, 2012 at 17:15 Comment(1)
Side note- if your class inherits from PDO and you clone the object you will also get this error. In my case I set $obj->pdo to null before cloning.Osburn
S
3

Take a look at the __sleep and __wakeup magic methods. http://us.php.net/manual/en/language.oop5.magic.php#object.sleep

They allow you to specify which properties get serialized and which get ignored. The issue there is that you'll need to regularly pass in an instance of your PDO object.

Scarface answered 7/6, 2012 at 17:23 Comment(2)
thanks for the answer. I have just tried them but still get the same error, could you please have a look at my edit above. thanks.Picrite
You have to reverse it. With __sleep, you return an array of properties you WANT to serialize. The point is to be able to exclude properties that are not serializable. eg: your connection property. The reason I said this might not be the best solution is because any time you access the cart from the $_SESSION global, you'd have to reset the connection property. something like... $cart = $_SESSION['cart']; $cart->set_connection($db)Scarface
U
4

PDO objects contain active links to databases (which may have a transaction initiated or db session settings and variabiles).

You cannot serialize a PDO object because the above would get lost and cannot be re-established automatically.

You should redesign your classes to access the current database link statically using a separate class (dedicated for holding db connections), instead of saving a reference in a member variable (I supose this is happening when you do new cart($connection))).

Usable answered 7/6, 2012 at 17:35 Comment(1)
Since ~ PHP 5.3.0 it seems __sleep and __wakeup have been marked as final for PDOStatement and PDO, so no more tricks possible :)Usable
S
3

Take a look at the __sleep and __wakeup magic methods. http://us.php.net/manual/en/language.oop5.magic.php#object.sleep

They allow you to specify which properties get serialized and which get ignored. The issue there is that you'll need to regularly pass in an instance of your PDO object.

Scarface answered 7/6, 2012 at 17:23 Comment(2)
thanks for the answer. I have just tried them but still get the same error, could you please have a look at my edit above. thanks.Picrite
You have to reverse it. With __sleep, you return an array of properties you WANT to serialize. The point is to be able to exclude properties that are not serializable. eg: your connection property. The reason I said this might not be the best solution is because any time you access the cart from the $_SESSION global, you'd have to reset the connection property. something like... $cart = $_SESSION['cart']; $cart->set_connection($db)Scarface

© 2022 - 2024 — McMap. All rights reserved.