I would like to know, for example, where I would apply this function in a real scenario?
Jobs
I use a lot to create Jobs, particularly an implementation of Laravel.
It basically works like this: You serialize an instance of a class that will perform a specific action and save it to the database. Then you deserialize this class and call a method specific to that class through the command line.
Session
In addition, PHP natively uses serialize to save the data stored in the variable $_SESSION
, and unserialize
when you will recover this data.
See what the little code below does:
session_save_path('tmp_sessions');
session_start();
$_SESSION['nome'] = 'Wallace';
Above I set that sessions will be saved inside the folder tmp_sessions
. After running the script, a file appears inside the folder tmp_sessions/sess_st3e3ksr5vjsj8h5rrm57u11l4
, with the following content:
nome|s:7:"Wallace";
What is the advantage of using serialize in relation to any variable?
I think part of this question was answered above, but it is natural to use serialize in cases where you need to recover this data later, so that PHP could recover it in the same state as it was created.
Important remarks
Serialization aims at storing data in formats that are interpreted by PHP for a future recovery. You should keep in mind that there are some restrictions regarding data serialization.
One of them is Closure
and also Classes Anonymous. Obviously these data cannot be serialized natively because they represent a temporary structure, which would make it very difficult to reconstruct these objects.
In cases where you need to implement serialization in a specific instance of an object, you may need to define how PHP will behave when you sort this object, in this case, or create the method __wakeup
and __sleep
or implementing the native interface Serializable
, who has the methods serialize
and unserialize
. These methods aim to "point" to PHP what will or will not be serialized from that object.
Let us take the example of JOB I mentioned earlier.
In the case below, consider that I am wanting to create a "worker" who will send the emails to me from the command line, so I don’t have to do this by http.
At HTTP:
interface Trabalho
{
public function trabalhar();
}
class EmailNotificacao implements Trabalho, Serializable
{
public function __construct($id)
{
$this->id = $id;
}
public function trabalhar()
{
$usuario = Usuario::find($this->id);
Email::texto('Enviando email para o usuário', $usuario->email);
}
public function serialize()
{
return serialize(['id' => $this->id]);
}
public function unserialize($data)
{
$properties = unserialize($data);
$this->id = $properties['id'];
}
}
$id = 1;
BancoDeDados::inserir('trabalhos', serialize(new EmailNotificacao($id)));
In the above case, this allows me to insert the instance of a serialized class into the database, because the serialization always returns a string
, which can easily be included in a column of the type TEXT
.
Now, a script that is running on your cronjob and has access to the same class settings as your http application will be able to retrieve the data through deserialization.
Behold:
// no script do cronjob
$trabalho = BancoDeDados::obterPrimeiro('trabalhos');
$trabalho_instancia = unserialize($trabalho['dado_serializado']);
if ($trabalho_instancia instanceof Trabalho)
{
$trabalho_instancia->trabalhar();
BancoDeDados::deletar($trabalho_instancia->id);
}
See a small example of the customisation of serializable
in the Ideone
Why then use two more steps (serialize/unserialize) for something that can be "treated" directly?
It is because you are thinking of the application in a single execution. In those cases, it really doesn’t make sense to serialize the data - unless it’s something very specific.
As I said, the purpose of serialization is to create a string containing a representation of a PHP data structure.
This can be very useful for you to save an object in a specific location to retrieve it later, as is done in the case of session.
If it weren’t for serialization, how could you save arrays
, strings
or even instances of certain objects in your application session?
Note that in the case of sessions you not only get the previously stored value, you get it in the same type. If you save a int
, you’ll always have the same int
on the new page call.
For you to understand better, the session works basically like this:
Create the script serialize.php
and then create a file session.txt
in the same empty folder.
Now add this to your script:
$file = 'session.txt';
// desserializa o conteúdo do arquivo
$_session = unserialize(file_get_contents($file));
// Se for false, é que o arquivo está vazio
if ($_session === false) {
// então definimos que queremos que a variável seja um array
$_session = [];
}
// mostra os dados da sessão
var_dump($_session);
$_session['nome'] = 'wallace';
if (! isset($_session['quantidade_execucao']))
{
$_session['quantidade_execucao'] = 0;
}
// adiciona uma contagem para cada vez que o script é executado
$_session['quantidade_execucao']++;
// salvas os dados serializados no arquivo
file_put_contents($file, serialize($_session));
Basically, this is how the session works, and it would not be to keep the states of the variables, as in the example above, if there were no serialization.
But why not use JSON, which is so popular?
The JSON
aims at communication between different languages or applications. The serialize
PHP serves only and exclusively for PHP.
Moreover, the json_encode
PHP, when it comes to objects, is a one-way street, as it is only able to determine how the data of an object (in the case of a specific class) will be serialized to JSON, but there is no option to do otherwise.
That is, the json_decode
could never reconstruct an object like ArrayObject
, for example. But serialize is able to handle it perfectly.
**Note: If you try to deserialize a serial that contains a nonexistent class on Sop, PHP will return an error, saying it cannot deserialize __php_incomplete_class.
It is always necessary, when working with class serialization, that it is included both where it serializes itself and where it is deserialized.
serialize does not do the magic of saving the source code of your class in it, it only stores the information needed to rebuild an instance. For this, it is necessary that the class exists!
Look at this question I asked about the subject:
This is more rarely required if you want to persist the object (in file, memory or database) and recover later. I mean, in cases where you can’t "go right through".
– bfavaretto
@bfavaretto didn’t even imagine it. Very interesting. (despite as said, in rare needs)
– rbz
Complementing and answering the last question (Why then use two more steps?). There are objects that use external resources (
resources
). Which may be database connection, stream, etc. These features cannot be persisted or automatically closed/opened. The fact of these two extra steps may be to close a resource (duringserialize
) and recreate the resource (duringunserialize
).– Gabriel Heming