Search code examples
phpmongoidmongodate

Unserialize PHP string with obsolete MongoId and MongoDate Objects


I have this string in database. I need to unserialize it with php. The problem is that it returns some "__PHP_Incomplete_Class_Name" Objects.

I know that this string was serialized with old MongoDB PHP extension and I try to unserialized with newer MongoDB extension.

So MongoId and MongoDate are obsolete.

This is the string:

$string = 'a:2:{i:0;a:3:{s:4:"name";s:52:"----------------------------------------------------";s:6:"amount";s:5:"53.09";s:10:"service_id";s:24:"------------------------";}i:1;a:6:{s:2:"id";C:7:"MongoId":24:{5b2276372a4ef288038b45ba}s:4:"name";s:21:"---------------------";s:4:"type";s:8:"one time";s:10:"service_id";s:20:"thisrhietingcfffffff";s:6:"amount";s:6:"139.29";s:10:"added_date";O:9:"MongoDate":2:{s:3:"sec";i:1528985143;s:4:"usec";i:917000;}}}';

When I do:

$result =  @unserialize($string);
var_dump($result);

The result is:

array(2) {
  [0]=>
  array(3) {
    ["name"]=>
    string(52) "----------------------------------------------------"
    ["amount"]=>
    string(5) "53.09"
    ["service_id"]=>
    string(24) "------------------------"
  }
  [1]=>
  array(6) {
    ["id"]=>
    object(__PHP_Incomplete_Class)#1 (1) {
      ["__PHP_Incomplete_Class_Name"]=>
      string(7) "MongoId"
    }
    ["name"]=>
    string(21) "---------------------"
    ["type"]=>
    string(8) "one time"
    ["service_id"]=>
    string(20) "thisrhietingcfffffff"
    ["amount"]=>
    string(6) "139.29"
    ["added_date"]=>
    object(__PHP_Incomplete_Class)#2 (3) {
      ["__PHP_Incomplete_Class_Name"]=>
      string(9) "MongoDate"
      ["sec"]=>
      int(1528985143)
      ["usec"]=>
      int(917000)
    }
  }
}

I have tried to class_alias MongoId to ObjectId. No working. I Have tried to create new class MongoId to extend ObjectId. I am not allowed because ObjectId is a final class.

I have tried to replace C:7:"MongoId" with C:8:"ObjectID".

Still same result: __PHP_Incomplete_Class_Name

Maybe a posibility is to return result like an array not an object?


Solution

  • Your approach points in the right direction for MongoDate, because it uses normal O-type serialization. For MongoId it is more difficult since it has custom C-type serialize handlers.

    If this was my task I would roughly start like this:

    • Declare a class MongoId and implement the Serializable interface. For the unserialize function try and mimic the original function (available here on L407->L220).

    • For the serialize function find out what ObjectId serialization looks like and mimic it. (Available here L187)

    • unserialize the string from the database, and serialize it again.

    • Replace C:7:"MongoId" with C:21:"MongoDb\BSON\ObjectID" in the re-serialized string. You need the namespace along with the class name.

    • unserialize again and pray.

    The MongoId class should look something like this; but the code is not tested at all:

    class MongoId implements Serializable {
      public $id;
      public function serialize() {
        return serialize(['oid' => $this->id]);
      }
      public function unserialize($str) {
        $this->id = $str;
      }
    }
    

    I hope this helps a little at least.