4

I have a class with typo that is stored in MemCached. Here is example:

class Person { public $n1ame; } echo serialize(new Person()); 

I fix typo in next code version:

class Person { public $name; } var_dump(unserialize($previousSerializedPersion)); 

But here is what happens: PHP implicitly added unexisting field to my object:

object(Person)#1 (2) { ["name"]=> NULL ["n1ame"]=> NULL } 

My person got additional field with data. What I expect is an exception.

Is there any way to achieve that?

5
  • Where do you get $previousSerializedPersion and Does that already contain the old n1ame property Commented Aug 3, 2018 at 9:35
  • In this example I get $previousSerializedPersion from serialize(new Person()) of previous execution with Person::$n1ame.Let's say I store it in Memcache and then receive it :) Commented Aug 3, 2018 at 10:52
  • 3
    Then the old incorrect version os in the cache. Clear that cache and then start again Commented Aug 3, 2018 at 11:25
  • 1
    "What I expect is an exception" Then use a statically typed language, not a dynamically typed one. While in your circumstances, throwing an exception might be a desirable outcome, dealing with a large dataset while updating the code which sits on top of it is an awful lot easier when PHP does not throw an exception at deserialization in such an instance. Commented Aug 3, 2018 at 11:53
  • 1
    Whilst my answer is for "correcting" the problem, you could use __wakeup() to throw an exception if that's what you really need. Commented Aug 3, 2018 at 12:18

1 Answer 1

6

Three Suggestions:

1.) Perform manual string translations on your serialized data string to correct it before you call unserialize().

O:6:"Person":1:{s:5:"n1ame";N;} 

the s:5 is the character length of the property n1ame in the original serialization, you will need to change it to s:4 to restore it back to name, The s is for string data type, the number is the length of the text value, in this case the property key.

O:6:"Person":1:{s:4:"name";N;} 

you could try

unserialize( str_replace( 's:5:"n1ame"', 's:4:"name"', $previousSerializedPersion ) ); 

2.) Another solution is a __wakup() function to correct your data. This function is run on your object after serialization but before it is assigned and used, This might be a "better" solution as its layed cleanly out in code.

class Person { public $name; public function __wakeup() { if( property_exists( $this, 'n1ame' ) ) { $this->name = $this->n1ame; unset( $this->n1ame ); } } } unserialize('O:6:"Person":1:{s:5:"n1ame";s:4:"mark";}'); 

3.) Using the same __wakup() concept but throwing an Exception.

class Person { public $name; public function __wakeup() { if( property_exists( $this, 'n1ame' ) ) { throw new Exception('oh no this data is bad'); } } } unserialize('O:6:"Person":1:{s:5:"n1ame";s:4:"mark";}'); 

https://3v4l.org/h8pss

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for such a detailed answer :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.