DomainModelを生成時に、値をvalidateして内容を担保していく方法を書いていきます。
流れは下記になります
validate → new DomainModel()
しかし、validate()
をせずにインスタンス生成してしまうことも可能ですよね
$publicArticle = new PublicArticle($title, $body)
// validateしなくてもインスタンス生成可能
そこで、インスタンス生成時にvalidate()処理を必須化させて、値を担保していきたいと思います。
DomainModelでvalidate()を必須化させる。
インスタンス生成処理をprivateにする。
まずインスタンス生成処理をpublicではなくprivateメソッドにします。
phpのインスタンス生成メソッドは__construct()
ですが、通常だとpublicで定義されています。
public function __construct(
string $title,
string $body,
)
{
$this->title = $title;
$this->body = $body;
}
public()
だとどこでもnew DomainModel()
でインスタンスを生成できてしまいます。
$publicArticle = new PublicArticle($title, $body)
// validateしなくてもインスタンス生成可能
なので、__construct()
をprivateメソッドにして、制限します。
private function __construct(
string $title,
string $body,
)
{
$this->title = $title;
$this->body = $body;
}
これにより、DomainModel内のメソッドでしかインスタンスを生成できません。
new PublicArticle($title, $body)
//エラー Call to private Domain\DomainModel\PublicArticel::__construct()
では続いて、代わりにインスタンスを生成するメソッドを作ります。
validate()が必須とするmake()を追加
ここでは、インスタンス生成処理をmake()
に限定させます。
make()
処理内でvalidate()
させてから、new self()
を実行させます。
/**
* インスタンス生成処理
*
* @param string $title タイトル
* @param string $body 本文
* @return self $this
*/
public static function make(string $title, string $body): self
{
$validated = self::validate($title, $body); // バリーでションした値を取得
// validationした値を元にインスタンスを生成
return new self(
$validated['title'],
$validated['body'],
);
}
これでインスタンス生成時は、必ずvalidate()
していることになります。
複数ある入り口を一つ絞ったので、当然validate()されているという考え方です。
validate()の中身を書いていく
では続いてvalidate()を作成していきましょう
/**
* バリデーション
*
* @param string $title タイトル
* @param string $body 本文
* @return array
*/
private static function validate (string $title, string $body): array
{
$values = [
'title' => $title,
'body' => $body,
];
$rules = [
'title' => ['required', 'string', 'max:50'],
'body' => ['required', 'string'],
];
$validator = Validator::make($values, $rules);
if ($validator->fails()) {
throw new Exception('お知らせ公開に必要な情報が不足しています。');
}
return $validator->validated();
}
これでvalidate()された値を渡されて安心ですね
全体像
下記3点をそろいました。
- privateでインスタンス生成:__construct()
- コンストラクトを実行してインスタンスを生成:make()
- バリデーション実施メソッド: validate()
このメソッドを使ってvalidate()をさせた値で無事にDomainModelを生成できましたね。
それでは最後に全体像を見ていきましょう!
<?php
namespace App\Packages\Article\Domain\DomainModel;
use Illuminate\Support\Facades\Validator;
/**
* 公開する記事
*/
class PublicArticle
{
/**
* タイトル
*
* @var string
*/
public string $title;
/**
* お知らせの本文
*
* @var string
*/
public string $body;
/**
* 公開日時
*
* @var CarbonImmutable
*/
public CarbonImmutable $published_at;
private function __construct(
string $title,
string $body,
CarbonImmutable $published_at,
)
{
$this->title = $title;
$this->body = $body;
$this->published_at = CarbonImmutable::now();
}
/**
* インスタンス生成処理
*
* @param string $title タイトル
* @param string $body 本文
* @return self $this
*/
public static function make(string $title, string $body): self
{
$validated = self::validate($title, $body);
return new self(
$validated['title'],
$validated['body'],
);
}
/**
* バリデーション
*
* @param string $title タイトル
* @param string $body 本文
* @return array
*/
private static function validate (string $title, string $body): array
{
$values = [
'title' => $title,
'body' => $body,
];
$rules = [
'title' => ['required', 'string', 'max:50'],
'body' => ['required', 'string'],
];
$validator = Validator::make($values, $rules);
if ($validator->fails()) {
throw new Exception('お知らせ公開に必要な情報が不足しています。');
}
return $validator->validated();
}
}
今回はvalidate()だけになりますが、もっと複雑なルールを取り入れてもいいと思います。
これで以上となります
最後まで読んでいただき、ありがとうございます😄
コメント