UX / UI のデザインに強いWebシステムの開発と、BtoB Webマーケを支援するWeb制作を提供するN’s Creates (エヌズクリエイツ) 株式会社の西山です。
PHP、そしてLaravel開発において、私たちは毎日のように「連想配列」を使います。
['name' => 'John', 'email' => '...'] という形式は非常に手軽で、柔軟です。
しかし、プロジェクトが大きくなるにつれて、この便利さが牙を剥く瞬間があります。
ControllerからService、ServiceからJobへと、中身の不明な配列がバケツリレーされていく…いわゆる「闇鍋(やみなべ)」状態です。
今回は、この問題を解決するための設計パターン「DTO(Data Transfer Object)」について、コード比較を交えて解説します。
よくある光景:連想配列によるデータ受け渡し
まずは、DTOを使わない(連想配列を使った)一般的なコードを見てみましょう。
❌ 悪い例:中身がわからない「配列」
class UserService
{
/**
* ユーザー登録処理
* @param array $data ← ここが諸悪の根源
*/
public function register(array $data)
{
// $dataの中に何が入っているのか、コードを見ただけでは分からない
// 'email' キーが存在する保証はない(Undefined indexエラーのリスク)
$user = User::create([
'name' => $data['name'],
'email' => $data['email'], // ここでタイポしたら終わり
'role' => $data['role'] ?? 'member',
]);
// ... メール送信などの処理
}
}
このコードには、以下の3つの大きなデメリットがあります。
- 何が入っているか不明:
registerメソッドを使う人は、どんなキー(name?user_name?)を渡せばいいのか、中身を読んで解読する必要があります。 - 補完が効かない: IDE(エディタ)は
$data['...']の中身を知らないため、自動補完が効きません。タイポ(入力ミス)が実行時エラーになるまで発覚しません。 - 型の保証がない:
emailに文字列ではなく配列が渡されてきても、PHPは実行するまで気づけません。
✅ 良い例:DTOによる「型のある」受け渡し
DTOとは、単純に「データを運ぶためだけのクラス」のことです。
PHP 8.2以降なら、readonly クラスを使って非常にシンプルに書けます。
1. DTOクラスを作成
namespace App\DataTransferObjects;
use Illuminate\Http\Request;
readonly class UserRegistrationData
{
public string $name;
public string $email;
public string $role;
public function __construct(
string $name,
string $email,
string $role
) {
$this->name = $name;
$this->email = $email;
$this->role = $role;
}
// リクエストからDTOを作る静的メソッドを用意すると便利
public static function fromRequest(Request $request): self
{
// 実際には FormRequest の validated() データを使うのがベストですが、
// ここでは汎用的に input() を使用しています。
return new self(
name: $request->input('name'),
email: $request->input('email'),
role: $request->input('role') ?? 'member',
);
}
}
2. Service層でDTOを受け取る
class UserService
{
/**
* ユーザー登録処理
* @param UserRegistrationData $data ← 何が来るか明確!
*/
public function register(UserRegistrationData $data)
{
// IDEの補完がバリバリ効く
// プロパティが存在することが保証されている
$user = User::create([
'name' => $data->name,
'email' => $data->email,
'role' => $data->role,
]);
// ...
}
}
DTO導入のメリット・デメリット比較
配列とDTO、それぞれの特徴を表にまとめました。
| 比較項目 | 連想配列 (Array) | DTO (Object) |
|---|---|---|
| 実装コスト | 低い(書くだけ) | 中(クラス定義が必要) |
| IDE補完 | × 全く効かない | ◎ 完璧に効く |
| 可読性 | × 処理を追わないと不明 | ◎ 定義を見れば一目瞭然 |
| 安全性 | × キーの存在保証なし | ◎ 型と存在が保証される |
| リファクタリング | × 影響範囲が探せない | ◎ プロパティ名変更も容易 |
結論:いつDTOを使うべきか?
「たった数行のデータ受け渡し」であれば、連想配列でも問題ありません。
しかし、以下の条件に当てはまる場合は、迷わずDTOの導入をおすすめします。
- データが3層以上(Controller → Service → Job など)をまたいで移動する場合
- 配列のキー(
user_idなのかidなのか)を毎回確認している自分に気づいた時 - チーム開発で、他のメンバーが書いたメソッドを呼び出す場合
DTOは、開発者の認知負荷(脳のメモリ)を減らすための強力な武器です。
「配列地獄」から脱出し、型安全で快適なLaravelライフを送りましょう。
UX / UI のデザインに強いWebシステムの開発と、BtoB Webマーケを支援するWeb制作を提供する
N's Creates 株式会社は、神戸三宮オフィスまで週1出社(それ以外はリモートワーク)できる「デザイナー」「エンジニア」を募集しています。
興味のある方は、カジュアル面談しますので気軽にお問い合わせください!









