LoginSignup
25
24

More than 3 years have passed since last update.

Laravel - Laravel を使ったWebアプリケーション の基本パターンを実装してみた ( Service / Repository Pattern)

Last updated at Posted at 2019-08-18

はじめに

Laravel を使用した WebApplication を作成するときに、毎回同じようなセットアップを行うので、共通部分を作成してみました。

概要

コードは以下で公開しています。

システムの全体像

システム構成

このコードは次のようなシステム構成において、Application Server にて実行されることを想定しています。

image.png

アプリケーション・アーキテクチャ

Laravel で実現するアプリケーションのアーキテクチャは、次のような構成となります。

image.png

Entity Relation

仮で作成するエンティティは次のような構成です。

image.png

開発環境

開発環境は次のようなソフトウェア・スタックです。

image.png

Laravel と 関連ツールという側面でもう少し絞ったソフトウェア・スタックは次のような構成です。

image.png

上記の開発環境の構築については、以下の手順を参照してください。

手順

概要

今回作成するアプリケーションの作成手順は次の通りです。

  1. 事前準備
    1. 開発環境を用意する(仮想環境、エディタ)
    2. Laravel プロジェクトの新規作成と関連ツールの導入
  2. 構築を始める
    1. Model の作成
    2. Controller の作成
    3. カスタムログクラスの作成
    4. Repository クラスの作成
    5. Service クラスと Controller クラスの結合
    6. Service クラスの作成 と Repository クラスとの結合
  3. 動作確認する

1.) については、「開発環境」にて記載したリンクの手順で事前に作成している前提で、それ以降について詳細を記載します。

1-1. 開発環境を用意する(仮想環境、エディタ)

  • VirtualBox + Vagrant
  • Visual Studio Code

1-2. Laravel プロジェクトの新規作成と関連ツールの導入

2-1. Model の作成

次のコマンドで Model と migration のファイルを作成します。

command
# Create Model and Migration Files
php artisan make:model Models/Table/TblUser --migration
php artisan make:model Models/Table/TblBlogPost --migration

作成した migration ファイルに必要なカラムを追加するよう追記します。

database/migrations/XXXXX_create_tbl_users_table.php
    public function up()
    {
        Schema::create('tbl_users', function (Blueprint $table) {
            $table->bigIncrements('id')->unsigned();
            $table->string('name');
            $table->timestamps();
            $table->softDeletes();
        });
    }
database/migrations/XXXXX_create_tbl_blog_posts_table.php
    public function up()
    {
        Schema::create('tbl_blog_posts', function (Blueprint $table) {
            $table->bigIncrements('id')->unsigned();
            $table->unsignedBigInteger('user_id');
            $table->string('title');
            $table->text('content');
            $table->timestamps();
            $table->softDeletes();

            //外部キー制約
            $table->foreign('user_id')
                    ->references('id')
                    ->on('tbl_users')
                    ->onDelete('cascade');
        });
    }

作成した migration ファイルを実行します。

command
# execute migration
php artisan migrate

# You can rollback migration if you want.
php artisan migrate:rollback 

2-2. Controller の作成

artisan コマンドで REST API を実現する基本メソッドを実装した Controler を自動生成します。

command
php artisan make:controller UserController --resource
php artisan make:controller BlogPostController --resource

作成したコントローラへのルートを追加する。

routes/api.php
# 次のルートを追加する。
Route::resource('users', 'UserController');
Route::resource('blog-posts', 'BlogPostController');

作成したルートの設定を確認します。

# php artisan route:list
+--------+-----------+---------------------------------+--------------------+-------------------------------------------------+--------------+
| Domain | Method    | URI                             | Name               | Action                                          | Middleware   |
+--------+-----------+---------------------------------+--------------------+-------------------------------------------------+--------------+
|        | GET|HEAD  | /                               |                    | Closure                                         | web          |
|        | POST      | api/blog-posts                  | blog-posts.store   | App\Http\Controllers\BlogPostController@store   | api          |
|        | GET|HEAD  | api/blog-posts                  | blog-posts.index   | App\Http\Controllers\BlogPostController@index   | api          |
|        | GET|HEAD  | api/blog-posts/create           | blog-posts.create  | App\Http\Controllers\BlogPostController@create  | api          |
|        | GET|HEAD  | api/blog-posts/{blog_post}      | blog-posts.show    | App\Http\Controllers\BlogPostController@show    | api          |
|        | PUT|PATCH | api/blog-posts/{blog_post}      | blog-posts.update  | App\Http\Controllers\BlogPostController@update  | api          |
|        | DELETE    | api/blog-posts/{blog_post}      | blog-posts.destroy | App\Http\Controllers\BlogPostController@destroy | api          |
|        | GET|HEAD  | api/blog-posts/{blog_post}/edit | blog-posts.edit    | App\Http\Controllers\BlogPostController@edit    | api          |
|        | GET|HEAD  | api/user                        |                    | Closure                                         | api,auth:api |
|        | GET|HEAD  | api/users                       | users.index        | App\Http\Controllers\UserController@index       | api          |
|        | POST      | api/users                       | users.store        | App\Http\Controllers\UserController@store       | api          |
|        | GET|HEAD  | api/users/create                | users.create       | App\Http\Controllers\UserController@create      | api          |
|        | GET|HEAD  | api/users/{user}                | users.show         | App\Http\Controllers\UserController@show        | api          |
|        | PUT|PATCH | api/users/{user}                | users.update       | App\Http\Controllers\UserController@update      | api          |
|        | DELETE    | api/users/{user}                | users.destroy      | App\Http\Controllers\UserController@destroy     | api          |
|        | GET|HEAD  | api/users/{user}/edit           | users.edit         | App\Http\Controllers\UserController@edit        | api          |
+--------+-----------+---------------------------------+--------------------+-------------------------------------------------+--------------+

作成したコントローラのテストコードを作成します。

command
# Feature Test
# API 単位のテスト
php artisan make:test Http/Controllers/UserControllerTest
php artisan make:test Http/Controllers/BlogPostController

# Unit Test
# Method 単位のテスト
php artisan make:test Http/Controllers/UserControllerTest --unit
php artisan make:test Http/Controllers/BlogPostControllerTest --unit

テストコードを実行します。

command
composer exec -v phpunit
> __exec_command: phpunit
PHPUnit 7.5.14 by Sebastian Bergmann and contributors.

..............                                                    14 / 14 (100%)

Time: 1.95 seconds, Memory: 18.00 MB

OK (14 tests, 14 assertions)

2-3. Custom Log Class の追加

次の Merge Request を参照してください。

cf.

2-4. Repository クラスの作成

次の Merge Request を参照してください。

cf.

2-5. Service クラスと Controller クラスの結合

次の Merge Request を参照してください。

cf.

2-6. Service クラスの作成 と Repository クラスとの結合

次の Merge Request を参照してください。

3. 動作確認する

ブラウザで以下の URL にアクセスし、ログ・ファイルに出力されるログを確認する。

その他

テストカバレッジ

次のコマンドでテストカバレッジを HTML 出力することができます。

command
# Execute at project root
# see PROJECT_ROOT/coverage/
composer test:coverage

UnitTest 用のデータベース

テスト実行時用のデータベースを作成し、ユニットテスト実行時にはそちらのDBを参照するようにします。

まずは次のように、テスト用の .env を作成します。(変更箇所のみ記載)

.env.testing

# ここを testing に変更
APP_ENV=testing

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
# db をテスト用のDBに変更
DB_DATABASE={{ db_test }}
DB_USERNAME={{ db_user }}
DB_PASSWORD={{ db_password }}

以下のコマンドでテスト環境向けDBをマイグレーションした上で、その環境を使用してテストを実行することができます。

command
# Migrate to test schema
php artisan migrate --env=testing

# Run Test Code using `APP_ENV=testing`
composer test:run

Todo

  • Request / Response クラスの実装に関する解説
  • Unit Test Code の作成

おわりに

2019/08/19

本当にざっくりの構成だけ作成しました。
途中から Unit Test Code の作成がおざなりになってしまいました。
もう少し拡張する予定です。

参考

25
24
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
24