Skip to content

Commit

Permalink
アーキテクチャー
Browse files Browse the repository at this point in the history
  • Loading branch information
ryuring committed Sep 24, 2023
1 parent 64dce8d commit 0d6a2ff
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 1 deletion.
182 changes: 181 additions & 1 deletion 5/package/architecture.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,183 @@
# アーキテクチャー

{% include looking_for.html %}
baserCMSのアーキテクチャーは、CakePHP4の標準的なアーキテクチャーをベースにしており、さらに、ビジネスロジックをサービスに実装し、はDIコンテナを利用して注入する方針としています。

## ビジネスロジックの実装対象
ビジネスロジックの実装は、テーブルクラスではなく、サービスクラスに実装し、コントローラーにおいては、テーブルクラスを直接利用することはせず、そのサービスクラスを利用します。

## 構成の全体像
- サービスクラス(例: `UsersService`
- 基本的には対象エンティティに関するユースケースを提供
- 状態はできるだけ保持せずテスタブルなコードとする
- 管理画面用コントローラー(例: `Admin/UsersController`
- サービスクラスをDIコンテナで利用し、処理の振り分けを担当
- 基本的に `$this->set()` で引き渡すデータは、管理画面用のサービスクラスを作成し(例:`UsersAdminService`)そのメソッドで一括で作成し、一括で引渡し、コントローラーが煩雑にならないようにする
- API用コントローラー(例: `Api/UsersController`
- サービスクラスをDIコンテナで利用し、Web APIを提供
- 管理画面用ヘルパ
- 対象画面に必要な情報を提供する
- 適宜、DIコンテナを利用してサービスクラスの利用が可能( `BcContainerTrait` を利用)


### クラス図
![管理画面アーキテクチャー](./svg/class/baser-core/basic_manage.svg)
![APIアーキテクチャー](./svg/class/baser-core/basic_api.svg)

## サービスクラスの実装
サービスクラスは、ユースケースを定義します。テーブルクラスと対になるクラスを用意してもよいですが、基本的には役割ごとに用意します。

- ユーザーを管理する(一覧表示、登録、編集、削除)
- プラグインをインストールしアンインストールする

最初は1つのクラスで実装を行い、肥大化に伴って、役割を分けクラスを分割します。

### インターフェイスの定義
サービスクラスを作成する際は、まずインターフェイスを定義します。
```php
// baser-core/src/Service/UsersServiceInterface.php
interface UsersServiceInterface
{
public function get(int $id): EntityInterface;
}
```

### サービスクラスの定義
作成したインターフェイスを実装するようにサービスクラスを定義します。
```php
// baser-core/src/Service/UsersService.php
class UsersService implements UsersServiceInterface
{
public function get(int $id): EntityInterface;
{
// 実装
}
}
```
なお、サービスクラスはできるだけ状態を持たないように実装します。

#### サービスクラスの命名規則
テーブルと対にしてサービスを提供する場合はエンティティの複数形にServiceを付け加えます。
```php
User -> UsersService
```



## 利用するサービスの定義

利用するサービスはサービスプロバイダで定義します。

メンバー変数 `provides` に利用するサービスのインターフェイスを定義し、`services` メソッドにて、
DIコンテナを利用して、利用するサービスのインターフェイスごとに、実装するサービスクラスを追加します。

```php
// baser-core/src/ServiceProvider/BcServiceProvider.php
class BcServiceProvider extends ServiceProvider
{
protected $provides = [
UsersServiceInterface::class
];

public function services($container): void
{
$container->add(UsersServiceInterface::class, UsersService::class);
}

}
```


## コントーローラーの実装

コントローラーでは、引数に利用したいサービスのインターフェイスを定義すると、
サービスプロバイダで定義したサービスクラスを利用できます。

```php
// baser-core/src/Controller/Admin/UsersController.php
class UsersController extends BcAdminAppController
{
public function index(UsersServiceInterface $service)
{
// 処理を記載
}
}
```

コントローラーではビジネスロジックをできるだけ実装せず、サービスクラスに実装して、それを利用します。

また、コントローラー内ではテーブルクラスを直接利用せつ、サービスクラスに利用する処理を実装し、そちらを利用するようにします。


### ビューへの変数の引き渡し
コントローラーからビューに変数を引き渡す場合は、コントローラーの処理が煩雑とならないよう、管理画面用のサービスクラスを作成し、そこで一括で生成した上で、一括で `$this->set()` に渡すようにします。

サービスに実装することで、引き渡す変数の明示化を行い、テスタブルなコードを目指します。

```php
// /baser-core/src/Service/UsersAdminService.php
class UsersAdminService extends UsersService
{
public function getViewVarsForIndex()
{
return [
'users' => $this->getIndex()
];
}
}

// /baser-core/src/Controller/Admin/UsersController.php
class UsersController extends BcAdminAppController
{
public function index(UsersAdminService $service)
{
$this->set($service->getViewVarsForIndex());
}
}
```

## ヘルパーの実装

ヘルパーについては、適宜必要となるサービスクラスを利用することもできます。
CakePHP4では、ヘルパでDIコンテナが利用できませんので、代替措置として `BcContainerTrait ` を利用します。

```php
// baser-core/src/View/Helper/BcAdminUserHelper.php
class BcAdminUserHelper extends Helper
{
use \BaserCore\Utility\BcContainerTrait;

public $UsersService;

public function initialize(array $config)
{
parent::initialize($config);
$this->UsersService = $this->getService(UsersServiceInterface::class)
}

public function get($id)
{
$this->UsersService->get($id);
}
}
```


## APIの実装
APIは、コントローラーからサービスクラスを呼び出し実装します。

`BcAdminApiController` を継承することによりJWT認証がかかる仕様となっています。

```php
// baser-core/src/Controller/Api/Admin/UsersController.php
class UsersController extends BcAdminApiController
{
public function index(UsersServiceInterface $users)
{
// 実装
}
}
```

### 参考
[依存性の注入 - CakePHP4](https://book.cakephp.org/4/ja/development/dependency-injection.html)

3 changes: 3 additions & 0 deletions 5/package/specification/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# baserCMS 設計書

baserCMS5リリース時の各機能の設計書です。
内容については、一部古い場合がありますのでご了承ください。

## 基本設計
- [共通クラス図](baser-core/common/index.md)

Expand Down

0 comments on commit 0d6a2ff

Please sign in to comment.