Variable handling 函数
在线手册:中文 英文
PHP手册

serialize

(PHP 4, PHP 5)

serialize 产生一个可存储的值的表示

描述

string serialize ( mixed $value )

serialize() 返回字符串,此字符串包含了表示 value 的字节流,可以存储于任何地方。

这有利于存储或传递 PHP 的值,同时不丢失其类型和结构。

想要将已序列化的字符串变回 PHP 的值,可使用 unserialize()serialize() 可处理除了 resource 之外的任何类型。甚至可以 serialize() 那些包含了指向其自身引用的数组。你正 serialize() 的数组/对象中的引用也将被存储。

当序列化对象时,PHP 将试图在序列动作之前调用该对象的成员函数 __sleep()。这样就允许对象在被序列化之前做任何清除操作。类似的,当使用 unserialize() 恢复对象时, 将调用 __wakeup() 成员函数。

Note:

在 PHP 3 中,对象属性将被序列化,但是方法则会丢失。PHP 4 打破了此限制,可以同时存储属性和方法。请参见类与对象中的序列化对象部分获取更多信息。

Example #1 serialize() 示例

<?php
// $session_data 是包含了当前用户 session 信息的多维数组。
// 我们使用 serialize() 在请求结束之前将其存储到数据库中。

$conn odbc_connect ("webdb""php""chicken");
$stmt odbc_prepare ($conn,
      
"UPDATE sessions SET data = ? WHERE id = ?");
$sqldata = array (serialize($session_data), $PHP_AUTH_USER);
if (!
odbc_execute ($stmt, &$sqldata)) {
    
$stmt odbc_prepare($conn,
     
"INSERT INTO sessions (id, data) VALUES(?, ?)");
    if (!
odbc_execute($stmt, &$sqldata)) {
    
/* 出错 */
    
}
}
?>

参见:unserialize()


Variable handling 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: 产生一个可存储的值的表示

用户评论:

Anonymous (29-Feb-2012 03:44)

Please! please! please! DO NOT serialize data and place it into your database. Serialize can be used that way, but that's missing the point of a relational database and the datatypes inherent in your database engine. Doing this makes data in your database non-portable, difficult to read, and can complicate queries. If you want your application to be portable to other languages, like let's say you find that you want to use Java for some portion of your app that it makes sense to use Java in, serialization will become a pain in the buttocks. You should always be able to query and modify data in the database without using a third party intermediary tool to manipulate data to be inserted.

I've encountered this too many times in my career, it makes for difficult to maintain code, code with portability issues, and data that is it more difficult to migrate to other RDMS systems, new schema, etc. It also has the added disadvantage of making it messy to search your database based on one of the fields that you've serialized.

That's not to say serialize() is useless. It's not... A good place to use it may be a cache file that contains the result of a data intensive operation, for instance. There are tons of others... Just don't abuse serialize because the next guy who comes along will have a maintenance or migration nightmare.

tickthokk at gmail dot com (02-May-2011 07:39)

On the topic of serialization, the comments seemed split on which was faster: serialize() or json_encode().

I used an array with a serialized strlen() of 1604.

At 5,000 itterations, serialize won over (by .0001 seconds).  At 50,000 itterations, serialize still won.  I then tested it with the suggested gzcompress() and base64_encode() combo.  Both times json_encode won; first by .25 seconds, and second (at 50k) 2.85 seconds.

However, that's only half the battle.  Please take into consideration the difference between unserialize() and json_decode().  In every instance, unserialize() was always faster.  In the 5k test, it was faster by .22 seconds (.13 with compression).  In the 50k test, it was faster by 2.4 seconds (1.8 with compression).

Even if serialize() has it's downfalls, unserialize() balances that out.

jmanuel at ciges dot net (29-Apr-2011 04:03)

Hello,

I wanted to serialize a complex array (an array of arrays with a few levels, it's a configuration file) and I think I have found a bug in the 'serialize' function. I work with PHP 5.2.5 (from SLES 10).

I had as result always the string "N;". This value corresponds to NULL value.

So I did my own 'serialize' function. Here it is in case you had the same problem.

<?php
   
# Function which returns serialization string for a scalar value
   
private function ser_value($value)    {
        if (
is_null($value))    {  return "N";  }
        elseif (
is_bool($value))    {  return $value ? "b:0":"b:1";  }
        elseif (
is_integer($value))    {  return "i:".$value;  }
        else    {  return
"s:".strlen($value).":\"".$value."\"";  }
        }

   
# Recursive function which returns serialization string for an array
   
function serialize_data($array)    {
       
$n = count($array);
       
$result = "a:".$n.":{";
       
$i = 1;
        foreach (
$array as $key => $value)    {
           
$result .= ser_value($key).";";
           
$result .= (is_array($value)) ? serialize_data($value) : ser_value($value).";";
            }
       
$result .= "}";

        return
$result;
        }
?>

Greetings from Spain

José M. Ciges

kevin at tra dot as (13-Apr-2011 08:45)

In addition to base64_encode(), save space in the DB by compressing the serialized object.  As follows:

<?php
mySerialize
( $obj ) {
   return
base64_encode(gzcompress(serialize($obj)));
}

myUnserialize( $txt ) {
   return
unserialize(gzuncompress(base64_decode($txt)));
}
?>

pgl at yoyo dot org (03-Feb-2011 05:13)

Another suggestion for coping with binary data in serialize()d variables is just to base64_encode() those fields before serializing. It will increase the size of the variable, but not by too much.

reiners dot joh at googlemail dot com (18-Jan-2011 07:02)

I just realized a certain behaviour when I serialize objects, store them in $_SESSION and unserialize them after a reload.
More precisely, static fields of the object will be available when serializing/unserializing but NOT when you do a page reload.

This is because the static fields are on class level, and certainly, the classes will be completly initialized again when you do a page reload.
Actually that behaviour is correct, but i spent long long time to debug a script before i actually realized this.

<?php
session_start
();
echo
"<pre>Press F5

"
;
class
MyClass {
   
//static variable
   
static private $foo_static;
   
//normal variable
   
private $foo = null;

    static function
getString_static() {
        return
self::$foo_static;
    }

    static function
setString_static($str) {
       
self::$foo_static = $str;
    }

    function
setString($str) {
       
$this->foo = $str;
    }

    function
getString() {
        return
$this->foo;
    }

}
if (!isset(
$_SESSION['myObj'])) {
   
$myObj = new MyClass();
   
$myObj->setString_static("Will NOT be stored!!!");
   
$myObj->setString("Will be stored");

    echo
"Print content: \n";
    echo
'Normal Var: ' . $myObj->getString() . "\n";
    echo
'Static Var: ' . $myObj->getString_static();

    echo
"\t\n\nNow serialize and unserialize object\n";
   
$myObj = unserialize(serialize($myObj));

    echo
"And print again..\n";
    echo
'Normal Var: ' . $myObj->getString() . "\n";
    echo
'Static Var: ' . $myObj->getString_static();

   
//Store object in session
   
$_SESSION['myObj'] = serialize($myObj);

} else {
   
//if myobj was stored
   
$myObj_loaded = unserialize($_SESSION['myObj']);

    echo
"Print content when serialized, stored in session and unserialized after a relaod:\n";
    echo
'Normal Var: ' . $myObj_loaded->getString() . "\n";
    echo
'Static Var: ' . $myObj_loaded->getString_static();

    unset(
$_SESSION['myObj']);
}

?>
</pre>

jcastromail at yahoo dot es (26-Oct-2010 01:05)

i did a benchmark between serialization and json_serialize and i found that serialize is 12% fast than json_encode (no tag, php 5.2.12).

I used this array as a example of serialization (10'000 iterations)
<?php
$arr
=array(
  
"in"=>array("in1"=>"valin1","in2"=>506,"in33"=>"valin3")
   ,
"out"=>array("in1"=>"valin1","in2"=>"valin2"));
?>
and unserialize is 70% fast than json_decode.

in conclusion:
a) as expected, serialize is the fast way to.. ahem, serialize objects and array (at least for some complex cases).
b) but json produce a smaller string (and is more standard).

Anonymous (17-Oct-2010 07:03)

if you just want a way to store array as string, you should use "json_encode" and "json_decode" because:

1. json_encode + json_decode is much faster than serialize + unserialize

2. json format is readable

3. json format is smaller than serialized result

regality at gmail dot com (27-May-2010 11:30)

serialize can be a handy tool for protecting against page expirations if you are using POST's.

In my code I call the following function whenever I detect that the page has expired.

<?php
function savePost() {
   
// Save this in the login form
   
if (isset($_POST['savePost'])) {
        echo
"<input type='hidden' name='savePost' value=\"{$_POST[savePost]}\">";
    } else {
       
$savePost = htmlspecialchars(serialize($_POST));
        echo
"<input type='hidden' name='savePost' value=\"$savePost\">";
    }
}
?>

and when I load each page I call the function:

<?php
function restorePost() {
    if (isset(
$_POST[savePost])) {
       
$_POST = unserialize(stripslashes(htmlspecialchars_decode($_POST[savePost])));
    }
}
?>

That way if a user takes a long time doing something, they can re-authenticate and have their work restored.

travis at travishegner dot com (02-Mar-2010 08:37)

If serializing objects to be stored into a postgresql database, the 'null byte' injected for private and protected members throws a wrench into the system. Even pg_escape_bytea() on the value, and storing the value as a binary type fails under certain circumstances.

For a dirty work around:
<?php

$serialized_object
= serialize($my_object);
$safe_object = str_replace("\0", "~~NULL_BYTE~~", $serialized_object);

?>

this allows you to store the object in a readable text format as well. When reading the data back:

<?php

$serialized_object
= str_replace("~~NULL_BYTE~~", "\0", $safe_object);
$my_object = unserialize($serialized_object);

?>

The only gotcha's with this method is if your object member names or values may somehow contain the odd "~~NULL_BYTE~~" string. If that is the case, then str_replace() to a string that you are guaranteed not to have any where else in the string that serialize() returns.
Also remember to define the class before calling unserialize().

If you are storing session data into a postgresql database, then this workaround is an absolute must, because the $data passed to the session's write function is already serialized.

Thanks,
Travis Hegner

darlan at rdacom.com.br (09-Feb-2010 06:54)

I've made a simple code to serialize small arrays.. may be useful if someone needs to read the data in JS or store the array in database in a simple format. base64_encode/decode functions in JS can be found over the web...

<?php
function array2str($array,$level=1) {
 
$str = array();
  foreach(
$array as $key=>$value) {
   
$nkey = base64_encode($key);
   
$nvalue = is_array($value)?'$'.base64_encode(array2str($value)) : (string)base64_encode($value);
   
$str[] = $nkey.'&'.$nvalue;
   
//printf("Encoded %s,%s to %s,%s\n",$key,$value,$nkey,$nvalue);
 
}
  return
implode('|',$str);
}
function
str2array($str) {
 
$rest = array();
  if(
strpos($str,'|')>0) {
   
$array = explode('|',$str);
  } else
$array=array($str);
 
  foreach(
$array as $token) {
    list(
$key,$value) = explode('&',$token);
   
$nkey=base64_decode($key);   
   
$nvalue = (    substr($value,0,1) != '$' ? base64_decode($value) : str2array(base64_decode(substr($value,1))) );
   
$rest[$nkey] = $nvalue;
   
//printf("Decoded %s,%s to %s,%s\n",$key,$value,$nkey,$nvalue);
 
}
  return
$rest;
}
?>

[]'s

Anonymous (21-Jan-2010 05:23)

you should really use mysql_real_escape_string() for escaping (serialized) strings that got thrown into a query (visit php.net/mysql_real_escape_string for further information)

Alastair Lynn (16-Sep-2009 09:46)

This may be obvious, but for the record: as of the time of writing (PHP 5.3.0) you can't serialise a Closure object.

donotmail at me dot com (02-Sep-2009 07:16)

NOTE: php's serialize does not properly serialize arrays with which a slice of the array is a reference to the array itself, observe:

<?php
$a
= array();
$a[0] = "blah";
$a[1] =& $a;

$a[1][0] = "pleh"; // $a[0] === "pleh"

$b = unserialize(serialize($a));

// $b[0] == "pleh", $b[1][0] == "pleh"

$b[1][0] = "blah";
?>

now $b[1][0] == "blah", but $b[0] == "pleh"
after serializing and unserializing, slice 1 is no longer a reference to the array itself... I have found no way around this problem... even manually modifying the serialized string from
'a:2:{i:0;s:4:"pleh";i:1;a:2:{i:0;s:4:"pleh";i:1;R:3;}}'
to
'a:2:{i:0;s:4:"pleh";i:1;R:1;}'

to force the second slice to be a reference to the first element of the serialization (the array itself), it seemed to work at first glance, but then unreferences it when you alter it again, observe:

<?php
    $testser
= 'a:2:{i:0;s:4:"pleh";i:1;R:1;}';

   
$tmp = unserialize($testser);

   
print_r($tmp);

    print
"\n-----------------------\n";

   
$tmp[1][0] = "blah";

   
print_r($tmp);
 
?>

outputs:
Array
(
    [0] => pleh
    [1] => Array
 *RECURSION*
)

-----------------------
Array
(
    [0] => pleh
    [1] => Array
        (
            [0] => blah
            [1] => Array
                (
                    [0] => pleh
                    [1] => Array
 *RECURSION*
                )

        )

)

Alessandro Segala (17-Jul-2009 04:18)

I needed to serialize an array to store it inside a database.
I was looking for a fast, simple way to do serialization, and I came out with 2 options: serialize() or json_encode().

I ran some benchmarks to see which is the faster, and, surprisingly, I found that serialize() is always between 46% and 96% SLOWER than json_encode().
So, if you don't need to serialize objects and have the json extension available, consider using it instead of serialize().

NWdev (09-Jun-2009 03:27)

If you're serializing a small array of values and sending them from page to page for display/navigation purposes (versus storing them as session values) via $_GET, save yourself some time and ensure your php.ini magic_quotes_gpc values are set the same on your hosting and localhost severs.

In my case I had magic_quotes_gpc OFF locally, and it took a while to see why the values weren't unserializing properly (actually at all -- unserialize produced FALSE) on the action page (form action page) of the hosted version. A quick look at phpinfo() showed a difference -- Thanks to others mentioning use of magic_quotes when saving to mysql triggered a thot that this mismatch might cause the problem.

Chieftl (chieftl at ua dot fm) (27-Sep-2008 10:32)

I think serialized data must be compact. But serialize() function saves float values in bulky format. It possible to squeeze float values, using preg_replace():
<?php
$val
= 3.14159;
var_dump($val);  // initial value: float(3.14159)
$val = serialize($val);
var_dump($val);  // standart float format: string(55) "d:3.14158999999999988261834005243144929409027099609375;"
$val = preg_replace('/d:([0-9]+(\.[0-9]+)?([Ee][+-]?[0-9]+)?);/e', "'d:'.((float)$1).';'", $val);
var_dump($val);  // compact float format: string(10) "d:3.14159;"
$val = unserialize($val);
var_dump($val);  // unserialization successed: float(3.14159)
?>
In result becomes slowly serilization, but faster unserialization and less disk space.

WARNING! Some values can be rounded off
<?php
$val
= 1/3;
var_dump($val);  // initial value: float(0.333333333333)
$val = serialize($val);
var_dump($val);  // standart float format: string(55) "d:0.333333333333333303727386009995825588703155517578125;"
$val = preg_replace('/d:([0-9]+(\.[0-9]+)?([Ee][+-]?[0-9]+)?);/e', "'d:'.((float)$1).';'", $val);
var_dump($val);  // compact float format: string(10) "d:0.333333333333;"
$val = unserialize($val);
var_dump($val);  // unserialization successed: float(0.333333333333)
$val = serialize($val);
var_dump($val);  // but value is rounded off!: string(55) "d:0.3333333333330000147753935380023904144763946533203125;"
?>

WARNING! Do not use for recursive serializations (serialize(serialize(...)))!

Sorry for my poor English.

Aditya P Bhatt (adityabhai at gmail dot com) (31-Mar-2008 11:29)

Here is a simple code to understand serialize function:

<?php
class dog {

    var
$name;
    var
$age;
    var
$owner;

    function
dog($in_name="unnamed",$in_age="0",$in_owner="unknown") {
       
$this->name = $in_name;
       
$this->age = $in_age;
       
$this->owner = $in_owner;
    }

    function
getage() {
        return (
$this->age * 365);
    }
   
    function
getowner() {
        return (
$this->owner);
    }
   
    function
getname() {
        return (
$this->name);
    }
}
?>

<body bgcolor=white>
<h1>Beware the dog</h1>
<?php
$ourfirstdog
= new dog("Rover",12,"Lisa and Graham");
$dogdisc = serialize($ourfirstdog);
 
$pet = unserialize($dogdisc);
$old = $pet->getage();
$name = $pet->getname();
print
"Our first dog is called $name and is $old days old<br>";
print
$dogdisc;
?>

Marek Soldt (21-Nov-2007 05:50)

serialize() and unserialize() behave a bit crazy if you try to work with bigger strings (100kb of size). It helps to divide the string parts to array:

<?php
// string in $data
               
$ko = 4096;
               
$data2 = array();
                for(
$i=0;$i<ceil(strlen($data) / $ko);$i++) {
                 
$data2[] = substr($data,($i * $ko),(($i+1) * $ko));
                }
// prepared array in $data2
?>

...before serialize()

and

<?php
// array in $data2
             
$data = '';
              for(
$i=0;$i<count($data2);$i++) {
               
$data .= $data2[$i];
              }
// your string in $data
?>

...after unserialize()

Feral (16-Nov-2007 03:30)

While it may not be recommended, it is possible to convert an object to another class while conserving all of its properties (public, protected and private), using serialize.

<?php
function cast_class($object, $newclass)
{
    if( !
is_object($object) )
    {
       
trigger_error('cast_class expects parameter 1 to be object, ' . gettype($object) . ' given', E_USER_WARNING);
        return
false;
    }
    if( !
class_exists($newclass) )
    {
       
// We'll save unserialize the work of triggering an error if the class does not exist
       
trigger_error('Class ' . $newclass . ' not found', E_USER_ERROR);
        return
false;
    }
   
$serialized_parts = explode(':', serialize($object));
   
$serialized_parts[1] = strlen($newclass);
   
$serialized_parts[2] = '"' . $newclass . '"';
    return
unserialize(implode(':', $serialized_parts));
}

?>

Please note that several built-in classes (or classes that are declared in PECL extensions) will not behave as PHP-declared classes and will ne be able to be serialized properly. Because of that, you will not be able to change their class using this function.

Please also note that serialize and unserialize are memory-hungry functions.

barbuj at NOSPAM dot yahoo dot com (14-Nov-2007 10:19)

In my specific situation, I wanted to be able to pass some data from page to page, but without relying on a session variable. The answer I came up with was to serialize() the object in question, pass it on to the next page as a hidden form field, then unserialize() it. When ALL class variables are public, this worked fine. However, if there was at least one private/protected variable, the code no longer worked as expected ("Fatal error: Call to a member function display() on a non-object in page2.php on line 4")

As others have already mentioned, private/protected class variables will not behave nicely (private variables are prefixed by class_name + &#65533;, while protected variables are only prefixed by &#65533; - when looking at the page source using Firefox). Internet Explorer does NOT display the extra character between the class name and variable name, but the code still doesn't work as one would expect.

Suppose you have a simple class:

testclass.php
=============
<?php
class TestClass {
  var
$i = 1;

  function
display() {
    echo
"i=" . $this->i;
  }
?>

page1.php
=========
<?php
 
require_once 'testclass.php';
 
$tc = new TestClass;
 
$tc->display();
?>
<form method = "post" action = "page2.php">
<input type = "hidden" name = "str" value = "<?php echo htmlspecialchars( serialize( $tc ) ); ?>">
<input type = "submit">
</form>

page2.php
=========
<?php
 
require_once 'testclass.php';
 
$tc = unserialize( stripslashes( htmlspecialchars_decode( $_POST["str"] ) ) );
 
$tc->display();
?>

The fix, suggested by evulish on #php/irc.dal.net, is to replace htmlspecialchars()/htmlspecialchars_decode() by base64_encode()/base64_decode. The code becomes:

page1.php
=========
<input type = "hidden" name = "str" value = "<?php echo base64_encode( serialize( $tc ) ); ?>">

page2.php
=========
<?php
  $tc
= unserialize( base64_decode( $_POST["str"] ) );
?>

Hope this will help someone...

Jeex (06-Nov-2007 10:59)

It may be worth noting that, depending on the size of the object you are serializing, the serialize function can take up a lot of memory.

If your script isn't working as expected, your serialize call may have pushed the memory usage over the limit set by memory_limit in php.ini.

More info on memory limits here: http://www.php.net/manual/en/ini.core.php

aksel at metal dot ee (13-Sep-2007 11:31)

To serialize objects with fields that contain unicode values use that logic.

Note! Obviously it does not convert correctly possible unicode values in arrays that may be member values of the object. Use an array class for that that inherits from the same base object that implements that serialization;)

<?php
/**
                  * Serializes object with/without unicode fields
                  * Before serializing encodes unicode values
                  *
                  * @return string
                  */
                 
public function serialize(){
                      
$serialized = array();
                       foreach(
array_keys(get_class_vars(get_class($this))) as $key){
                           if(
is_array($this->$key) ){
                               eval(
'$serialized["'.$key.'"] = serialize($this->'.$key.');');
                           }else{
                                eval(
'$serialized["'.$key.'"] = utf8_encode($this->'.$key.');');
                           }
                       }
                      
$str = serialize($serialized);
                       return
$str;
                  }
                 
/**
                   * Unserializes object with/without unicode fields
                   *
                   * @param string Serialized data
                   */
                  
public function unserialize($serialized){
                      
$data = unserialize($serialized);
                       foreach(
$data as $prop => $val){
                           if(
is_array($this->$prop) ){
                               
$this->$prop = unserialize($val);
                           }else{
                               
$this->$prop = utf8_decode($val);
                           }
                       }
                   }
?>

nothanks at nothanks dot no (16-Aug-2007 11:02)

I had to put a massive multidimensional array in a single field in the database. Unfortunatly the array contained lots of "forbidden" characters: ", ', ;, :, and so on and so forth, breaking the query and my later attempts at deserialize().

Here's a quick and dirty solution:
<?php
$safe_string_to_store
= base64_encode( serialize( $multidimensional_array ) ) ;
?>

And in the other end:
<?php
$encoded_serialized_string
= dbh->query("SELECT archives_arr FROM ". $table_name . " WHERE id=0")

$array_restored_from_db = unserialize( base64_decode( $encoded_serialized_string ));
?>

deminy at deminy dot net (08-Aug-2007 05:44)

Reply to erudd's post:

The regular expression you used to unserialize a PHP session file won't work if the session file contains string variable which contains character "|".

As I can see now, there is no any regular expression that can easily split data in a PHP session file. To read data from a session file, we may have to write a function to read content from the file, and then parse the content.

btbeat at gmail dot com (28-Jun-2007 09:09)

Generally when I do an insert into a database table of posted data, I use the recommended mysql_real_escape_string function, with stripslashes if the get_magic_quotes_gpc is on.
<?php
function prepData($var) {
  if (
get_magic_quotes_gpc()) {
   
$var = stripslashes($var);
  }
return
mysql_real_escape_string($var);
}
?>
I've been having a problem inserting a serialized array into a MySQL database that contained single and double quotes for values.

ex: "quotes" => "some 'quoted' "text""
you'd think it would be:
a:1:{s:6:"quotes";s:20:"some 'quoted' "text"";}
as prepData function would strip the slashes.

However, what goes into the database is:
a:1:{s:6:"quotes";s:24:"some 'quoted' "text"";}
as if there are slashes before the single and double quotes.

Obviously on unserializing the data, there is an error, as 24 chars are expected, when there are only 20.

So, the solution I've coded for my safe insert prepData function is:
<?php
function prepData($var, $serialized = 0) {
  if(
$serialized == 0 )  {
    if (
get_magic_quotes_gpc()) {
     
$var = stripslashes($var);
    }
  }
return
mysql_real_escape_string($var);
}
?>

when inserting plain data from a post:
<? $data = prepData($data); ?>

for serialized data:
<? $data = prepData($data, 1); ?>

cracked my head on this one a bit :|

strange behaviour for serialize(), i.e. string count, counts slashes that are not there.

friday13 at ig dot com dot br (19-Jun-2007 03:15)

I have problem to use serialize function with hidden form field and the resolution was use htmlentities.

Ex.:

<?

$lista = array( 'pera', 'ma?a', 'laranja' );

print "< input type='hidden' name='teste' value='htmlentities( serialize( $lista ) )'" >";

?>

lacent at gmail dot com (13-Jun-2007 06:22)

i noticed the same problem related to quotes, but the person below had no code detailing it. i can only assume he wrote it to fix values, and not to fix the whole array, so heres 2 functions to handle encoding the array.

    function slw_serial ( $var = array(), $recur = FALSE )
    {
        if ( $recur ) {
            foreach ( $var as $k => $v )
            {
                if ( is_array($v) ) {
                    $var[$k] = slw_serial($v, 1);
                } else {
                    $var[$k] = base64_encode($v);
                }
            }
            return $var;
        } else {
            return serialize(slw_serial($var, 1));
        }
    }
       
    function slw_unserial ( $var = FALSE, $recur = FALSE )
    {
        if ( $recur ) {
            foreach ( $var as $k => $v )
            {
                if ( is_array($v) ) {
                    $var[$k] = slw_unserial($v, 1);
                } else {
                    $var[$k] = base64_decode($v);
                }
            }
            return $var;
        } else {
            return slw_unserial(unserialize($var), 1);
        }
    }

---------
USAGE:
---------

    $array = array();
    $array[] = 'this "is a" test';
    $array[] = array('pos'=>'test', 'name'=>'some "dude in" cali');
    $array = slw_serial($array);
    echo $array . '<Br><br>';
    $array = slw_unserial($array);
    echo print_r($array, 1);

kris dover (22-Apr-2007 01:45)

The PHPSerialization class linked in my last comment now supports serialize()'ing java objects to the php serialization text format, thus facilitating a means of data inter-change between php and java communicating against a common php serialized data source.

reverse mappings are as follows:
   _PHP Type_   <-----------------   _Java Type_
      array                            java.lang.Object[]
      int                                java.lang.Byte
      int                                java.lang.Short
      double                           java.lang.Float
      double                           java.lang.Long
      double                           java.lang.BigInteger
      double                           java.lang.BigDecimal
      string                            java.lang.Character
      string                            java.lang.CharBuffer
      string                            java.lang.StringBuffer

admin at goodsoft dot lv (19-Nov-2006 04:25)

When I serialized an object and looked into resulting string, I mentioned that all private properties' names were prefixed by class name.

This code:
<?php
       
class myclass {
                private
$priv1 = "val1",
                          
$myclasspriv2 = "val2";
                public
$pub = "val3";
        }

       
$inst = new myclass ();
        echo
serialize($inst);
?>
resulted in (don't look at word wrapping):
O:7:"myclass":3:{s:14:"myclasspriv1";
s:4:"val1";s:21:"myclassmyclasspriv2";
s:4:"val2";s:3:"pub";s:4:"val3";}

Ates Goral (18-Jul-2006 07:59)

Corrections/clarifications to  "Anatomy of a serialize()'ed value":

All strings appear inside quotes. This applies to string values, object class names and array key names. For example:

s:3:"foo"
O:7:"MyClass":1:{...
a:2:{s:3:"bar";i:42;...

Object property names and values are delimited by semi-colons, not colons. For example:

O:7:"MyClass":2:{s:3:"foo";i:10;s:3:"bar";i:20}

Double/float values are represented as:

d:0.23241446

egingell at sisna dot com (16-May-2006 01:12)

<?
/*
Anatomy of a serialize()'ed value:

 String
 s:size:value;

 Integer
 i:value;

 Boolean
 b:value; (does not store "true" or "false", does store '1' or '0')

 Null
 N;

 Array
 a:size:{key definition;value definition;(repeated per element)}

 Object
 O:strlen(object name):object name:object size:{s:strlen(property name):property name:property definition;(repeated per property)}

 String values are always in double quotes
 Array keys are always integers or strings
    "null => 'value'" equates to 's:0:"";s:5:"value";',
    "true => 'value'" equates to 'i:1;s:5:"value";',
    "false => 'value'" equates to 'i:0;s:5:"value";',
    "array(whatever the contents) => 'value'" equates to an "illegal offset type" warning because you can't use an
    array as a key; however, if you use a variable containing an array as a key, it will equate to 's:5:"Array";s:5:"value";',
     and
    attempting to use an object as a key will result in the same behavior as using an array will.
*/
?>

erudd at netfor dot com (30-Mar-2006 09:36)

To unserialize a PHP session file, unserlize can not be used directly.
The data must be split, as the php session file also contains the names of the variables which serialize/unserialize do not do.  Here is a simple preg_split that will acomplish the split.. (regex not thuroughly tested, but should work for most all circumstances)

<?php
$session
= file_get_contents($session_file);
$data = preg_split('/([A-Za-z_][A-Za-z0-9_]*)\|/',$session,-1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
?>

$data[0] will contain the variable name, and $data[1] will contain the serialized data.  so in effect
<?php
$$data[0] = unserialize($data[1]);
?>
will restore that one variable.

just go through the $data array evens being the variable name, odd being the data.  You can use this to create a simple command line session viewer:)

angel at support-24 dot com (09-Feb-2006 08:25)

I recently had a problem inserting serialized array in mysql DB using PEAR DB_Base class functions. mySQL fails to insert the serialized array because the serialized data contains semicolon. A way to solve that problem is to make same changes to the serialized data:

$serializeorder = serialize($order);
$serializeorder = preg_replace("#;#msi",'0x3B',$serializeorder);
$serializeorder = preg_replace("/(\n)|(\r)/"," ",$serializeorder);
$serializeorder = addcslashes($serializeorder, "\0..\37!@\@\177..\377");
$serializeorder = addslashes($serializeorder);

Here we substitute the semicolon with it's hex. We alse get rid of cariage return. Remember to make the vise versa substitution again when extracting the data.

Neil Green (03-Feb-2006 01:23)

Are you trying to store and retrieve an object from session and it's disappearing?  Did you look at what the serialized object looked like and saw a strange "N;"?  Does the object you're trying to serialize or store in a session define the __call magic method?

Here's the problem:  If you try to serialize an object that uses the __call magic method you are not going to be able to unserialize it.

Here's what happens:

1.  You try to serialize an object with the __call magic method defined
2.  The magic method __sleep is always called on an object being serialized
3.  __call traps __sleep because it's not defined
4.  __call does not respond to __sleep with what is expected: an array of properties to serialize

The solution is defining a __sleep method that returns what it's supposed to when you define a __call:

<?
// This is just a handy debug function
function show( $object ){ echo "<pre>" . print_r( $object, true ) . "</pre>"; }

class foo
{
    private $private = "private value";
    public $public = "public value";
   
    public function __call( $method, $arguments )
    {
       
    }
   
    // Remove this and serialise/unserialse won't work
    public function __sleep()
    {
        return array_keys( get_object_vars( $this ) );
    }
}

$foo = new Foo();

show( $foo );

$serializedFoo = serialize( $foo );
show( $serializedFoo );
show( unserialize( $serializedFoo ) );
?>

BTW, I'm using PHP Version 5.0.4 on Windows.

To the editor:  This post may be useful under the __call, __unserialise, and session pages as well.

Embeded nulls with private vars (18-Jan-2006 04:08)

If you are serializing an object with private variables, beware. The serialize() function returns a string with null (\x00) characters embedded within it, which you have to escape. Not great if you're trying to save objects into a DB...

(16-Jan-2006 03:47)

I use PHP 4.3.10 and I found out that if you use a class "MyClass", the constructor of the class must be called "__construct()" and NOT "MyClass()" like in Java or other languages.

If you use the "MyClass()" constructor, the following won't work :
    $_SESSION['obj_my_class'] = new MyClass();
If you don't believe me, you can have a look in the directory "session.save_path" (default /var/lib/php4) where is stored the session's file. You will see this :
    obj_my_class|N;
and not your complete class!

It took me almost one day to understand what was happening... :-(

varrah NO_GARBAGE_OR_SPAM AT mail DOT ru (13-Jan-2006 09:21)

Worked with Andrea, so the script is now updated to support at least UTF-8 correctly. Details can be found at http://www.sitepoint.com/blogs/2004/04/22/ serializing-php-data-structures-for-javascript (had to insert space after the 22/  otherwise the link was too long and comments engine didn't want to pass it :-) )

varrah NO_GARBAGE_OR_SPAM AT mail DOT ru (10-Jan-2006 01:52)

andrea at 3site dot it gave a link for a JavaScript serialization class, but be prepared! This class works only on single-byte symbols, since JS str.length property gives the length of the string in SYMBOLS, not bytes (as PHP serialize() does), so a Unicode string JS-serialized in a way like:

strSerialized = "s:" + strOriginal.length + ":" + strOriginal;

will not be unserialized correctly by PHP.

MC_Gurk at gmx dot net (03-Jan-2006 03:44)

If you are going to serialie an object which contains references to other objects you want to serialize some time later, these references will be lost when the object is unserialized.
The references can only be kept if all of your objects are serialized at once.
That means:

$a = new ClassA();
$b = new ClassB($a); //$b containes a reference to $a;

$s1=serialize($a);
$s2=serialize($b);

$a=unserialize($s1);
$b=unserialize($s2);

now b references to an object of ClassA which is not $a. $a is another object of Class A.

use this:
$buf[0]=$a;
$buf[1]=$b;
$s=serialize($buf);
$buf=unserialize($s);
$a=$buf[0];
$b=$buf[1];

all references are intact.

Alexander Podgorny (03-Dec-2005 07:47)

Here is an example of a base class to implement object persistence using serialize and unserialize:

<?php
class Persistent
{
    var
$filename;
       
   
/**********************/
   
function Persistent($filename)
    {
       
$this->filename = $filename;
        if(!
file_exists($this->filename)) $this->save();
    }
   
/**********************/
   
function save()
    {
        if(
$f = @fopen($this->filename,"w"))
        {
            if(@
fwrite($f,serialize(get_object_vars($this))))
            {
                @
fclose($f);
            }
            else die(
"Could not write to file ".$this->filename." at Persistant::save");
        }
        else die(
"Could not open file ".$this->filename." for writing, at Persistant::save");
       
    }
   
/**********************/
   
function open()
    {
       
$vars = unserialize(file_get_contents($this->filename));
        foreach(
$vars as $key=>$val)
        {           
            eval(
"$"."this->$key = $"."vars['"."$key'];");
        }
    }
   
/**********************/
}

?>

When an object is extended from this one it can be easily saved and re-opened using it's own methods as follows:

<?

class foo extends Persistent
{
   var $counter;
   function inc()
   {
       $this->counter++;
   }
}

$fooObj = new $foo;
$foo->open();
print $foo->counter; // displays incrementing integer as page reloads
$foo->inc();
$foo->save();

?>

andrea at 3site dot it (26-Nov-2005 05:31)

Hello!
Here you can find a JavaScript Object that should serialize JS vars for PHP and unserialize PHP vars for JavaScript.
http://www.devpro.it/javascript_id_102.html

Please read notes inside the code to know more about vars compatibility.

It was created to resolve AJAX interaction and maybe usefull for other situations .... such:

<?php
// example nested array
$myarray = array(
   
true,
   
123,
    array(
       
'nested',
        array(
           
1,
           
'test'=>false
       
)
    ),
   
'other'=>'value'
);
// array serializzation
$serialized = serialize($myarray);
?>
<script type="text/javascript" src="PHP_Serializer.js"></script>
<script type="text/javascript">
// function to dump an object
function showObject(obj, level) {
    var l = '';
    var tmp = '';
    for(var a = 0; a < level; a++)
        l += '[_]';
    for(var a in obj) {
        var type = typeof(obj[a]);
        if(type == 'object')
            tmp += showObject(obj[a], (level + 1));
        else
            tmp += l + ' key: ' + a + ' = value: ' +
            obj[a] + ' < ' + type + '\n';
    }
    return tmp;
}
// new PHP_Serializer variable
var php = new PHP_Serializer();
// dinamyc JS var creation
var myJSvar = php.unserialize("<?php echo str_replace('"', '\\"', $serialized); ?>");
// look at dump :-)
alert(showObject(myJSvar, 0));
</script>

Regards

pavic at ieee dot org (01-Nov-2005 07:18)

Hi, if You get code like
d:234 and than string You wanted, it's the problem, that
s dot marechal at jejik dot com
explanied.

Well, here is a workaround for that problem, function safe serialize, which won't produce that unwanted chars...

function safe_serialize($string) {
    return preg_replace("/(\n)|(\r)/"," ",$string);
}

stephen dot adamson at smius dot com (01-Nov-2005 05:40)

If you are serializing an object to store it in the database, using __sleep() can save you some space. The following code will not store empty (null) variables in the serialized string. For my purposes this saved a lot of space, since some of the member variables would not be given values.

function __sleep()
{
    $allVars = get_object_vars($this);
    $toReturn = array();
    foreach(array_keys($allVars) as $name)
    {
        if (isset($this->$name))
        {
            $toReturn[] = $name;
        }
    }
    return $toReturn;
}

php barryhunter co uk (29-Oct-2005 12:51)

if you wanting to do something similar to 'mwwaygoo AT hotmail DOT com', then you may want to look at the built in function var_export.

"var_export() gets structured information about the given variable. It is similar to var_dump()  with one exception: the returned representation is valid PHP code."

Sean at http://seanj dot jcink dot com (11-Oct-2005 10:07)

Very short function I made to turn arrays into a string for fwriting, doesnt create unnecessary commas either:

<?
function arraytostring($array){
$text.="array(";
$count=count($array);
foreach ($array as $key=>$value){
$x++;
if (is_array($value)) {$text.=$key."=>".arraytostring($value); continue;}
$text.="\"$key\"=>\"$value\"";
if ($count!=$x) $text.=",";
}
$text.=")";
return $text;
}
?>

eggyknap at gmail dot com (11-Oct-2005 05:01)

My thanks to the editor who pointed out the serialization bug. According to the bug report, this should be fixed in version 5.0.4, and is confirmed fixed in v 5.0.5. Unfortunately I'm not in a position to update my installation, but I found that passing the serialized string through addslashes before saving it to the database does the trick. It may be a bit inefficient, but it works.

eggyknap at gmail dot com (09-Oct-2005 05:12)

[Editor's note: This has been fixed. Protected and private members were serialized with a leading \0 (zero byte). Bug report here, http://bugs.php.net/29865 - aidan@php.net]

Be careful trying to serialize objects containing private or protected data members. It appears that the serialization process includes characters in the result string to indicate the visibility of each member, but the characters used to denote protected or private data are outside the normal character set and can cause problems as you pass them through applications. I haven't found the culprit in my particular case, so I can't say that this is a bug in PHP, but it certainly is causing me some annoyance in my particular situation.

mwwaygoo AT hotmail DOT com (18-Jul-2005 04:03)

Hello people,

I had major problems getting serialize to work properly, as I wanted to sync two databases via email, and needed a way of converting a retrieved row to a string. It works the reverse of array(), in that it creates a statement that you can use to evaluate to the original array, so I called it unarray().
Its a recursive function (self calling), so it doesnt matter how complex the array is.

<?php

$source
=array(1,4,'x'=>'test');
$text=unarray($source);

$destination=array(); // prime the variable incase of failure.
eval('$destination='.$text);
print_r($destination);

// unarray.php    REVERSE of array();

function unarray($array, $first=TRUE)
{
   
$text="";
    if(
is_array($array))
    {
       
$text.="array(";
        while(list(
$key,$value)=each($array))
        {
            if(
is_string($key))
            {
               
$text.="'".$key."'";
            }
            else
            {
               
$text.=$key;
            }
           
$text.="=>";
           
$text.=unarray($array[$key], FALSE);
        }
       
$text=$text."), ";
    }
    else
    {
        if(
is_string($array))
        {
           
$text.="'".addslashes($array)."', ";
        }
        else
        {
            if(
is_bool($array))
            {
                if(
$array)
                {
                   
$text.="TRUE, ";
                }
                else
                {
                   
$text.="FALSE, ";
                }
            }
            else
            {
                if(
is_null($array))
                {
                   
$text.="NULL, ";
                }
                else
                {
                   
$text.=$array.", ";
                }
            }
        }
    }
    if(
$first) $text=substr($text,0,-2).";";
    return
$text;
}

?>

p.s. I realise that it also creates unnecessary commas, but these are ignored when re-creating it. array(1,2,) is the same as array(1,2).

abductee _at_ texture _minus_ editor.com (14-Jun-2005 12:44)

wiart at yahoo dot com wrote:
>As you can see, the original array :
>$arr["20041001103319"] = "test"
>
>after serialize/unserialize is:
>$arr[683700183] = "test"

yepp, and i can explain it.

the internal compiler of php does not hit anys rule wich foces him to make that number a string during serialisation. since it becomes an integer and php supports 32bit interger not arbitary bitwidth this is what happens:

"20041001103319"
equals hexadecimal:

0x123A28C06FD7h

if you cut away the frontpart cutting down to 32bis,
you get:

0x28C06FD7h

wich equals 683700183.

of, for those of you who speak binary:

20041001103319 =
100100011101000101000110000000110111111010111bin

----cut-away----00101000110000000110111111010111bin
=683700183

so, what can you do to prevent stuff like this?
eihter use only numbers between 0..9999999999
or force strings, best way ist to add a character
like

foo["c2342303"]

cheers, abductee

gafunchal NOSPAN at inf dot ufrgs dot br (23-Jan-2005 12:33)

(please, excuse my poor English)

'serialize' does strange things with floats, this code:

  $a = 3.14;
  $s = serialize($a);
  $fp = fopen("storage", "w");
  fwrite($fp, $s);
  fclose($fp);

outputs something like (PHP 5.0.2):

d:3.140000000000000124344978758017532527446746826171875;

I wonder why serialize doesn't store data (not only float, I mean all types of data) in a more 'economic' format. Maybe binary is not the best option (there can be trouble storing it in databases), but there are still a lot of other possibilities.

cjmeyer at npcc dot net (24-Dec-2004 07:16)

More on troubles with recursive object references and serialization.

In my PHP 4.2.2 the solution suggested above (by james at gogo dot co dot nz), to pass a reference to the object to serialize(), does not help.  There are still multiple copies of the objects woken up, and the recursive reference is no longer recursive.

The only solution I have found is to use the __sleep and __wakeup magic functions to only serialize the link one-way, then recreate it manually on unserialize.  This isn't too difficult;  here is some code demonstrating this approach:

class A {
  var $data = Null;
  var $b = Null;

  function A($data, $bData) {
    $this->data = $data;
    $this->b = new B(&$this, $bData);
  }

  function printData() {
    print 'A thinks A data is ' . $this->data . "\n";
    print 'A thinks B data is ' . $this->b->data . "\n";
  }

  function __sleep() {
    print "A is going to sleep.\n";
    return array('data', 'b');
  }

  function __wakeup(){
    print "A is waking up.\n";
    $this->b->reLinkA($this);
  }

}

class B {
  var $data = Null;
  var $a = Null;

  function B(&$a, $data) {
    $this->a =& $a;
    $this->data = $data;
  }

  function printData() {
    print 'B thinks A data is ' . $this->a->data . "\n";
    print 'B thinks B data is ' . $this->data . "\n";
  }

  function __sleep() {
    print "B is going to sleep.\n";
    return array('data');
  }

  function __wakeup(){
    print "B is waking up.\n";
  }

  function reLinkA(&$a) {
    $this->a =& $a;
  }

}

$a = new A("origAdata", "origBdata");

print '<pre>';

print "I think A data is " . $a->data . "\n";
print "I think B data is " . $a->b->data . "\n";
$a->printData();
$a->b->printData();

$serA = serialize($a);
$newA = unserialize($serA);

$newA->data = 'newAdata';
$newA->b->data = 'newBdata';

print "I think new A data is " . $newA->data . "\n";
print "I think new B data is " . $newA->b->data . "\n";
$newA->printData();
$newA->b->printData();

wiart at yahoo dot com (16-Dec-2004 11:40)

Warning: on 64 bits machines,  if you use a long string only composed of numbers as a key in an array and serialize/unserialize it, you can run into problems:

an example code:
$arr["20041001103319"] = 'test';
var_dump( $arr);
$arr_in_str = serialize($arr);
print "Now result is: $arr_in_str<BR />";
$final_arr = unserialize($arr_in_str);
print "The final unserialized array:<BR />";
var_dump($final_arr);

The result:
array(1) { [20041001103319]=>  string(4) "test" }
Now result is: a:1:{i:20041001103319;s:4:"test";}
The final unserialized array:
array(1) { [683700183]=> string(4) "test" }

As you can see, the original array :
$arr["20041001103319"] = "test"

after serialize/unserialize is:
$arr[683700183] = "test"

As you can see,  the key has changed ...

Apparently a problem of implicit casting + integer overflow (I posted a PHP bug report: http://bugs.php.net/bug.php?id=31117)

I tested with the latest 4.3.10 compiled on my laptop (32 bits, Mandrake 9.1) --> no such problem. But compiled on AMD 64 bits (Red Hat Taroon), the problem is present.

Hope this will help some of you to not loose almost a whole day of debugging ;-)

richard dot prangnell at ntlworld dot com (12-Dec-2004 10:08)

Although the serialise function has its proper uses, it is a relatively slow process. I try to avoid using it wherever possible in the interests of performance. You can store text records in a database as plain text even when it contains PHP variables. The variable values are lost, naturally; but if they can easily be re-attached to retrieved records, zillions of clock cycles can be saved simply by using the str_replace() function:

  if($convert)
  {
    $mainContent = str_replace('$fixPath', $fixPath, $mainContent);
    $mainContent = str_replace('$theme', $theme, $mainContent);
  }

The above snippet is used in a CMS project. $fixPath contains  something like '.' or '..' to prepend relative paths (allowing the record to be used by scripts located in different parts of the directory hierarchy) and $theme inserts the name of the users custom page rendering scheme, which obviously would be undefined at record storage time anyway.

corey at eyewantmedia dot com (08-Dec-2004 06:47)

If this helps anybody, I was looking for a few quick calls to cache stuff to files. I settled on the below functions. By the way, if I am doing something stupid here, I'd appreciate some comments on that also. Anyway, on with the code:

First, the usage:

//Use:

$var = tuncache('MyCacheName');
if (is_null($var)) {
    $var = 'a really expensive process';
    $check = tcache('MyCacheName', $var, '+25 minutes');
    if (is_null($check)) {
        die('I need to reset my permissions or get a bigger hard drive');
    }
}

//use $var now

Now, the functions:

//uses strtotime to decide how long to cache $cacheVar based on $lifespan
//so anything but a timestamp works. +1 day works, 09/14/2010 works, etc
function tcache($cacheName, $cacheVar, $lifespan=null) {
    if (!is_null($lifespan)) { //a lifespan was provided
        if (strpos($lifespan, '+') === 0 || strpos($lifespan, '-') === 0) {
            //Have to do this to counter for bug in php5 to
            //properly evaluate now to do the date math
            $endTime = strtotime(date('m/d/Y H:i:s') . ' ' .$lifespan);
        } else {
            //we can safely use anything else I think
            $endTime = strtotime($lifespan);
        }
    } else {
        //cache forever (forever being ten years) until manually deleted
        $endTime = strtotime(date('m/d/Y H:i:s') . ' +10 years');
    }
   
    $cVal = serialize($cacheVar);
    $file = tFindcache($cacheName);
    $result = true;
   
    $f = fopen($file, 'w');
    if ($f === false) {
        $result = null; //barf if we can't open the file
    } else { //write the cache
        fwrite($f, $endTime . "\n");
        fwrite($f, $cVal);
        fclose($f);
    }
   
    return $result;
}

function tuncache($cacheName) {
    $file = tFindCache($cacheName);

    if (is_readable($file)) {
        //open file
        $f = fopen($file, 'r');
        $time = time();
        $expTime = trim(fgets($f));
        //check time
        if ($time > $expTime) {
            //It expired
            $result = null;
        } else {
            //Read it and unserialize it
            $data = fread($f, filesize($file));
            $result = unserialize($data);
        }
    } else {
        //barf
        $result = null;
    }
   
    return $result;
}

//just to set a few options for setting where to save stuff
function tFindCache($cacheName) {
    if (isset($_ENV['PHP_CACHE_PATH'])) {
        $cachePath = $_ENV['PHP_CACHE_PATH'];
    } else if (isset($_SERVER['PHP_CACHE_PATH'])) {
        $cachePath = $_SERVER['PHP_CACHE_PATH'];
    } else {
        $cachePath = './'; //Potential danger here
    }
   
    $cachePath .= 'PHP_CACHE_' . $cacheName . '.cache';
   
    return $cachePath;
}

(01-Dec-2004 09:30)

This is just a modification of what Alan Reddan (areddan at silverarm dot ie) posted below.

I figured it would be faster than walking an array, and it works wonderfully with cookies

<?php
$data
[qwerty] = "blah";
$data[1][a] = "1aa";
$data[2][b] = "2bb";
$data[3][c] = ";;;;;;";
$data[name][first] = "Bob";
$data[name][last] = "Jones";
$data[val] = "This is a real long test string, to see how well the compression works!";

//To Serialise Call :
$string = gzcompress(serialize($data), 9);
setcookie("my_var", $string, time()+60*60*24*60, '/');
//print "String: $string\n<br>"; //uncomment to see serialized array

//To Unserialize Call
if (isset($_COOKIE[my_var])) {
 
$array = unserialize(gzuncompress($_COOKIE[my_var]));

  echo
"<pre>";
 
print_r($array);
  echo
"</pre>";
}
?>

you can replace gzcompress with base64_encode and gzuncompress with base64_decode to have a similar experience

Alan, thanks for the tip though, it got me where I wanted to be!

paul at moveNOtoSPAMiceland DOT com (18-Nov-2004 04:29)

I was trying to submit a serialized array through a hidden form field using POST and was having a lot of trouble with the quotes. I couldn't figure out a way to escape the quotes in the string so that they'd show up right inside the form, so only the characters up to the first set of quotes were being sent.

My solution was to base64_encode() the string, put that in the hidden form field, and send that through the POST method. Then I decoded it (using base64_decode()) on the other end. This seemed to solve the problem.

Alexei dot Filine at cern dot ch (24-Oct-2004 03:57)

A simple way to transfer PHP variables between PHP scripts running on different hosts can be done with HTTP_Request PEAR module. I think it is much more fast way than one done with XML-RPC but less portable (there were described ways to exchange vars between Perl and PHP below). Recieved PHP obects are required to be created before recieving by class definition similar to definition used on sending side. A script sending variable must output nothing except data sent by function 'sendVariable' so a 'composite variable' is to be used to transfer some variables by one request.

<?php
// exchange-protocol.php
ini_set( 'include_path', '.' );
require_once
"config.php"; // set $PEAR_path
ini_set( 'include_path', ini_get( 'include_path' ).$PEAR_path );

// PEAR module
require_once "HTTP/Request.php";

// magic words for HTTP header
$gzcompressed_serialized_type = 'application/serialized_gzcompressed_PHP_variable';
$serialized_type = 'application/serialized_PHP_variable';

$compression_flag_name = '_compressionFlag_';

// Date in the past
header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );

// always modified
header( "Last-Modified: ".gmdate( "D, d M Y H:i:s" )." GMT" );

// returns non-zero on success
function recieveVariable( $url,
              &
$var,
             
$user = '',
             
$passw = '',
                 
$compression_flag = 1 ) {

    global
$gzcompressed_serialized_type;
    global
$serialized_type;
   
$req =& new HTTP_Request( "" );
     
$req->setURL( $url );
     
$req->setMethod( HTTP_REQUEST_METHOD_POST );

     
// set user/password if required
   
if ( $user && $passw ) {
         
$req->addPostData( $user,
                            
$passw );
    }
     
$response = $req->sendRequest();
     
$req->clearPostData();
    if (
$compression_flag ) {
       
$req->addPostData( $compression_flag_name, 1 );
    }
      if (
PEAR::isError( $response ) ) {
            echo
$response->getMessage();
      } else {
           
$header = $req->getResponseHeader();
            if (
$req->getResponseCode() != 200 ||
                 ! (
$header['content-type'] == $gzcompressed_serialized_type ||
                   
$header['content-type'] == $serialized_type ) ) {
                   
// type error message
                   
echo $req->getResponseBody();
            } else {
                    if (
$header['content-type'] == $gzcompressed_serialized_type )
{
                           
$data = gzuncompress( $req->getResponseBody() );
                    } else {
                           
$data = $req->getResponseBody();
                    }
                   
$var = unserialize( $data );
            return
1;
            }
    }
    return
0;
}

// just for extra flexibility, if data chunk is small enough we can skip gzipping on the sending side: $compression_flag = 0;
// in other case we use client preference: $compression_flag = $_REQUEST[$compression_flag_name];
function sendVariable( &$var, $compression_flag = 1 ) {

    global
$gzcompressed_serialized_type;
    global
$serialized_type;
   
// Date in the past
   
header( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );

   
// always modified
   
header( "Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");

    if (
$compression_flag ) {
       
// set specialised content type to inform about data type
       
header( 'content-type: '.$gzcompressed_serialized_type );
        echo
gzcompress( serialize( $var ) );
    } else {
       
// set specialised content type to inform about data type
       
header( 'content-type: '.$serialized_type );
        echo
serialize( $var );
    }
}
?>

on client side:
<?php
...
require_once
"exchange-protocol.php";
...
if (
recieveVariable( $url, $var) ) {
   
// success...
} else {
   
// there was something wrong...
}
?>

on the server side:
<?php
...
require_once
"exchange-protocol.php";
...
// there must not be output before the function is called!!! execution is to 'die' if an error occures.
sendVariable( $var, $compression_flag )
?>

areddan at silverarm dot ie (23-Oct-2004 09:56)

<?php
/*
This is an array_walk style serialize that works with multi dimensional arrays, it also base64 encodes and decodes to allow ';' to exist in the array.
 -- Alan Reddan
*/
$data[qwerty] = "blah";
$data[1][a] = "1aa";
$data[2][b] = "2bb";
$data[3][c] = ";;;;;;";

//To Serialise Call :

array_walk($data,'base64_encoder_multi');
$serialized_string = serialize($data);
//print $serialized_string . '\n'; //uncomment to see serialized array

//To Unserialize Call

$array = unserialize($serialized_string);
array_walk($array,'base64_cleaner_multi');

print_r($array);
//start functions
function base64_encoder_multi(&$val,$key) {
   if (
is_array($val)) array_walk($val,'base64_encoder_multi',$new);
   else {
     
$val = base64_encode($val);
   }
}

function
base64_cleaner_multi(&$val,$key) {
   if (
is_array($val)) array_walk($val,'base64_cleaner_multi',$new);
   else {
     
$val = base64_decode($val);
   }
}
//ends

?>

brooklynphil hotmail com (06-Oct-2004 09:07)

In my experience of the (far and few in between) times when it is necessary to store large (megabytes) amounts of data in a php-readable ascii file format, using var_export() and require() is much faster serialize() and unserialize(file_get_contents()) (I have tested it on classes encapsulating arrays, i.e. <?php class blah { $a = array(megsofstuffhere); $b = array(megsofstuffhere); $c=... }; $data = new blah ?>)   (var_export is also more readable and notepadable than serialize!)

However, since var_export produces only the rvalue (or uninstantiation), of the data needed, dont forget to cosmetically modify output of var_export( , true): in case of classes, you will need to use "$var = new classname" (and rename a possible stdClass) and in case of arrays, etc, just use "$var = ".var_export().  The file being var_export()ed to and require()ed must also be encapculated in "<?php ?>" when written to (or else its just dumped to browser/stdout as a textfile).

Hope this helps :)

--Phil

P.S. (in cases of small amounts of data, serialize is better, especially for cross-URL data transport using <?php base64_encode(gzdeflate(serialize()))?>)

jan at bestbytes dot de (05-Oct-2004 09:58)

This should be EXTREMELY helpful when you are getting lost in php 4 circular references and sessions or serializing ...

<?php

// this example is for php 4

class Node {
  var
$value;
  var
$child;
  var
$parent;
  var
$load;
  var
$__destroyed = false;
  function
Node($value)
  {
   
$this->value = $value;
    global
$load;
   
$this->load = $load;
  }
  function
setParent(&$parent)
  {
   
$this->parent = &$parent;
  }
  function
setChild(&$child)
  {
   
$this->child = &$child;
  }
 
/**
  * @return void
  * @desc fake __destroy from a php 4 point of view
  */
 
function __destroy()
  {
   
$props = get_object_vars($this);
    foreach(
$props as $propName => $propValue) {
      unset(
$propValue);
      if(
is_object($this->$propName)) {
        if(
method_exists($this->$propName, '__destroy') AND $this->$propName->__destroyed !== false) {
         
$this->$propName->__destroy();
        }
      }
      if(isset(
$this->$propName)) {
        unset(
$this->$propName);
      }
    }
  }
}
header('Content-type: text/plain');

// small load to check the serialized string
$loadSize = 4;

// big load to check leaking
//$loadSize = 32 * 1024;

$load     = str_repeat('.', $loadSize);

for(
$i = 0;$i<10;$i++) {
  echo
'-------------------- '.(memory_get_usage()/1024).' -------------------------'.chr(10);
 
 
$serMe = array();
 
$serMe['parent'] =& new Node('parent');
 
$serMe['child']  =& new Node('child');
 
 
/*
   * this will work too !!
   *   $serMe['parent'] = new Node('parent');
   *   $serMe['child']  = new Node('child');
   */

 
$serMe['parent']->setChild($serMe['child']);
 
$serMe['child']->setParent($serMe['parent']);
 
 
 
$str = serialize($serMe);
 
 
/*
   * 1.Problem:
   *
   * You have 2 or more objects with circular references to one another.
   * Serializing these objects will result in unexpected behaviour when
   * unserializing them:
   *
   * Former references will become copies.
   *
   * This is because the php serialize handler can not handle references,
   * unless all involved objects, variables ... are within an array(),
   * that will be serialized.
   *
   * This should be selfexplaining (just take a look at the length ...):
   * echo serialize($serMe['parent']);
   * echo serialize($serMe);
   *
   * results in:
   *
   * O:4:"node":5:{s:5:"value";s:6:"parent";s:5:"child";O:4:"node
   * ":5:{s:5:"value";s:5:"child";s:5:"child";N;s:6:"parent";O:4:
   * "node":5:{s:5:"value";s:6:"parent";s:5:"child";R:3;s:6:"pare
   * nt";N;s:4:"load";s:4:"....";s:11:"__destroyed";b:0;}s:4:"loa
   * d";s:4:"....";s:11:"__destroyed";b:0;}s:6:"parent";N;s:4:"lo
   * ad";s:4:"....";s:11:"__destroyed";b:0;}
   *
   * a:2:{s:6:"parent";O:4:"node":5:{s:5:"value";s:6:"parent";s:5
   * :"child";O:4:"node":5:{s:5:"value";s:5:"child";s:5:"child";N
   * ;s:6:"parent";R:2;s:4:"load";s:4:"....";s:11:"__destroyed";b
   * :0;}s:6:"parent";N;s:4:"load";s:4:"....";s:11:"__destroyed";
   * b:0;}s:5:"child";R:4;}
   *
   * PLEASE GIVE THE WORLD PROPER DOCUMENTATION ON THIS (or prove us wrong)
   *
   * 2.Problem:
   *
   * The loop below will result in extensive leaking (use the big $loadsize ...),
   * unless you help yourself and unset all the properties manually
   * see Node::__destroy()
   *
   */
 
 
$serMe['parent']->__destroy();
 
$serMe['child']->__destroy();
 
$serMe = unserialize($str);
  unset(
$str);
 
$serMe['parent']->value = 'new parent';
  echo
'-->'.$serMe['parent']->child->parent->value.chr(10);
  echo
'-->'.$serMe['parent']->value.chr(10);
 
 
$serMe['parent']->__destroy();
 
$serMe['child']->__destroy();
  unset(
$serMe);
}

?>

mary at nospam dot com (20-Sep-2004 09:57)

If you use serialize() to easily convert an array to a sort of string which you can add to a URL, pay attention to the length of the serialized array.
A URL has a limit when it comes to passing variables and values and it cuts off whatever is over limit. If your serialized array is too long, it will be cut off and you will end up with strange results on your other pages.

jasbarne NOSPAM indiana SPAMSUCKS edu (22-Aug-2004 09:01)

ignatiev at users dot sourceforge dot net and others using __sleep():

If you decide to add this functionality (for whatever reason) you can serialize a modified copy of the object instead of the original object.  There's added overhead of copying, but doing this allows you to continue using the original object after you've serialize it.

goetas at lignano dot it - GoetAs (11-Aug-2004 06:41)

the serialize dont function properly when a variable contain a ;
I wrote these two functions that resolve this problem:
this function work only with arrays:
<?php

function base64_unserialize($str){
   
$ary = unserialize($str);
    if (
is_array($ary)){
        foreach (
$ary as $k => $v){
            if (
is_array(unserialize($v))){
               
$ritorno[$k]=base64_unserialize($v);
            }else{
               
$ritorno[$k]=base64_decode($v);
            }
        }
    }else{
        return
false;
    }
    return
$ritorno;
}
function
base64_serialize($ary){
    if (
is_array($ary)){
        foreach (
$ary as $k => $v){
            if (
is_array($v)){
               
$ritorno[$k]=base64_serialize($v);
            }else{
               
$ritorno[$k]=base64_encode($v);
            }
        }
    }else{
        return
false;
    }
    return
serialize ($ritorno);
}
?>

Andrew dot Morrison at stanford dot edu (29-Jun-2004 11:02)

Correction to my last note:

__sleep should return an array only containing the names of instance-variables to serialize.

A simple (if not a little wasteful) hack to serialize all but a few class vars is to use get_class_vars as follows:

<?php

class strawman
{
  var
$good_var;
  var
$lame_var;

  function
__sleep()
  {
    print
"Function __sleep() called\n";

   
$vars = get_class_vars('strawman');
    unset(
$vars['lame_var']);
    return
array_keys($vars);
  }

  function
__wakeup()
  {
   print
"Function __wakeup() called\n";
  }

  function
strawman() { }
}

session_start();

if(
session_is_registered('strawman'))
{
  print(
"session data:\n");
 
print_r($_SESSION['strawman']);
 
session_destroy();
}

else
{
 
$strawman =& new strawman();
 
session_register('strawman');
  print(
"new session data:\n");
 
print_r($_SESSION['strawman']);
}

?>

dr dot slump at cyteknt dot com (27-Apr-2004 05:15)

regarding PHP to JS serialization I did some time ago a function which works using "eval" as Harry points out.

<?php
//helper function, returns true if the array is associative
function is_assoc_array( $var ) {
   
//false if not an array or empty
   
if ( (!is_array($var)) || (!count($var)) ) return false;
   
    foreach(
$var as $k=>$v)
        if (!
is_int($k)) return true;
       
    return
false;
}
?>

Serialize function which generates JavaScript's eval's compatible code.

Usage (JavaScript) :
var myVar = eval('<?php js_serialize($phpvar); ?>');
   
Notes:
Objects and associative arrays are encoded as JS Objects   
Doesn't serialize object methods
Serializes 'resource' types as nulls
Assoc. Arrays containing integer keys, those keys are prefixed with 'idx_'

<?php
function js_serialize($var, $recursed = false) {
    if (
is_null($var) || is_resource($var)) return 'null';

   
$js = '';
   
   
//object or assoc. array
   
if (is_object($var) || is_assoc_array($var)) {
       
//typecast to array in the case it could be an object
       
$props = (array)$var;
           
        foreach(
$props as $k=>$v) {
           
//index values are preffixed with 'idx_'
           
if (is_int($k)) $k = "idx_$k";
           
$js .= $k.':'.js_serialize($v, true).',';
        }
        if (
count($props))
            
$js = substr($js, 0, strlen($js)-1);
        
        
$js = '{'.$js.'}';
         if (!
$recursed) $js = "($js)";
            
    } elseif (
is_array($var)) {
        foreach(
$var as $v)
           
$js .= js_serialize($v, true).",";
        if (
count($var))
           
$js = substr($js, 0, strlen($js)-1);
       
$js = "[$js]";
       
    } elseif (
is_string($var)) {
       
//escape the string
       
$var = str_replace( array('"', "\n", "\r"), array('\\"', '\\n'), $var );
       
$js = $recursed ? "\"$var\"" : "(new String(\"$var\"))";
   
    } elseif (
is_bool($var)) {

       
$var = ($var)?'true':'false';

       
$js = $recursed ? $var : "(new Boolean($var))";
   
    } else {
//should be an int or a float in theory       

       
$js = $recursed ? $var : "(new Number($var))";
    }

    return
$js;
}
?>

hfuecks at phppatterns dot com (22-Apr-2004 04:20)

Regarding serializing PHP data types to Javascript, following Ivans note below, theres an example at http://www.tekool.net/php/js_serializer/.

The basic serialization looks good although, in its current form, it works on the basis of generating Javascript source which a browser executes as a page loads. Using Javascripts eval() the same can be done with strings containing Javascript if youre working with something like XMLHTTPRequest

Antonie (20-Apr-2004 06:12)

Passing of multiple select (single dimensional or even multidimensional) arrays is even harder, even using serialize.

Jouhni [jouhni at web dot de] (08-Feb-2004 01:48)

In order to save serialized values in cookies you have to pay attention to the following:
A serialized array looks like this:

a:2:{i:0;s:9:"Element 1";i:1;s:9:"Element 2";}

Because quotation marks are saved with a backslash in front of it in cookies it is not possible to unserialize a cookie-saved serialized array. You have to do a stripslashes() before unserializing the cookie.

info at b1g dot de (07-Feb-2004 06:37)

If you are using Cache_Lite from pear.php.net and if you are logging in your users using cookies, use this cache-ID for example:

<?php
$cache_id
= base64_encode($_SERVER['REQUEST_URI'] . serialize($_COOKIE));
?>

This will create a new page in cache when a user logs in. Anyway he can't login properly. Works fine for me.

Sorry for my broken English.

tino at infeon dot com (24-Nov-2003 10:20)

While writing shopping cart applications i needed a way to keep track of many variables beteween page loads.. i was using a cookie for each but this became hard to manage so I cam up with this simple session object. It serializes the object, base 64 encodes it and sets a cookie for it.. vice versa on page load where it detects the cookie

add whatever variables you need to this class

btw if you like it, hate it or have any comments send me an email to let me know

<?php
class session {
    var
$cartID;
    var
$userID;
    var
$userAuth;
   
    function
session () {
       
//Attempt to load previous session from user cookie
       
        //First see if the session was passed through the URL
        //This is useful to pass stuff between different URL
               
if ($_GET['session']) {
           
$this = unserialize (base64_decode ($_GET['session']));
       
               
//Check for the cookie, if none a blank session is created
               
} else {
            if (
$_COOKIE['session']) {
               
$this = unserialize (base64_decode ($_COOKIE['session']));
            }
        }
    }

    function
save () {
       
setcookie ('session', base64_encode (serialize ($this)));
    }

    function
delete () {
       
setcookie ('session');
        unset (
$this);
    }

}
?>

ignatiev at users dot sourceforge dot net (24-Oct-2003 02:35)

One problem with serialize() is that by default it does NOT alter the object, so nothing prevents you from continuing using you object after serialize()'ing it.

After a while, you or someone else decides to optimize storage of this object and add a __sleep and __wakeup functions; now, serialize()'ing this same class calls __sleep() member function, potentially changing the object - old code unexpectedly breaks.

Possible solutions: in the above scenario old code would most likely still work if __sleep() only creates new object variables, not altering existing ones.  Another option is to always call __wakeup(), if it exists, after each serialize(), or immediately destroy the object if it is no longer used.

iam4webwork at hotmail dot com (15-Sep-2003 01:00)

I think an example is in order to specify what is meant by "returns a string containing a byte-stream representation of value that can be stored anywhere."

Here's an example:

<?php
echo serialize("php");
?>

Result is as follows:

s:3:"php";

The cryptic result is a string indicating that the serialized data is itself a string of 3 bytes whose value is "php".

james at gogo dot co dot nz (30-Jul-2003 11:04)

I just spent an hour rifling through code to find the cause of a problem
only to find it's an oddity with serialization and recursive objects, so
figured I'd post for the next person who gets the same problem.

********************************* Symptoms *********************************
When unserializing a previously serialized object, the __wakeup() function
is mysteriously called more than once, and the accessing the objects
properties from the "outside" gives different results than accessing them
from an object contained within the object and holding  a recursive
reference to the object.

********************************** Example *********************************
<?php
class foo2 {
        var
$foo = NULL;
        function
foo2(&$foo) {
               
$this->foo =& $foo;
        }

        function
fooName() {
                echo
'foo2 thinks foo->name is ' . $this->foo->name . '<br>';
        }
}

class
foo {
        var
$name  = 'unnamed';
        var
$foo2 = NULL;

        function
foo() {
               
$this->foo2 =& new foo2($this);
        }

        function
fooName() {
                echo
'foo thinks foo->name is ' . $this->name . '<br>';
        }

        function
__wakeup() {
                echo
"foo is waking up<br>";
        }
}

$myFoo         =& new foo();
$myFoo->name   = 'myFoo';
echo
"I think foo->name is {$myFoo->name}.<br>";
$myFoo->fooName();
$myFoo->foo2->fooName();

$serializedFoo = serialize($myFoo);
$myNewFoo      = unserialize($serializedFoo);

$myNewFoo->name = 'myNewFoo';
echo
"I think foo->name is {$myNewFoo->name}.<br>";
$myNewFoo->fooName();
$myNewFoo->foo2->fooName();
?>

********************************** Analysis ********************************
execution of the example produces...

I think foo->name is myFoo.
foo thinks foo->name is myFoo
foo2 thinks foo->name is myFoo
foo is waking up
foo is waking up
I think foo->name is myNewFoo.
foo thinks foo->name is myNewFoo
foo2 thinks foo->name is myFoo

We can see that the first three lines are as expected, however we see
__wakeup is happening twice, and then the final line is in error as foo2
apparently does not see the changed name.

What is happening is that there are actually two seperate foo objects being
deserialized, the "top level one" and the one that was originally
referenced in foo2, that is, the reference is not being serialized as a
reference but rather a whole object.  This is evident in the two __wakeup()
calls, there are two foo objects being woken up.

******************************** Solution **********************************
The solution is very simple, when serializing it is necessary to force the
passing of a reference to the top-level object being serialized thus..

$serializedFoo = serialize(&$myFoo);

with that form of the serialization (note the ampersand to force passing of
reference), the example produces the following..

I think foo->name is myFoo.
foo thinks foo->name is myFoo
foo2 thinks foo->name is myFoo
foo is waking up
I think foo->name is myNewFoo.
foo thinks foo->name is myNewFoo
foo2 thinks foo->name is myNewFoo

We note now there is only one __wakeup() call being made and that all
parties agree on the name property of the foo object.

******************************** Notes ************************************
I was of the belief that ampersand's in the arguments to functions was
deprecated in favour of ampersands in the function's parameter list
declaration (i.e instead of "blah(&$my_thing)" we declare blah as "function
blah(&$your_thing) {...}"), however this required use of serialize seems to
contravene this deprecation as it is plainly necessary to use the ampersand
in the function call here.  Perhaps this is a hold-over from earlier times
and will be changed in the future ?

--
James Sleeman (http://www.gogo.co.nz/)

dan at mojavelinux dot com (18-Jul-2003 08:08)

In order to safely unserialize a complex object in any context, it is wise to save two files at the time of serialization (or save the file in two parts).  One file will contain the result of get_included_files() at the time of serialization and the other file contains the serialized version of the object.  To unserialize, simply read in the included file list and call include_once on all of those files and then call unserialize on your object data.

While this may be slightly inefficient because certain files that were included are no longer needed (maybe they were only needed when creating the object), at least you can be sure the object data is going to come out of serialization okay.

Note: If you stick to the convention of classes beginning with uppercase (and the filenames following the classnames) then you can even filter the get_included_files() list to get only the class definition files.

webmaster at feeltong dot com (12-Jun-2003 11:49)

People usually use 'hidden' fields when they submit some variables from previous step to the next step even if they have so many varibles to send. It will look like following form.

<form name='tmpForm' method='post' action='nextStep.php'>
<input type='hidden' name='var[name]' value='<?=$var[name]?>'>
<input type='hidden' name='var[id]' value='<?=$var[id]?>'>
<input type='hidden' name='var[address]' value='<?=$var[address]?>'>
<input type='hidden' name='var[age]' value='<?=$var[age]?>'>
<input type='hidden' name='var[gender]' value='<?=$var[gender]?>'>
<input type='hidden' name='var[car]' value='<?=$var[car]?>'>
.
.
.
</form>

Look at the following codes. It is more simplified. I'd better use base64_encode and serialize than stripslashes and serialize.

<form name='tmpForm' method='post' action='nextStep.php'>
<input type='hidden' name='var' value='<?=base64_encode(serialize($var))?>'>
</form>

Have Fun !!!

rodrigo at ditech dot com dot br (17-Apr-2003 07:38)

Hi!
If you wanna save all the POST data and reload it again in another time... you can use this:
(Thanks for my_stripslashes() function ;-)

<?php
// saving POST
if ($REQUEST_METHOD=="POST") {
   
$fp = fopen("postData.txt","w"); 
 
$data = addslashes(serialize($_POST));
 
fwrite($fp, $data);
  
fclose($fp);
}

// reloading POST and passing to variables
if (file_exists("postData.txt")) {
 
$data = file("postData.txt");
 
$data = my_stripslashes($data[0]); // catches it in some message above
 
$postData = unserialize($data);
   
extract($postData, EXTR_OVERWRITE);
}
?>

Now you have all variables from old POST in your actual script.
Well useful when you have a great form very used and of course, DEPENDING of your tool.

pli9 at itsa dot ucsf dot edu (01-Feb-2003 07:05)

I have also written some code for importing serialized PHP data into PERL and then writing it back into PHP.  I think the similar library posted above is actually more robust for a few select cases, but mine is more compact and a little easier to follow.  I'd really like comments if anyone finds this useful or has improvements.  Please credit me if you use my code.

http://www.hcs.harvard.edu/~pli/code/serialPHP.pm

kjh90 at orgio dot net (20-Mar-2002 08:43)

If you want to put serialized data into DB, you have to add slashes.
At this point, there's a problem. If you got data via HTTP POST method, the data has slashes already. I tried to work with "array_walk" or "array_map", but it doesn't work when the data has array.
So make extended stripslashes function.

<?php
function my_stripslashes($vals) {
    if (
is_array($vals)) {
        foreach (
$vals as $key=>$val) {
           
$vals[$key]=my_stripslashes($val);
        }
    } else {
       
$vals = stripslashes($vals);
    }
    return
$vals;
}

$data = addslashes(serialize($_POST));
...
$SQL="insert into DB() values($data)";
...
$SQL="select data from DB";
...
$data = my_stripslashes($data);
...
?>

(18-Jul-2001 02:39)

BEWARE: if you serialize to store values on a database, and the variables you are serializing already have the " (double-quote) char, you may have a problem. After serializing you will have var delimiters as " and content " (double-quotes) escaped, but your databse may just treat them like the same. You end up with a failed unserialize. You want something like:

a:5:{s:9:"this is a \"quote\"";a:1:{s:(ETC)

And not:
a:5:{s:9:"this is a "quote"";a:1:{s:(ETC)

So just make sure you double escape content quotes ...

It's simple, but i can't explain it any simpler =(

scott (at) hurring.com (12-Jul-2001 10:44)

I have written a perl module that does the same thing as PHP's serialize() and unserialize() commands so that Perl can now serialize and unserialize data in the same format as PHP.

It's quite handy for storing information in databases or files (or anywhere, really) that both PHP and Perl scripts need to read from and write to.

It supports string, double, integer, and array types (no object or reference support).

It's free code, too. :)

URL: http://hurring.com/code/perl/serialize/

sbarnum at mac dot com (25-May-2001 03:53)

If you're having trouble with serialized strings, try this function.  Pass it the name of an array whose value you want to include in hidden form inputs, a url, or session variable.  Works with strings or multidimensional arrays.

<?php
   
//////////////////////////////////////////////
    // propogate v0.8 by sbarnum
    // method can be 'form' or 'url' or 'session'
    //////////////////////////////////////////////
function propogate ($arrayName, $method='form', $arrayData=''){
    if(
$arrayData){
       
// custom values passed to array, use these instead of globals
       
${$arrayName} = $arrayData;
    }else{
       
// use global values
       
global ${$arrayName};
    }
    if (
$method == "session"){
       
session_register(${$arrayName});
        return
TRUE;
    }

    @
reset(${$arrayName});
    while (list(
$key,$value)=@each(${$arrayName})){
        if (
is_array($value)){
           
$subArrayName = $arrayName . "[" . $key . "]";
           
$html .= propogate ($subArrayName, $method, $value);
        }else{
            switch (
$method){
                case
"form":
               
$html .= "<INPUT type='hidden' name='".$arrayName."[".$key."]' value='".htmlspecialchars($value)."'>\n";
                break;
                case
"url":
               
$html .= "&".$arrayName."[".$key."]=" . urlencode($value);
                break;
            }
        }
    }
    return
$html;
}
?>

MarkRoedel at letu dot edu (22-Feb-2000 06:58)

A call to serialize() appears to mess with the array's internal pointer.  If you're going to be walking through your array after serializing it, you'll want to make a call to reset() first.