欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP serialize進(jìn)行序列化工作的完全指南

 更新時間:2025年09月12日 09:54:58   作者:JaguarJack  
本文會介紹什么是序列化以及工作原理,然后會說明如何使用 PHP 的內(nèi)置序列化函數(shù),讓你能在應(yīng)用中序列化和反序列化數(shù)據(jù),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下

介紹

如果你和我一樣,第一次在 PHP 中看到序列化字符串時會覺得很困惑。我當(dāng)時在做一個 Laravel 項目,想搞清楚將任務(wù)推送到隊列時到底發(fā)生了什么。我發(fā)現(xiàn)一些數(shù)據(jù)被序列化了,但不知道為什么以及怎么工作的。不過在我花時間研究序列化后,發(fā)現(xiàn)它其實沒那么復(fù)雜。

本文會介紹什么是序列化以及工作原理。然后會說明如何使用 PHP 的內(nèi)置序列化函數(shù),讓你能在應(yīng)用中序列化和反序列化數(shù)據(jù)。最后會講如何編寫測試來確保序列化代碼正常工作。

讀完這篇文章,你應(yīng)該能理解什么是序列化,并且能放心地在項目中使用。

什么是序列化

序列化就是把變量、對象或數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換成字符串格式的過程。這種字符串格式能表示原始數(shù)據(jù),方便存儲或傳輸。反過來,反序列化(在 PHP 中通常叫"unserialization")就是把序列化的數(shù)據(jù)轉(zhuǎn)換回原來的形式。

序列化很重要,常用于把數(shù)據(jù)存儲到緩存、數(shù)據(jù)庫或文件中。

數(shù)據(jù)可以序列化成很多格式,比如 JSON、XML,甚至二進(jìn)制格式(比如 gRPC API 用的 Protocol Buffers)。不過這篇文章主要講 PHP 的內(nèi)置序列化函數(shù)。

舉個例子,如果你用過 Laravel,應(yīng)該注意到這個框架在把任務(wù)推送到隊列時會序列化數(shù)據(jù)。比如下面這個 Laravel 中被推到隊列的待處理任務(wù)(為了好看,分了行并去掉了一些屬性):

{
    "uuid": "3d05be68-8cd0-4c3a-8d05-71e86871713a",
    "data": {
        "commandName": "App\\Jobs\\SendOneTimePassword",
        "command": "O:28:\"App\\Jobs\\SendOneTimePassword\"
              :1:{s:15:\"oneTimePassword\";s:6:\"123456\";}"
    }
}

在這個待處理任務(wù)的 JSON 例子中,data.command 屬性是個序列化字符串,代表一個 App\Jobs\SendOneTimePassword 任務(wù)。隊列工作器拿到這個任務(wù)時,會把序列化字符串反序列化,創(chuàng)建 App\Jobs\SendOneTimePassword 類的實例來處理。如果現(xiàn)在看不懂也沒關(guān)系,后面會有更多例子來解釋。

PHP 中的序列化如何工作

PHP 中可以用 serializeunserialize 函數(shù)來序列化和反序列化數(shù)據(jù)。

serialize 函數(shù)接受要序列化的數(shù)據(jù),返回字符串格式。unserialize 函數(shù)接受序列化的數(shù)據(jù),返回原來的數(shù)據(jù)結(jié)構(gòu)。

看看怎么在 PHP 中序列化和反序列化不同類型的數(shù)據(jù):

序列化字符串

序列化字符串很簡單,直接傳給 serialize 函數(shù):

$serialized = serialize('Hello');

這將返回一個序列化字符串:

s:5:"Hello";

這乍看起來有點奇怪,但一旦你注意到模式,你會發(fā)現(xiàn)它并不像看起來那么可怕。我們的序列化數(shù)據(jù)遵循格式:data_type:string_length:string;。

所以在上面序列化字符串的情況下,s 代表字符串并表示反序列化數(shù)據(jù)時的數(shù)據(jù)類型,5 是字符串的長度。

然后我們可以將該序列化字符串傳遞給 unserialize 函數(shù)以獲取原始字符串:

$string = unserialize('s:5:"Hello";');

序列化整數(shù)和浮點數(shù)

我們也可以在 PHP 中序列化整數(shù)和浮點數(shù)。以下是序列化整數(shù)的方法:

serialize(123);

這將返回一個序列化字符串:

i:123;

你可能已經(jīng)注意到結(jié)構(gòu)與我們之前看到的序列化字符串略有不同。整數(shù)使用格式 data_type:data; 進(jìn)行序列化。注意這里我們沒有像字符串那樣的大小。在這種情況下,序列化數(shù)據(jù)的數(shù)據(jù)類型是 i 表示整數(shù)。

同樣,我們可以序列化浮點數(shù):

serialize(123.45);

這將返回一個序列化字符串:

d:123.45;

這個結(jié)構(gòu)類似于整數(shù)序列化,但數(shù)據(jù)類型是 d 表示雙精度浮點數(shù)。

序列化布爾值

我們也可以在 PHP 中序列化布爾值。例如,我們可以序列化 true

serialize(true);

這將返回一個序列化字符串,其中 b 作為數(shù)據(jù)類型,1(表示 true)作為值:

b:1;

同樣,我們可以序列化 false

serialize(false);

這將返回一個序列化字符串,其中 b 作為數(shù)據(jù)類型,0(表示 false)作為值:

"b:0;"

序列化數(shù)組

我們可以這樣在 PHP 中序列化數(shù)組:

serialize([1,2,3]);

這將返回一個序列化字符串:

a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}

現(xiàn)在,你可能已經(jīng)注意到這比我們已經(jīng)看過的其他序列化數(shù)據(jù)要復(fù)雜一些。讓我們分解一下。

字符串具有 data_type:size:{key_data_type:key_data;value_data_type:value_data;...} 的結(jié)構(gòu)。在這種情況下,data_typea 表示數(shù)組,size3,因為數(shù)組有 3 個元素。

如果我們?nèi)缓蟛榭?{ } 內(nèi)的數(shù)據(jù),我們可以看到鍵由 i 表示整數(shù),值也由 i 表示整數(shù)。通過將它們分成新行來可視化結(jié)構(gòu)可能會有所幫助:

i:0;i:1;
i:1;i:2;
i:2;i:3;

作為另一個例子,讓我們看看序列化的字符串?dāng)?shù)組可能是什么樣子。我們可以序列化以下數(shù)組:

serialize(['a','b','c']);

這將返回一個序列化字符串:

a:3:{i:0;s:1:"a";i:1;s:1:"b";i:2;s:1:"c";}

正如我們在上面的序列化字符串中看到的,鍵仍然由 i 表示,而值由 s 表示字符串。為了幫助可視化結(jié)構(gòu),我們可以將數(shù)據(jù)分成新行:

i:0;s:1:"a";
i:1;s:1:"b";
i:2;s:1:"c";

同樣,我們也可以序列化關(guān)聯(lián)數(shù)組:

serialize(['a' => 'A', 'b' => 'B', 'c' => 'C']);

這將返回一個序列化字符串:

a:3:{s:1:"a";s:1:"A";s:1:"b";s:1:"B";s:1:"c";s:1:"C";}

正如我們所看到的,結(jié)構(gòu)與我們已經(jīng)看過的序列化數(shù)組非常相似。但是,在這種情況下,鍵由 s 表示字符串。為了幫助可視化結(jié)構(gòu),我們可以將數(shù)據(jù)分成新行:

s:1:"a";s:1:"A";
s:1:"b";s:1:"B";
s:1:"c";s:1:"C";

序列化枚舉

我們也可以在 PHP 中序列化枚舉。作為一個基本示例,假設(shè)我們有以下表示博客文章狀態(tài)的枚舉:

namespace App\Enums;

enum PostStatus: string
{
    case Published = 'published';
    case Draft = 'draft';
    case Pending = 'in_review';
}

讓我們想象然后創(chuàng)建此枚舉的新實例并像這樣序列化它:

serialize(PostStatus::Published);

這將返回一個序列化字符串:

E:30:"App\Enums\PostStatus:Published";

序列化枚舉的結(jié)構(gòu)是 data_type:size:"enum_type:enum_value";。在這種情況下,數(shù)據(jù)類型由 E 表示,大小是 30,因為類名是 App\Enums\PostStatus,枚舉值是 Published

序列化對象

到目前為止,我們已經(jīng)介紹了序列化如何適用于基本數(shù)據(jù)類型,如字符串、整數(shù)、浮點數(shù)、布爾值、數(shù)組和枚舉。但是對象呢?

默認(rèn)情況下,除了少數(shù)內(nèi)置 PHP 類之外,所有對象都是可序列化的。

為了解釋對象序列化的工作原理,讓我們以一個基本的 App\User 類為例,它包含三個公共屬性:

namespace App;

class User
{
    public function __construct(
        public string $name,
        public string $email,
        public string $apiToken,
    ) { }
}

我們將創(chuàng)建此類的新實例并序列化它:

$user = new User(
    name: 'Ash Allen',
    email: 'mail@ashallendesign.co.uk',
    apiToken: 'secret',
);

serialize($user);

這將返回一個序列化字符串:

O:8:"App\User":3:{s:4:"name";s:9:"Ash Allen";s:5:"email";s:
25:"mail@ashallendesign.co.uk";s:8:"apiToken";s:6:"secret";}
 

讓我們分解序列化對象的結(jié)構(gòu)。我們有以下結(jié)構(gòu):

data_type:class_name_size:class_name:property_count:{
    property_name_type:property_name_size:property_name;
    property_value_type:property_value_size:property_value;
    ...
}

因此,從這個結(jié)構(gòu)中,我們可以看到數(shù)據(jù)類型是 O 表示對象,類名大小是 8,類名是 App\User,屬性計數(shù)是 3,因為對象有 3 個屬性。然后我們可以看到 { } 內(nèi)的每個序列化屬性。

然后我們可以將此序列化字符串傳遞給 unserialize 函數(shù)以獲取原始對象:

$serialized = 'O:8:"App\User":3:{s:4:"name";s:9:"Ash Allen'
    .'";s:5:"email";s:25:"mail@ashallendesign.co.uk";s:8:'
    .'"apiToken";s:6:"secret";}';

$user = unserialize($serialized);

這將返回 App\User 類的實例,每個屬性都像原始對象一樣設(shè)置。

屬性可見性

序列化對象時,屬性的可見性很重要,因為它會影響返回的字符串。

讓我們更新我們的 App\User 類以具有公共、受保護(hù)和私有屬性:

namespace App;

class User
{
    public function __construct(
        public string $name,
        protected string $email,
        private string $apiToken,
    ) { }
}

然后我們將創(chuàng)建此類的新實例并序列化它:

$user = new User(
    name: 'Ash Allen',
    email: 'mail@ashallendesign.co.uk',
    apiToken: 'secret',
);

serialize($user);

這將返回一個序列化字符串:

O:8:"App\User":3:{s:4:"name";s:9:"Ash Allen";s:8:
"\0*\0email";s:25:"mail@ashallendesign.co.uk";s:18:
"\0App\User\0apiToken";s:6:"secret";}

字符串格式與我們之前的序列化對象非常相似。但是,emailapiToken 屬性的名稱略有不同。

當(dāng) PHP 序列化對象時,它將為屬性名添加前綴以指示屬性的可見性。受保護(hù)的屬性由 * 前綴指示,私有屬性由類名前綴指示。所以我們可以看到,我們有 \0*\0email\0App\User\0apiToken\0 表示空字節(jié)),而不是 emailapiToken。

讓我們將序列化字符串分成新行以幫助可視化結(jié)構(gòu):

s:4:"name";s:9:"Ash Allen";
s:8:"\0*\0email";s:25:mail@ashallendesign.co.uk"
s:18:"\0App\User\0apiToken";

這意味著通過查看序列化對象,我們可以確定屬性的可見性。

序列化包含其他對象的對象

有時你可能需要序列化包含另一個對象的對象。我們將快速看一下包含另一個對象的序列化對象可能是什么樣子。

假設(shè)我們有一個簡單的 App\ValueObjects\Address 類:

namespace App\ValueObjects;

class Address
{
    public function __construct(
        public int $number,
        public string $postalCode,
    ) { }
}

然后我們假設(shè)我們的 App\User 類有一個 App\ValueObjects\Address 對象作為屬性。我們可能想要創(chuàng)建一個新對象并序列化它:

$user = new User(
    name: 'Ash Allen',
    email: 'mail@ashallendesign.co.uk',
    apiToken: 'secret',
    address: new Address('18', 'SW1A 2AA'),
);

serialize($user);

這將導(dǎo)致如下序列化字符串:

O:8:"App\User":4:{s:4:"name";s:9:"Ash Allen";s:5:"email";
s:25:"mail@ashallendesign.co.uk";s:8:"apiToken";s:6:
"secret";s:7:"address";O:24:"App\ValueObjects\Address":2:
{s:6:"number";i:18;s:10:"postalCode";s:8:"SW1A 2AA";}}

讓我們將此對象的內(nèi)容分解到單獨的行上:

s:4:"name";s:9:"Ash Allen";
s:5:"email";s:25:"mail@ashallendesign.co.uk";
s:8:"apiToken";s:6:"secret";
s:7:"address";O:24:"App\ValueObjects\Address":2:{
    s:6:"number";i:18;
    s:10:"postalCode";s:8:"SW1A 2AA";
}

正如我們在這里看到的,App\ValueObjects\Address 對象只是作為 App\User 對象的屬性序列化。

反序列化時的錯誤處理

處理嘗試反序列化無效數(shù)據(jù)時可能發(fā)生的任何錯誤很重要。根據(jù)你嘗試反序列化的無效數(shù)據(jù),PHP 8.3 將發(fā)出 E_WARNING 或拋出 \Exception\Error

例如,讓我們看看這個無效的序列化字符串,它對字符串 hello 的長度為 10 而不是預(yù)期的 5:

unserialize('s:10:"hello";');

如果我們在 PHP 8.3 中運行此代碼,將發(fā)出 E_WARNING,錯誤消息如下:

Warning: unserialize(): Error at offset 2 of 13 bytes in
/www/serialization.php on line 3

為了處理警告以便我們可以在代碼中捕獲和處理它們,我們可以使用 set_error_handler 函數(shù)設(shè)置自定義錯誤處理程序。這將允許我們捕獲警告并將它們作為異常拋出。

為此,我們首先創(chuàng)建一個新的 App\Services\Serializer 類,如下所示:

declare(strict_types=1);

namespace App\Services;

final readonly class Serializer
{
    public function unserialize(string $serialized): mixed
    {
        try {
            set_error_handler(static function (
                $severity, $message, $file, $line
            ) {
                throw new \ErrorException(
                    $message, 0, $severity, $file, $line
                );
            });

            $result = unserialize($serialized);
        } finally {
            restore_error_handler();
        }

        return $result;
    }
}

在此類中,我們添加了一個接受序列化字符串的 unserialize 方法。然后我們覆蓋錯誤處理程序,以便我們可以捕獲任何警告并將它們作為異常拋出。然后我們嘗試反序列化數(shù)據(jù)。如果發(fā)出警告,它將作為異常拋出。然后我們在 finally 塊內(nèi)將錯誤處理程序恢復(fù)到其原始狀態(tài),無論反序列化是否成功都會運行。假設(shè)成功,我們?nèi)缓蠓祷胤葱蛄谢臄?shù)據(jù)。

然后我們可以使用此類來反序列化數(shù)據(jù):

use App\Services\Serializer;

$result = (new Serializer())->unserialize(
    serialized: 's:10:"hello";'
);

運行上述代碼將導(dǎo)致拋出 \ErrorException,消息如下:

unserialize(): Error at offset 2 of 13 bytes

或者我們可以運行以下代碼:

use App\Services\Serializer;

$result = (new Serializer())->unserialize(
    serialized: 's:5:"hello";'
);

這將導(dǎo)致返回字符串 hello。

目前有一個 RFC部分實現(xiàn),旨在改進(jìn)反序列化數(shù)據(jù)時的錯誤處理。RFC 包含一個提案,從 PHP 9.0 開始,改變 unserialize 的行為,使其拋出 \UnserializationFailedException 而不是發(fā)出 E_WARNING。因此,如果實現(xiàn)了這一點,我們不需要覆蓋錯誤處理程序來捕獲警告并將它們作為異常拋出,就像我們上面所做的那樣。

在 PHP 中定義序列化邏輯

正如我們在上面已經(jīng)看到的,PHP 默認(rèn)提供序列化和反序列化對象的能力。

但是,有時你可能想要為對象定義自定義序列化邏輯。這可能有幾個原因,例如在序列化之前加密敏感數(shù)據(jù),或者你可能需要在反序列化對象時執(zhí)行一些額外的邏輯。

值得慶幸的是,PHP 提供了兩個魔術(shù)方法,你可以使用它們來定義如何序列化和反序列化對象:__serialize__unserialize

為了了解這可能如何工作,讓我們看一個例子。堅持我們之前的 App\User 類,假設(shè)我們想要在序列化對象之前加密 apiToken 屬性,并在反序列化對象時解密它。這可能是因為我們將序列化數(shù)據(jù)存儲在緩存或隊列中,所以我們想要確保數(shù)據(jù)在受到威脅時是安全的。

為了本文的目的,我們將假設(shè)我們有兩個可以調(diào)用來加密和解密數(shù)據(jù)的函數(shù):encryptdecrypt。我們現(xiàn)在不需要擔(dān)心這些函數(shù)的實現(xiàn),我們只是假設(shè)它們存在。如果你們中的任何人是 Laravel 開發(fā)者,你們可能會認(rèn)識這些函數(shù),因為它們都隨 Laravel 一起提供。

讓我們更新我們的 App\User 類以包含 __serialize__unserialize 方法,然后討論正在做什么:

declare(strict_types=1);

namespace App;

class User
{
    public function __construct(
        public string $name,
        public string $email,
        public string $apiToken,
    ) { }

    public function __serialize(): array
    {
        return [
            'name' => $this->name,
            'email' => $this->email,
            'apiToken' => encrypt($this->apiToken),
        ];
    }

    public function __unserialize(array $data): void
    {
        $this->name = $data['name'];
        $this->email = $data['email'];
        $this->apiToken = decrypt($data['apiToken']);
    }
}

__serialize 方法中,我們返回要序列化的屬性數(shù)組。我們在返回之前加密 apiToken 屬性。這意味著當(dāng)我們對對象調(diào)用 serialize 時,apiToken 屬性將被加密。

讓我們創(chuàng)建 App\User 類的新實例并序列化它:

$user = new User(
    name: 'Ash Allen',
    email: 'mail@ashallendesign.co.uk',
    apiToken: 'secret',
);

$serialized = serialize($user);

序列化字符串可能如下所示(為簡潔起見縮短了加密字符串):

O:8:"App\User":3:{s:4:"name";s:9:"Ash Allen";s:5:"email";s:
25:"mail@ashallendesign.co.uk";s:8:"apiToken";s:200:
"eyJpdiI6Ikx0N3BDQwYzcwMzE1NGQy...sdfsfsfdssInRhZyI6IiJ9";}

正如我們所看到的,apiToken 屬性現(xiàn)在已加密,沒有加密密鑰就無法解密數(shù)據(jù)。

現(xiàn)在,如果我們想從序列化字符串創(chuàng)建 App\User 類的實例,我們可以對字符串調(diào)用 unserialize,將調(diào)用 __unserialize 方法。此 __unserialize 方法接受序列化數(shù)據(jù)的數(shù)組,因此我們可以分配每個屬性并解密 apiToken 屬性。

測試你的序列化代碼

就像應(yīng)用程序的任何其他部分一樣,如果你正在自定義對象的序列化和反序列化方式,你可能會想要為序列化邏輯編寫測試。這是確保你的序列化代碼按預(yù)期工作并且你可以捕獲任何錯誤的好方法。

例如,讓我們看看我們剛剛看過的前面的例子。如果我們意外地從 apiToken 屬性的 __unserialize() 函數(shù)中刪除了 decrypt() 函數(shù)調(diào)用,會發(fā)生什么?這將導(dǎo)致我們擁有一個具有加密令牌而不是我們期望的原始未加密值的對象。

你的測試可以根據(jù)你的喜好進(jìn)行深入和嚴(yán)格。讓我們看看我們可以編寫的一個簡單測試,以確保 App\User 對象可以被序列化然后反序列化:

declare(strict_types=1);

namespace Tests\Feature\User;

use App\User;
use Illuminate\Foundation\Testing\TestCase;
use PHPUnit\Framework\Attributes\Test;

final class SerializeTest extends TestCase
{
    // ...

    #[Test]
    public function serialize_and_unserialize_works(): void
    {
        $user = new User(
            name: 'Ash Allen',
            email: 'mail@ashallendesign.co.uk',
            apiToken: '1234567890',
        );

        $serialized = serialize($user);

        $unserializedUser = unserialize($serialized);

        // 斷言我們剛剛構(gòu)建的用戶與我們最初序列化的用戶相同。
        $this->assertEquals($user, $unserializedUser);
    }
}

在上面的測試中,我們創(chuàng)建了 App\User 的實例,序列化它,然后反序列化它。然后我們斷言我們剛剛構(gòu)建的用戶與我們最初序列化的用戶相同。這是一個簡單的測試,可以讓我們確信我們的序列化代碼按預(yù)期工作。

但是,如果我們刪除 encryptdecrypt 函數(shù)調(diào)用,測試仍然會通過,即使我們可能沒有像預(yù)期的那樣加密和解密 apiToken 屬性。

如果你更喜歡對測試更嚴(yán)格一些,你可以編寫兩個更多的測試來確保 apiToken 屬性按預(yù)期被加密和解密。

我們將編寫測試,就像它們是 Laravel 應(yīng)用程序的一部分,并且 encryptdecrypt 函數(shù)只是使用 encrypter 鍵從服務(wù)容器解析 Illuminate\Contracts\Encryption\Encrypter 接口的實例。但是如果你不熟悉 Laravel,這并不重要。你只需要知道我們正在模擬 encryptdecrypt 函數(shù)調(diào)用的底層類,這樣我們就可以在測試中硬編碼預(yù)期的加密值并對其進(jìn)行斷言。

我們要編寫的第一個測試是確保在序列化用戶對象時 apiToken 屬性被加密:

declare(strict_types=1);

namespace Tests\Feature\User;

use App\User;
use Illuminate\Foundation\Testing\TestCase;
use Mockery\MockInterface;
use PHPUnit\Framework\Attributes\Test;

final class SerializeTest extends TestCase
{
    // ...

    #[Test]
    public function user_object_can_be_serialized(): void
    {
        // 模擬加密器,這樣我們就可以嚴(yán)格測試用戶對象的序列化。
        $this->mock('encrypter', function ($mock): void {
            $mock->shouldReceive('encrypt')
                ->once()
                ->withArgs(['1234567890', true])
                ->andReturn('encrypted');
        });

        $user = new User(
            name: 'Ash Allen',
            email: 'mail@ashallendesign.co.uk',
            apiToken: '1234567890',
        );

        $serialized = serialize($user);

        $expectedString = 'O:8:"App\User":3:{s:4:"name";s:'.
            '9:"Ash Allen";s:5:"email";s:25:"'.
            'mail@ashallendesign.co.uk";s:8:"apiToken";s:'.
            '9:"encrypted";}';

        // 斷言序列化字符串正是我們期望的。
        $this->assertSame(
            expected: $expectedString,
            actual: $serialized,
        );
    }
}

在測試中,我們首先模擬加密器,這樣我們就可以在測試中硬編碼預(yù)期的加密值。在這種情況下,我們期望 apiToken 屬性的值為 1234567890,當(dāng)加密它時,我們將返回字符串 encrypted。然后我們創(chuàng)建 App\User 類的新實例并序列化它。然后我們斷言序列化字符串正是我們期望的。

然后我們可以編寫另一個測試來確保在反序列化用戶對象時 apiToken 屬性被解密:

declare(strict_types=1);

namespace Tests\Feature\User;

use App\User;
use Illuminate\Foundation\Testing\TestCase;
use Mockery\MockInterface;
use PHPUnit\Framework\Attributes\Test;

final class SerializeTest extends TestCase
{
    // ...

    #[Test]
    public function user_string_can_be_unserialized(): void
    {
        // 模擬加密器,這樣我們就可以嚴(yán)格測試用戶對象的序列化。
        $this->mock('encrypter', function ($mock): void {
            $mock->shouldReceive('decrypt')
                ->once()
                ->withArgs(['encrypted', true])
                ->andReturn('1234567890');
        });

        $serialized = 'O:8:"App\User":3:{s:4:"name";s:9:"'.
            'Ash Allen";s:5:"email";s:25:"'.
            'mail@ashallendesign.co.uk";s:8:"apiToken";s:'.
            '9:"encrypted";}';

        $user = unserialize($serialized);

        $this->assertInstanceOf(User::class, $user);
        $this->assertSame('Ash Allen', $user->name);
        $this->assertSame(
            'mail@ashallendesign.co.uk',
            $user->email
        );
        $this->assertSame('1234567890', $user->apiToken);
    }
}

在上面的測試中,我們模擬了加密器,這樣我們就可以在測試中硬編碼預(yù)期的解密值。然后我們反序列化序列化字符串并斷言用戶對象是 App\User 的實例,并且屬性符合我們的預(yù)期。

結(jié)論

在本文中,我們了解了什么是序列化以及它是如何工作的。我們探索了如何使用 PHP 的內(nèi)置序列化函數(shù)在 PHP 應(yīng)用程序中序列化和反序列化數(shù)據(jù)。我們還討論了如何編寫測試來確保你的序列化代碼按預(yù)期工作。

到此這篇關(guān)于PHP serialize進(jìn)行序列化工作的完全指南的文章就介紹到這了,更多相關(guān)PHP serialize序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論