0

I am asking question after applied SO Ans.

i am trying to Unserialize from a serialized string fetched from DB.

I am getting Error : Unserialize offset error

I have two case

Same Code in both case:

 $categories = preg_replace( '!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'",  $data['Member']['category'] );        
 var_dump($categories);  
 $cat_unserialize = unserialize($categories);
 var_dump($cat_unserialize );  

case 1 : when

$data['Member']['category'] => Adventure Camps

case 1 : Error:

string 'Adventure Camps' (length=15)

Notice (8): unserialize(): Error at offset 0 of 15 bytes

boolean false

case 2 : when

$data['Member']['category'] => a:4:{i:0;s:9:"Adventure";i:1;s:12:"Sports ";i:2;s:15:"Training";i:3;s:29:"Educational";}

case 2 : No Error Code id Working Fine

NikiC
  • 100,734
  • 37
  • 191
  • 225
Naresh
  • 2,761
  • 10
  • 45
  • 78
  • In case 1 you are trying to unserialize a string that isn't serialized - that being the issue? try '@unserialize' and compare it to 'false' to check if its serialized – mr12086 Oct 03 '14 at 16:35
  • Code is same in both condition . – Naresh Oct 03 '14 at 16:36
  • Maybe I didn't understand but it seems that you're trying to `unserialize` something that have not serialized before. `Adventure Camps` is not serialized. Maybe something went wrong with your preg_replace function regarding `case 1`? – Ofir Baruch Oct 03 '14 at 16:36
  • After reading your updated question's title -> you can't use `unserialize` on string which are not already `serialized`. You'll have to serialize all the values (even if there's only one value and not several) or you'll have to check it first. – Ofir Baruch Oct 03 '14 at 16:38
  • `Adventure Camps` is not a serialized string. it's JUST a string. if it was serialized, then it'd look more like `s:15:"Adventure Camps"` – Marc B Oct 03 '14 at 16:47

2 Answers2

1

Unserialize only works on a serialized string. You need to prevent the notice from printing when trying to unserialize a string that isn't a serialized array.

$cat_unserialize = @unserialize($categories);

Otherwise, I'm not sure why it would be a problem.
Then afterwards, before using the variable you can check if it's an array or string.

if(is_array($cat_unserialize)) {
    //do something with array.
}
else {
    //do something with string.
}

Also, I don't understand the preg_replace(). Why remove the elements that make the string serialized, and then try to unserialize it?

Evadecaptcha
  • 1,403
  • 11
  • 17
  • Using `@` is like knowing that there's a problem with the code but instead of solving it, just not giving a *** – Ofir Baruch Oct 03 '14 at 16:40
  • There isn't a problem. Unless the information is being stored incorrectly. There is nothing being done wrong on the retrieval side. – Evadecaptcha Oct 03 '14 at 16:41
  • 1
    With that being said, you can expand your answer using: http://stackoverflow.com/questions/1369936/check-to-see-if-a-string-is-serialized – Ofir Baruch Oct 03 '14 at 16:42
  • Yeah that answer looks a lot better. But I really just don't understand the issue here, or why he's doing it this way. Like running the preg_replace() on it seems weird to me, so maybe I just misunderstood at first. – Evadecaptcha Oct 03 '14 at 16:44
0

If you want the long option : this is from wordpress

<?php
function is_serialized( $data ) {
    // if it isn't a string, it isn't serialized
    if ( !is_string( $data ) )
        return false;
    $data = trim( $data );
    if ( 'N;' == $data )
        return true;
    if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
        return false;
    switch ( $badions[1] ) {
        case 'a' :
        case 'O' :
        case 's' :
            if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
                return true;
            break;
        case 'b' :
        case 'i' :
        case 'd' :
            if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;\$/", $data ) )
                return true;
            break;
    }
    return false;
}

Check to see if a string is serialized?

Community
  • 1
  • 1
mr12086
  • 1,137
  • 13
  • 29