LoginSignup
158
170

More than 5 years have passed since last update.

Laravel5を使ってドメイン駆動設計で作るサンプルアプリ。

Last updated at Posted at 2015-10-24

Laravel5で変更に強いアプリケーションを作成する。

サンプルとして経費(本)を記録するだけのWebアプリケーションを作成。
日付、タイトル、価格、URLを1テーブルにしてMySQLへ格納。

Laravelインストール

% composer create-project laravel/laravel keihi
% cd keihi
% php artisan -V 
Laravel Framework version 5.1.20 (LTS)

名前空間を更新

Keihiという名前空間にします。

// namespaceを「App」から「Keihi」へ変更
% php artisan app:name Keihi

namespace指定してある箇所が全部以下のように変更されます。

composer.json
         "psr-4": {
-            "App\\": "app/"
+            "Keihi\\": "app/"
         }
app/Console/Kernel.php
 <?php

-namespace App\Console;
+namespace Keihi\Console;

Databaseを用意

MAMPでMYSQLサーバー起動、UTF8でDB作成。

以下、MAMPのソケットで繋ぐときに必要な処理。

UNIX_SOCKET追記
/config/database.php
        'mysql' => [
            'driver'    => 'mysql',
            'unix_socket' => env('DB_UNIX_SOCKET'),// 1行追記
            'host'      => env('DB_HOST', 'localhost'),
            'database'  => env('DB_DATABASE', 'forge'),
.envのDB設定を編集してDB_UNIX_SOCKETは追記。
.env
DB_UNIX_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock
DB_HOST=localhost
DB_DATABASE=keihi_db
DB_USERNAME=test
DB_PASSWORD=test

マイグレーション作成

作成コマンド

% php artisan make:migration create_keihi_table --create=keihi 
Created Migration: 2015_10_23_235515_create_keihi_table

ファイル編集

/database/migrations/2015_10_23_235515_create_keihi_table.php
public function up()
{
    Schema::create('keihi', function (Blueprint $table) {
        $table->increments('id');       // ID
        $table->char('title', 100);     // タイトル
        $table->integer('price');       // 価格
        $table->text('url');            // URL
        $table->timestamps();           // 作成時刻
     });
}

マイグレーション実行

MySQLにテーブルが作成。(keihi以外はデフォルトで存在するもの)

% php artisan migrate
Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2015_10_23_235515_create_keihi_table

エレクエント作成

Keihiモデル(/app/Keihi.php)を作成。

% php artisan make:model Keihi

エレクエント編集

Keihiモデルに紐づくテーブルを「keihi」に設定。

/app/Keihi.php
<?php

namespace Keihi;

use Illuminate\Database\Eloquent\Model;

class Keihi extends Model
{
    protected $table = 'keihi';
}

リポジトリ作成

インターフェース作成

/app/Repositories/KeihiInterface.php
<?php

/**
 * Interface KeihiInterface
 */
interface KeihiInterface
{
    /**
     * 取得
     * @param $id
     * @return mixed
     */
    public function get($id);

    /**
     * 一覧取得
     * @return mixed
     */
    public function getList();

    /**
     * 更新
     * @param $id
     * @param $data
     * @return mixed
     */
    public function update($id, $data);

    /**
     * 新規登録
     * @param $data
     * @return mixed
     */
    public function create($data);

    /**
     * 削除
     * @param $id
     * @return mixed
     */
    public function delete($id);
}

リポジトリ実装

インターフェースを使用して実装します。
コンストラクタでエレクエントモデルを依存注入します。

/app/Repositories/KeihiRepository.php
<?php

namespace Keihi\Repositories;

use Keihi\Repositories\KeihiInterface;
use Keihi\Keihi;

/**
 * Class KeihiRepository
 * @package Keihi\Repositories
 */
class KeihiRepository implements KeihiInterface
{
    /**
     * @var Keihi
     */
    protected $keihi;

    /**
     * @param Keihi $keihi
     */
    public function __construct(Keihi $keihi)
    {
        $this->keihi = $keihi;
    }

    /**
     * 取得
     * @param $id
     * @return mixed
     */
    public function get($id)
    {
     
    }

サービスプロバイダー作成

リポジトリ用のサービスプロバイダー作成

php artisan make:provider RepositoryProvider

サービスプロバイダー編集

/app/Providers/RepositoryProvider.php
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        // 経費インターフェスと経費リポジトリの連結
        $this->app->bind(KeihiInterface::class, KeihiRepository::class);
    }

リポジトリサービスプロバイダーの読込

/config/app.php
        /*
         * Application Service Providers...
         */
        Keihi\Providers\AppServiceProvider::class,
        Keihi\Providers\AuthServiceProvider::class,
        Keihi\Providers\EventServiceProvider::class,
        Keihi\Providers\RouteServiceProvider::class,
        Keihi\Providers\RepositoryProvider::class,// 1行追加
    ],

テストデータ投入

シーダー作成

% php artisan make:seeder KeihiSeeder

シーダー編集

エレクエントモデルを利用してテスト用データを記述。

/database/seeds/KeihiSeeder.php
<?php

use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use Keihi\Keihi;

class KeihiSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Model::unguard();
        Keihi::create([
            'id' => 1,
            'title' => 'WEB+DB PRESS Vol.89',
            'price' => 1598,
            'url' => 'http://www.amazon.co.jp/gp/product/4774176389'
        ]);
        Keihi::create([
            'id' => 2,
            'title' => 'Docker実践入門――Linuxコンテナ技術の基礎から応用まで (Software Design plus)',
            'price' => 2894,
            'url' => 'http://www.amazon.co.jp/gp/product/4774176540'
        ]);
        Keihi::create([
            'id' => 3,
            'title' => 'HTML5 Web標準API バイブル',
            'price' => 3218,
            'url' => 'http://www.amazon.co.jp/gp/product/4774176540'
        ]);
    }
}

データ投入

% php artisan db:seed --class=KeihiSeeder

単体テスト(PHPUnit)

単体テスト作成

/tests/Repositories/KeihiRepositoryTest.php
<?php

use Keihi\Repositories\KeihiInterface;

class KeihiRepositoryTest extends TestCase
{
    protected $repo;

    public function setUp()
    {
        parent::setUp();
        $this->repo = $this->app->make(KeihiInterface::class);
    }

    public function testGet()
    {
        $result = $this->repo->get(1);
        $this->assertSame($result->title, 'WEB+DB PRESS Vol.89');
        $this->assertSame($result->price, 1598);
        $this->assertSame($result->url,   'http://www.amazon.co.jp/gp/product/4774176389');
    }

    public function testGetList()
    {
        $result = $this->repo->getList();
        $this->assertCount(3, $result);
        $this->assertSame($result[2]->title, 'HTML5 Web標準API バイブル');
        $this->assertSame($result[2]->price, 3218);
        $this->assertSame($result[2]->url,   'http://www.amazon.co.jp/gp/product/4774176540');
    }

}

単体テスト実行

% php vendor/bin/phpunit --tap
TAP version 13
ok 1 - ExampleTest::testBasicExample
ok 2 - KeihiRepositoryTest::testGet
ok 3 - KeihiRepositoryTest::testGetList
1..3

サービス作成

コーントローラー内でリポジトリを操作する為のサービスを作成。

インターフェースを作成。

/app/Services/KeihiServiceInterface.php
/**
 * Interface KeihiServiceInterface
 * @package Keihi\Services
 */
interface KeihiServiceInterface
{
    /**
     * 単体取得
     * @return mixed
     */
    public function get($id);

    /**
     * 一覧取得
     * @return mixed
     */
    public function getList();

    /**
     * 保存
     * @param $input
     * @param $id | null
     * @return $id | null
     */
    public function save($input, $id=null);

    /**
     * 削除
     * @param $id
     * @return $id
     */
    public function delete($id);

    /**
     * エンティティ作成
     * @return $entity
     */
    public function createEntity();

インターフェースを使用して実装。
データ検証の役割を持たせる。

/app/Services/KeihiService.php
<?php

namespace Keihi\Services;

use Keihi\Services\KeihiServiceInterface;
use Keihi\Repositories\KeihiInterface;
use Illuminate\Validation\Factory as ValidateFactory;

/**
 * Class KeihiService
 * @package Keihi\Services
 */
class KeihiService implements KeihiServiceInterface
{
    /**
     * @var KeihiInterface
     */
    protected $keihiInterface;

    /**
     * @var ValidateFactory
     */
    protected $validateFactory;

    /**
     * @var array
     */
    protected $rules = ["title" => "required|max: 100", "price" => "required|integer|min:0|max:100000", "url" => "required"];

    /**
     * @param KeihiInterface $keihiInterface
     * @param ValidateFactory $validateFactory
     */
    public function __construct(KeihiInterface $keihiInterface, ValidateFactory $validateFactory)
    {
        $this->keihiInterface = $keihiInterface;
        $this->validateFactory = $validateFactory;
    }

    /**
     * @param $id
     * @return mixed
     */
    public function get($id)
    {
        return $this->keihiInterface->get($id);
    }

    /**
     * @return mixed
     */
    public function getList()
    {
        return $this->keihiInterface->getList();
    }

    /**
     * @param $request
     * @param $id
     * @return $id
     */
    public function save($request, $id=null)
    {
        $input = $request->only(['title', 'price', 'url']);
        $v = $this->validateFactory->make($input, $this->rules);
        if ($v->fails()) {
            return null;
        }

        if (is_null($id)) {
            $id = $this->keihiInterface->create($input);
        } else {
            $id = $this->keihiInterface->update($id, $input);
        }

        return $id;
    }

    /**
     * @param $id
     * @return bool
     */
    public function delete($id)
    {
        $this->keihiInterface->delete($id);
        return true;
    }

    /**
     * @return mixed
     */
    public function createEntity()
    {
        return $this->keihiInterface->createEntity();
    }
}

Appサービスプロバイダーに登録。

/app/Providers/AppServiceProvider.php
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        // 経費サービス
        $this->app->singleton(KeihiServiceInterface::class, KeihiService::class);
    }

コントローラー作成。

経費サービスインターフェースを依存注入して使用します。

% php artisan make:controller KeihiController
/app/Http/Controllers/KeihiController.php
<?php

namespace Keihi\Http\Controllers;

use Illuminate\Http\Request;
use Keihi\Http\Requests;
use Keihi\Http\Controllers\Controller;
use Keihi\Services\KeihiServiceInterface;

/**
 * Class KeihiController
 * @package Keihi\Http\Controllers
 */
class KeihiController extends Controller
{
    /**
     * @var KeihiServiceInterface
     */
    private $keihiService;

    /**
     * @param KeihiServiceInterface $keihiServiceInterface
     */
    public function __construct(KeihiServiceInterface $keihiServiceInterface)
    {
        $this->keihiService = $keihiServiceInterface;
    }

    /**
     * 一覧
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $list = $this->keihiService->getList();
        return view('keihi.list', compact('list'));
    }

    /**
     * 新規入力画面
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $keihi = $this->keihiService->createEntity();
        return view('keihi.edit', compact('keihi'));
    }

    /**
     * 新規登録処理
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $id = $this->keihiService->save($request);
        return $this->show($id);
    }

    /**
     * 詳細
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $keihi = $this->keihiService->get($id);
        return view('keihi.detail', compact('keihi'));
    }

    /**
     * 編集画面
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $keihi = $this->keihiService->get($id);
        return view('keihi.edit', compact('keihi'));
    }

    /**
     * 更新処理
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $id = $this->keihiService->save($request, $id);
        return $this->show($id);
    }

    /**
     * 削除処理
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $this->keihiService->delete($id);
        return $this->index();
    }
}

ルーティング

/app/Http/routes.php
Route::resource('keihi', 'KeihiController');

ルーティングの確認。

% php artisan route:list
+--------+----------+--------------------+---------------+------------------------------------------------+------------+
| Domain | Method   | URI                | Name          | Action                                         | Middleware |
+--------+----------+--------------------+---------------+------------------------------------------------+------------+
|        | GET|HEAD | /                  |               | Closure                                        |            |
|        | GET|HEAD | keihi              | keihi.index   | Keihi\Http\Controllers\KeihiController@index   |            |
|        | POST     | keihi              | keihi.store   | Keihi\Http\Controllers\KeihiController@store   |            |
|        | GET|HEAD | keihi/create       | keihi.create  | Keihi\Http\Controllers\KeihiController@create  |            |
|        | DELETE   | keihi/{keihi}      | keihi.destroy | Keihi\Http\Controllers\KeihiController@destroy |            |
|        | PATCH    | keihi/{keihi}      |               | Keihi\Http\Controllers\KeihiController@update  |            |
|        | GET|HEAD | keihi/{keihi}      | keihi.show    | Keihi\Http\Controllers\KeihiController@show    |            |
|        | PUT      | keihi/{keihi}      | keihi.update  | Keihi\Http\Controllers\KeihiController@update  |            |
|        | GET|HEAD | keihi/{keihi}/edit | keihi.edit    | Keihi\Http\Controllers\KeihiController@edit    |            |
+--------+----------+--------------------+---------------+------------------------------------------------+------------+

158
170
0

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
158
170