フレームワークへの依存度を下げるFLUDパターン (4)
フレームワークへの依存度を下げるFLUDパターン (3) の続きです。
CodeIgniter4のチュートリアルのコードをFLUDパターンに変更しています。
最後は、記事の作成です。
ドメイン層
NewsRepositoryInterface
NewsRepositoryInterface
にNewsを追加するメソッドを追加します。
--- a/packages/news/src/Domain/News/NewsRepositoryInterface.php
+++ b/packages/news/src/Domain/News/NewsRepositoryInterface.php
@@ -12,4 +12,6 @@ interface NewsRepositoryInterface
public function getNewsList(): array;
public function getNewsBySlug(string $slug): ?News;
+
+ public function addNews(News $news): void;
}
addNews()
メソッドは渡された News
をリポジトリに追加(保存)します。
ユースケース層
CreateNewsUseCase
News
を作成するユースケースを追加します。
packages/news/src/UseCase/News/CreateNewsUseCase.php
<?php
declare(strict_types=1);
namespace Acme\News\UseCase\News;
use Acme\News\Domain\News\News;
use Acme\News\Domain\News\NewsRepositoryInterface;
class CreateNewsUseCase
{
/**
* @var NewsRepositoryInterface
*/
private $newsRepository;
public function __construct(NewsRepositoryInterface $newsRepositry)
{
$this->newsRepository = $newsRepositry;
}
public function run(string $title, string $slug, string $body): void
{
$news = new News(
null,
$title,
$slug,
$body,
);
$this->newsRepository->addNews($news);
}
}
渡されたデータを元に News
インスタンスを作成し、リポジトリに保存します。
フレームワーク/ライブラリ層
モデル
フレームワークのモデルです。
NewsRepository
NewsRepository
に addNews()
メソッドを追加します。
--- a/app/Models/NewsRepository.php
+++ b/app/Models/NewsRepository.php
@@ -49,4 +49,17 @@ class NewsRepository extends Model implements NewsRepositoryInterface
return $news;
}
+
+ public function addNews(News $news): void
+ {
+ $id = $this->insert([
+ 'title' => $news->title,
+ 'slug' => $news->slug,
+ 'body' => $news->body,
+ ]);
+
+ if ($id === false) {
+ throw new RuntimeException('Failed to insert news.');
+ }
+ }
}
CodeIgniter\Model
の insert()
メソッドでテーブルに挿入しています。
コントローラ
フレームワークのコントローラです。
Newsコントローラ
create()
メソッドを CreateNewsUseCase
を使うように変更します。
--- a/app/Controllers/News.php
+++ b/app/Controllers/News.php
@@ -6,6 +6,7 @@ use App\Models\NewsRepository;
use Acme\News\UseCase\News\NewsDto;
use Acme\News\UseCase\News\GetNewsListUseCase;
use Acme\News\UseCase\News\GetNewsItemUseCase;
+use Acme\News\UseCase\News\CreateNewsUseCase;
class News extends BaseController
{
@@ -47,17 +48,18 @@ class News extends BaseController
public function create()
{
- $model = model(NewsModel::class);
+ $repository = model(NewsRepository::class);
+ $useCase = new CreateNewsUseCase($repository);
if ($this->request->getMethod() === 'post' && $this->validate([
'title' => 'required|min_length[3]|max_length[255]',
'body' => 'required',
])) {
- $model->save([
- 'title' => $this->request->getPost('title'),
- 'slug' => url_title($this->request->getPost('title'), '-', true),
- 'body' => $this->request->getPost('body'),
- ]);
+ $title = $this->request->getPost('title');
+ $slug = url_title($this->request->getPost('title'), '-', true);
+ $body = $this->request->getPost('body');
+
+ $useCase->run($title, $slug, $body);
echo view('news/success');
} else {
CreateNewsUseCase
を生成し、実行しています。
create()
メソッド全体は以下のようになります。
public function create()
{
$repository = model(NewsRepository::class);
$useCase = new CreateNewsUseCase($repository);
if ($this->request->getMethod() === 'post' && $this->validate([
'title' => 'required|min_length[3]|max_length[255]',
'body' => 'required',
])) {
$title = $this->request->getPost('title');
$slug = url_title($this->request->getPost('title'), '-', true);
$body = $this->request->getPost('body');
$useCase->run($title, $slug, $body);
echo view('news/success');
} else {
echo view('templates/header', ['title' => 'Create a news item']);
echo view('news/create');
echo view('templates/footer');
}
}
これで、記事の作成ができるようになりました。
ディレクトリ構成
現状のディレクトリ構成は以下になります。
app/
├── Config
│ ├── Autoload.php
├── Controllers
│ ├── News.php
├── Models
│ └── NewsRepository.php
└── Views
└── news
├── create.php
├── overview.php
├── success.php
└── view.php
packages/
└── news ... Newsパッケージ
└── src
├── Domain ... ドメイン層
│ └── News
│ ├── News.php
│ └── NewsRepositoryInterface.php
└── UseCase ... ユースケース層
└── News
├── CreateNewsUseCase.php ← 追加
├── GetNewsItemUseCase.php
├── GetNewsListUseCase.php
└── NewsDto.php
app/
以下のファイルはモデルのファイル名を変更しただけで配置はそのままにしています。
packages/
以下にドメイン層とユースケース層のコードが追加されています。
フレームワークへの依存度を下げるFLUDパターン (4.5) へ続く。
参考
Date: 2021/12/23