> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Eloquent 序列化

> 說明如何將 Eloquent 模型轉為 JSON 或陣列，控制屬性顯示與隱藏、設定追加屬性以及自訂日期格式。

## 簡介

在 Laravel 建置 API 時，經常需要將模型與其關聯轉為陣列或 JSON。
Eloquent 提供便利的方法來執行這類轉換，並可控制哪些屬性會出現在序列化後的表示中。

<Info>
  關於 Eloquent 模型與集合更健全的 JSON 序列化方式，請參閱 [Eloquent API 資源](./eloquent-resources)文件。
</Info>

## 模型與陣列

### 序列化為陣列

要將模型與已載入的[關聯](/zh-TW/eloquent-relationships)轉成陣列，可使用 `toArray` 方法。
此方法會遞迴運作，將所有屬性與所有關聯（包含關聯內的關聯）皆轉為陣列。

```php theme={null}
use App\Models\User;

$user = User::with('roles')->first();

return $user->toArray();
```

`attributesToArray` 方法可只將模型的屬性轉為陣列，不包含關聯。

```php theme={null}
$user = User::first();

return $user->attributesToArray();
```

要將整個模型集合轉為陣列，可對集合實例呼叫 `toArray`。

```php theme={null}
$users = User::all();

return $users->toArray();
```

### 序列化為 JSON

要將模型轉為 JSON，使用 `toJson` 方法。
`toJson` 也會遞迴運作，將所有屬性與關聯轉為 JSON。
你也可以指定 [PHP 支援的 JSON 編碼選項](https://www.php.net/manual/en/function.json-encode.php)。

```php theme={null}
use App\Models\User;

$user = User::find(1);

return $user->toJson();

return $user->toJson(JSON_PRETTY_PRINT);
```

也可以把模型或集合轉為字串，此時會自動呼叫 `toJson`。

```php theme={null}
return (string) User::find(1);
```

由於模型與集合在被轉為字串時會自動變成 JSON，你可以直接在路由或控制器中回傳 Eloquent 物件。
Laravel 會自動將路由或控制器回傳的 Eloquent 模型與集合序列化為 JSON。

```php theme={null}
Route::get('/users', function () {
    return User::all();
});
```

#### 關聯

當 Eloquent 模型被轉為 JSON 時，已載入的關聯會自動作為 JSON 物件的屬性包含在內。
Eloquent 的關聯方法名以「駝峰式」定義，但 JSON 屬性會用「蛇底式」。

## 屬性顯示控制

### 隱藏屬性

有時你想限制模型陣列 / JSON 表示中的某些屬性（例如密碼）。
可為模型使用 `Hidden` 屬性。列在 `Hidden` 中的屬性不會出現於模型的序列化表示。

```php theme={null}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Model;

#[Hidden(['password'])]
class User extends Model
{
    // ...
}
```

<Info>
  要隱藏關聯，只要把關聯方法名稱加入 Eloquent 模型的 Hidden 屬性中即可。
</Info>

### 公開屬性

也可以使用 `Visible` 屬性定義模型陣列 / JSON 表示應包含的屬性「白名單」。
不在 `Visible` 屬性中的所有屬性，在模型被轉為陣列或 JSON 時將被隱藏。

```php theme={null}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Attributes\Visible;
use Illuminate\Database\Eloquent\Model;

#[Visible(['first_name', 'last_name'])]
class User extends Model
{
    // ...
}
```

### 屬性的暫時顯示 / 隱藏

若要為特定的模型實例顯示原本隱藏的屬性，可用 `makeVisible` 或 `mergeVisible`。
`makeVisible` 會回傳模型實例本身。

```php theme={null}
return $user->makeVisible('attribute')->toArray();

return $user->mergeVisible(['name', 'email'])->toArray();
```

反之，若要隱藏原本顯示的屬性，可用 `makeHidden` 或 `mergeHidden`。

```php theme={null}
return $user->makeHidden('attribute')->toArray();

return $user->mergeHidden(['name', 'email'])->toArray();
```

若要暫時完全覆蓋顯示 / 隱藏屬性，可使用 `setVisible` 或 `setHidden`。

```php theme={null}
return $user->setVisible(['id', 'name'])->toArray();

return $user->setHidden(['email', 'password', 'remember_token'])->toArray();
```

## 追加屬性

在將模型轉為陣列或 JSON 時，有時想加入資料庫中不存在對應欄位的屬性。
為此，請先定義該值的[存取器](/zh-TW/eloquent-mutators)。

```php theme={null}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 判斷使用者是否為管理員。
     */
    protected function isAdmin(): Attribute
    {
        return new Attribute(
            get: fn () => 'yes',
        );
    }
}
```

若希望存取器始終出現在模型的陣列與 JSON 表示中，可為模型使用 `Appends` 屬性。
存取器的 PHP 方法以「駝峰式」定義，但屬性名通常會用「蛇底式」在序列化中呈現。

```php theme={null}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Attributes\Appends;
use Illuminate\Database\Eloquent\Model;

#[Appends(['is_admin'])]
class User extends Model
{
    // ...
}
```

屬性一旦加入 `appends` 清單，就會同時出現在模型的陣列與 JSON 表示中。
`appends` 陣列中的屬性也會遵守模型設定的 `visible` 與 `hidden`。

### 執行期加入

在執行期，可用 `append` 或 `mergeAppends` 指示模型實例加入額外屬性。
也能透過 `setAppends` 完全覆寫特定模型實例的追加屬性陣列。

```php theme={null}
return $user->append('is_admin')->toArray();

return $user->mergeAppends(['is_admin', 'status'])->toArray();

return $user->setAppends(['is_admin'])->toArray();
```

若要移除所有已加入的屬性，可使用 `withoutAppends` 方法。

```php theme={null}
return $user->withoutAppends()->toArray();
```

## 日期序列化

### 自訂預設日期格式

透過覆寫 `serializeDate` 方法，可自訂預設的序列化格式。
此方法不會影響儲存到資料庫的日期格式。

```php theme={null}
/**
 * 將日期準備為陣列 / JSON 序列化格式。
 */
protected function serializeDate(DateTimeInterface $date): string
{
    return $date->format('Y-m-d');
}
```

### 逐屬性自訂日期格式

可在模型的[轉換宣告](/zh-TW/eloquent-mutators#屬性轉換)中指定日期格式，來自訂個別 Eloquent 日期屬性的序列化格式。

```php theme={null}
protected function casts(): array
{
    return [
        'birthday' => 'date:Y-m-d',
        'joined_at' => 'datetime:Y-m-d H:00',
    ];
}
```


## Related topics

- [從 Laravel 12 升級到 13 指南](/zh-TW/blog/upgrade-12-to-13.md)
- [Redis](/zh-TW/redis.md)
- [Laravel 13 新功能彙總](/zh-TW/blog/laravel-13-new-features.md)
- [Eloquent 集合](/zh-TW/eloquent-collections.md)
- [Eloquent 存取器、修改器與型別轉換（Casts）](/zh-TW/eloquent-mutators.md)
