LoginSignup
25
25

More than 5 years have passed since last update.

Laravel基礎(5)Webアプリ開発の実践

Last updated at Posted at 2018-10-14

Laravelでカレンダーアプリを例に開発の流れを紹介します。

デモサイト

最初にアプリの雛形を作ります


laravel new cal_lara
cd cal_lara

タイムゾーンやロケールは次のように設定します

config/app.php
'
timezone' => 'Asia/Tokyo', 
'locale' => 'ja',

DB接続内容を設定します

編集するファイル:.env

休日モデルを作成します

アプリが扱うリソースの名前を決めて、その名前でモデルクラスを作成します。カレンダーアプリなので、休日を扱うリソース(テーブル)を持たせます。


php artisan make:model Holiday 

マイグレーション(DBテーブルの用意)も行っておきます


php artisan make:migration Holiday 

出来上がったファイルの中にholidaysテーブルのスキーマ定義を書きます。

database/migrations/YYYY_MM_DD_HHMMSS_holiday.php
class Holiday extends Migration { 
    public function up() { 
        Schema::create('holidays', function (Blueprint $table) { 
            $table->increments('id'); 
            $table->date('day'); 
            $table->string('description'); 
            $table->timestamps(); 
        }); 
    } 
    public function down() {
        Schema::drop('holidays'); 
    } 
} 

マイグレーション実行します


php artisan migrate


マイグレーションをやり直したい場合は次の通りです。


php artisan migrate:refresh

カレンダーコントローラーを作ります


php artisan make:controller CalendarController

まずは休日の入力と表示のメソッドを作ります。

app/Http/Controllers/CalendarController.php

use App\Holiday;
use Illuminate\Http\Request;
class CalendarController extends Controller
{
    public function getHoliday(Request $request)
    {
        // 休日データ取得
        $list = Holiday::all();
        return view('calendar.holiday', ['list' => $list]);        
    }
    public function postHoliday(Request $request)
    {
        // POSTで受信した休日データの登録
        $holiday = new Holiday(); 
        $holiday->day = $request->day;
        $holiday->description = $request->description;        
        $holiday->save();
        // 休日データ取得
        $list = Holiday::all();
        return view('calendar.holiday', ['list' => $list]);
    }
}

Viewは後ほど用意しますが、入力、表示ともに同じViewを使うようにします。

ルーティング情報を設定します

ルーティングにコントローラークラス@メソッドを定義します。

routes/web.php
Route::get('/holiday','CalendarController@getHoliday');
Route::post('/holiday','CalendarController@postHoliday');

ビュー(Blade)を作ります


mkdir resources/views/calendar

Viewではコントローラーに対して日付と説明を送信するフォーム部分と、コントローラーから休日一覧を受け取り、その結果を表示する部分の2つの機能を持たせます。

resources/views/calendar/holiday.blade.php
<html>
<head>
    <title>休日データ</title>
</head>
<body>
    <h1>休日</h1>
    <!-- 休日入力フォーム -->
    <form method="POST" action="/holiday"> 
    {{csrf_field()}}
    
    日付: <input type="text" name="day"> [YYYY/MM/DD]
    説明: <input type="text" name="description"> 
    <input type="submit"> 
    </form> 
    <!-- 休日一覧表示 -->
    <table>
    <tr>
    <th>日付</th>
    <th>説明</th>
    <th>作成日</th>
    <th>更新日</th>
    </tr>
    @foreach($list as $val)
    <tr>
        <td>{{$val->day}}</td>
        <td>{{$val->description}}</td>
        <td>{{$val->created_at}}</td>
        <td>{{$val->updated_at}}</td>
    </tr>
    @endforeach
    </table>
</body>
</html>

ここまで作ったら、動かしてみましょう。休日データが登録できて、一覧取得できるはずです。


 php artisan serve --port 8080

URLアドレス:http://[servername]/holiday

レイアウトを分割し、ついでにJQuery/Bootstrap導入します

レイアウトファイルを作り、HTMLの共通部分はこのファイルに書くようにします。

resources/views/layout.blade.php

<!DOCTYPE HTML>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>@yield('title')</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    @yield('content')
</div>
</body>
</html>

先ほど作ったBladeファイルを下記のように変更します。

resources/views/calendar/holiday.blade.php

@extends('layout')
@section('title', '休日設定')
@section('content')
    <h1>休日設定</h1>
    <!-- 休日入力フォーム -->
    <form method="POST" action="/holiday"> 
    <div class="form-group">
    {{csrf_field()}}
    
    <label for="day">日付[YYYY/MM/DD] </label>
    <input type="text" name="day" class="form-control" id="day">
    <label for="description">説明</label>
    <input type="text" name="description" class="form-control" id="description"> 
    </div>
    <button type="submit" class="btn btn-primary">登録</button> 
    </form> 
    <!-- 休日一覧表示 -->
    <table class="table">
    <thead>
    <tr>
    <th scope="col">日付</th>
    <th scope="col">説明</th>
    <th scope="col">作成日</th>
    <th scope="col">更新日</th>
    </tr>
    </thead>
    <tbody>
    @foreach($list as $val)
    <tr>
        <th scope="row">{{$val->day}}</th>
        <td>{{$val->description}}</td>
        <td>{{$val->created_at}}</td>
        <td>{{$val->updated_at}}</td>
    </tr>
    @endforeach
    </tbody>
    </table>
@endsection

@extends“layout” (layout.blade.php) を継承するよう指示しています。

@section(‘content’)から @endsection までが、layout ビューの @yield(‘content’)の箇所に流し込む部分になります。

ここでbootstrapのCSSを使うようにし画面をリッチにします。
参考:
https://getbootstrap.com/docs/4.0/content/tables/

JQueryで日付入力を便利にします

日付(YYYY/MM/DD)の入力をポップアップカレンダーから選択して日付入力できるようにしてみましょう。
次のコードを書きます。(<body>タグの中ならどこでもいいです)

resources/views/calendar/holiday.blade.php
・・(一部抜粋)・・
<script>
  $( function() {
    $( "#day" ).datepicker({dateFormat: 'yy-mm-dd'});
  } );
</script>

そして日付の入力をするフォームのid属性をつけます。(bootstrapの適用の時id="day"と入れたのでそれを使います)
<input type="text" id="day">

参考:
http://jqueryui.com/datepicker/

ここまで作ったら、動かしてみましょう。休日一覧が綺麗に表示され、日付入力時にカレンダーから日付が選択できるはずです。


 php artisan serve --port 8080

URLアドレス:http://[servername]/

カレンダーの表示処理を作ります

カレンダー処理を行うクラスをComposerでオートロードするようにします。
以下のようなクラスを作成します。

app/Calendar.php

namespace App;
class Calendar
{
    private $html;    
    public function showCalendarTag($m, $y)
    {
        $year = $y;
        $month = $m;
        if ($year == null) {
            // システム日付を取得する。 
            $year = date("Y");
            $month = date("m");
        }
        $firstWeekDay = date("w", mktime(0, 0, 0, $month, 1, $year)); // 1日の曜日(0:日曜日、6:土曜日)
        $lastDay = date("t", mktime(0, 0, 0, $month, 1, $year)); // 指定した月の最終日
        // 日曜日からカレンダーを表示するため前月の余った日付をループの初期値にする
        $day = 1 - $firstWeekDay;
        $this->html = <<< EOS
<h1>{$year}{$month}</h1>
<table class="table table-bordered">
<tr>
  <th scope="col"></th>
  <th scope="col"></th>
  <th scope="col"></th>
  <th scope="col"></th>
  <th scope="col"></th>
  <th scope="col"></th>
  <th scope="col"></th>
</tr>
EOS;
        // カレンダーの日付部分を生成する
        while ($day <= $lastDay) {
            $this->html .= "<tr>";
            // 各週を描画するHTMLソースを生成する
            for ($i = 0; $i < 7; $i++) {
                if ($day <= 0 || $day > $lastDay) {
                    // 先月・来月の日付の場合
                    $this->html .= "<td>&nbsp;</td>";
                } else {
                   $this->html .= "<td>" . $day . "</td>"; 
                }
               $day++;
            }

            $this->html .= "</tr>";
        }

        return $this->html .= '</table>';
    }
}

HTMLタグをコードに埋め込み、指定の年月のカレンダーを表として出力するshowCalendarTagメソッドを作ります。
プロジェクトディレクトリ直下にあるcomposer.jsonのautoload.filesへ以下のようにこのCalendarクラスのファイル・パスを追加します。

composer.json
・・(一部抜粋)・・
"autoload": {
    "classmap": [
        ...
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        "app/Calendar.php"
    ]
},

その後、以下のComposerコマンドを実行します。


composer dump-autoload

これでCalendarクラスが使えるようになりました。
コントローラーでカレンダーの表示のためのCalendarクラスをインスタンス化し、メソッドを呼び出します。

app/Http/Controllers/CalendarController.php

use App\Calendar;
・・(一部抜粋)・・
    public function index(Request $request)
    {
        $cal = new Calendar();
        $tag = $cal->showCalendarTag($request->month,$request->year);

        return view('calendar.index', ['cal_tag' => $tag]);
    }

ルーティング情報はコントローラークラス@メソッドを定義します

routes/web.php

Route::get('/','CalendarController@index');

Viewではコントローラーから受け取る結果(カレンダー表)を表示します

resources/views/calendar/index.blade.php

@extends('layout')
@section('title', 'カレンダー')
@section('content')
    {!!$cal_tag!!}
@endsection

カレンダーと休日一覧の画面の行き来を行います

先ほど作った休日一覧画面のholiday.blade.phpファイルに下記を追加

resources/views/calendar/holiday.blade.php

<a href="{{ url('/') }}">カレンダーに戻る</a>

先ほど作ったカレンダー画面のindex.blade.phpファイルに下記を追加

resources/views/calendar/index.blade.php
<a href="{{ url('/holiday') }}">休日設定</a>

ここまで作ったら、動かしてみましょう。カレンダーが表示され、休日一覧画面との行き来ができるはずです。


 php artisan serve --port 8080

URLアドレス:http://[servername]/

カレンダーに休日情報を入れます

Calendarクラスで休日データをもらうようにします。
まずインスタンス変数を作り、コンストラクタで受け取るようにします。

app/Calendar.php
・・(一部抜粋)・・
    private $holidays; 
    function __construct($holidays) {
        $this->holidays = $holidays;
    }

日付を入れる行: $this->html .= "<td>" . $day . "</td>"; を下記のように書き換え、日付に応じて休日の情報を表示できるようにします。

・・(一部抜粋)・・
                   $this->html .= "<td>" . $day ."&nbsp"; 
                   $target = date("Y-m-d", mktime(0, 0, 0, $month, $day, $year)); 
                   foreach($this->holidays as $val) {
                       if ($val->day == $target) {
                           $this->html .= $val->description; 
                           break;
                       }
                   }
                   $this->html .= "</td>"; 

コントローラーのindexでは

app/Http/Controllers/CalendarController.php
・・(一部抜粋)・・
        $list = Holiday::all();
        $cal = new Calendar($list);

とCalendarクラスのインスタンス化の時に休日のデータを渡すようにします。

ここまで作ったら、再度動かしてみましょう。カレンダーが表示され、休日が表示できるはずです。(休日データを登録してくださいね)


 php artisan serve --port 8080

URLアドレス:http://[servername]/

カレンダーの月めくりを行います

Calendarクラスの中で前月と翌月の年月の計算を行い、ボタンを表示できるようにします。

次のコードを表示すべき\$yearと\$monthが確定したのちの適切な箇所に追加します。

app/Calendar.php
・・(一部抜粋)・・
        // 前月
        $prev = strtotime('-1 month',mktime(0, 0, 0, $month, 1, $year));
        $prev_year = date("Y",$prev);
        $prev_month = date("m",$prev);
        // 翌月
        $next = strtotime('+1 month',mktime(0, 0, 0, $month, 1, $year));
        $next_year = date("Y",$next);
        $next_month = date("m",$next);

そしてHTMLの年月の表示部分のところで、前月と翌月のリンクボタンを表示します。

app/Calendar.php
・・(一部抜粋)・・
         $this->html = <<< EOS
<h1>
<a class="btn btn-primary" href="/?year={$prev_year}&month={$prev_month}" role="button">&lt;前月</a>
{$year}{$month}
<a class="btn btn-primary" href="/?year={$next_year}&month={$next_month}" role="button">翌月&gt;</a>
</h1>

ここまで作ったら、再度動かしてみましょう。カレンダーが表示され、月めくりできるはずです。


 php artisan serve --port 8080

URLアドレス:http://[servername]/

休日の修正ができるようにします

休日一覧の日付をクリックするとそのデータを編集できるようにします。
ルーティング情報で編集のアクションを定義します。

routes/web.php

Route::get('/holiday/{id}','CalendarController@getHolidayId');

コントローラーのなかの表示と編集のメソッドを書き換えます。

app/Http/Controllers/CalendarController.php
・・(一部抜粋)・・
class CalendarController extends Controller
{
    public function getHoliday(Request $request)
    {   
        // 休日データ取得
        $data = new Holiday();
        $list = Holiday::all();
        return view('calendar.holiday', ['list' => $list,'data' => $data]);
    }
    public function getHolidayId($id)
    {
        // 休日データ取得
        $data = new Holiday();
        if (isset($id)) {
            $data = Holiday::where('id', '=', $id)->first();
        } 
        $list = Holiday::all();
        return view('calendar.holiday', ['list' => $list, 'data' => $data]);
    }
    public function postHoliday(Request $request)
    {
        // POSTで受信した休日データの登録
        if (isset($request->id)) {
            $holiday = Holiday::where('id', '=', $request->id)->first();
            $holiday->day = $request->day;
            $holiday->description = $request->description;        
            $holiday->save();
        } else {
            $holiday = new Holiday(); 
            $holiday->day = $request->day;
            $holiday->description = $request->description;        
            $holiday->save();
        }
        // 休日データ取得
        $data = new Holiday();
        $list = Holiday::all();
        return view('calendar.holiday', ['list' => $list, 'data' => $data]);
    }
}

Viewに次のコードを書きます。
編集のためにIDをHiddenで送信できるようにし、各フォームに編集するべき内容を入れるようにします。

resources/views/calendar/holiday.blade.php
・・(一部抜粋)・・
    <form method="POST" action="/holiday"> 
    <div class="form-group">
    {{csrf_field()}}    
    <label for="day">日付[YYYY/MM/DD] </label>
    <input type="text" name="day" class="form-control" id="day" value="{{$data->day}}">
    <label for="description">説明</label>
    <input type="text" name="description" class="form-control" id="description" value="{{$data->description}}"> 
    </div>
    <button type="submit" class="btn btn-primary">登録</button> 
    <input type="hidden" name="id" value="{{$data->id}}">
    </form> 
・・
    <!-- 日付のリンクをつける -->
    <th scope="row"><a href="{{ url('/holiday/'.$val->id) }}">{{$val->day}}</a></th>

ここまで作ったら、再度動かしてみましょう。休日が修正できるはずです。


 php artisan serve --port 8080

URLアドレス:http://[servername]/

休日の削除ができるようにします

Viewに次のコードを書き削除のためのボタンを追加します。
休日一覧の<table>に新しい列を作るため<td>のなかに次のフォームを追加します。

resources/views/calendar/holiday.blade.php
・・(一部抜粋)・・
        <td><form action="/holiday" method="post">
            <input type="hidden" name="id" value="{{$val->id}}">
            {{ method_field('delete') }}
            {{csrf_field()}} 
            <button class="btn btn-default" type="submit">Delete</button>
        </form></td>

ルーティング情報で削除のアクションを定義します

routes/web.php

Route::delete('/holiday','CalendarController@deleteHoliday');

コントローラーのなかに削除のメソッドを書き加えます。

app/Http/Controllers/CalendarController.php
・・(一部抜粋)・・
    public function deleteHoliday(Request $request)
    {
        // DELETEで受信した休日データの削除
        if (isset($request->id)) {
            $holiday = Holiday::where('id', '=', $request->id)->first();        
            $holiday->delete();
        }
        // 休日データ取得
        $data = new Holiday();
        $list = Holiday::all();
        return view('calendar.holiday', ['list' => $list, 'data' => $data]);
    }

ここまで作ったら、再度動かしてみましょう。休日が削除できるはずです。


 php artisan serve --port 8080

URLアドレス:http://[servername]/

バリデーションを行います

コントローラーのなかのpostHolidayメソッドの中で次のコードを追加します。

app/Http/Controllers/CalendarController.php
・・(一部抜粋)・・
    public function postHoliday(Request $request)
    {
        $validatedData = $request->validate([
            'day' => 'required|date_format:Y-m-d',
            'description' => 'required',
        ]);

バリデーション結果のメッセージを表示するためにViewに次のコードを書きます。

resources/views/calendar/holiday.blade.php
・・(一部抜粋)・・
@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

ここまで作ったら、再度動かしてみましょう。休日のフォームで空のときバリデーションが機能し、登録できないはずです。


 php artisan serve --port 8080

URLアドレス:http://[servername]/

日本語化のため

resources/lang/ja/validation.phpを上記URLで取得したvalidation.phpで置き換えます。
フォーム項目名の日本語化は同ファイルのattributesで定義します。

resources/lang/ja/validation.php
・・(一部抜粋)・・
    'attributes' => [
        'day' => '日付',
        'description' => '説明',
    ],

以上、これで完了です。

ソース Github

25
25
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
25