Laravel10でスケジュールシステムを作成しました。間もなく2023年2月7日にLaravel10がリリースされますが、本日はまだ2023年1月です。Laravel10 dev 開発版で作成しました。FullCalendar等ライブラリを使わずに、フロント部分については、ゴリゴリPHPでプログラムを書いて作りました。
はじめに
Laravel プロジェクトの作成
windowsのコマンドプロンプトあるいはVisualStudioのターミナルで行います。
Laravel10の開発版10.x-devを導入するには、10開発版を指定する必要があります。このようにしてプロジェクトを作成しました。
1 |
composer create-project "laravel/laravel=10.x-dev" lara10 |
通常は(Laravel10リリース)2023年2月7日?以降は、下のコマンドで良いです。
1 |
composer create-project --prefer-dist laravel/laravel lara1 |
1 |
cd lara1 |
作成したディレクトリに移動します。開発用サーバを起動します。
1 |
php artisan serve |
laravelのenvファイル DB設定を DB_DATABASE=lara1 とします。
次にLaravel Breezeを導入するためのお決まりのコマンドを入力します。
composer require laravel/breeze –dev
php artisan breeze:install
php artisan migrate
npm install
npm run dev
こちらのブログシステムに機能追加として作成していきました。ユーザーアカウントを三名追加しておきます。
schedules テーブルの作成
マイグレーションファイルを作成します。
1 |
php artisan make:migration create_schedules_table |
生成された database\migrations\2023_01_08_144153_create_schedules_table.php のカラムを拡張します。
タイトル title 、 日付 yyyymmdd、 登録者 user_id のカラムを追加します。
1 2 3 4 5 6 7 8 |
// Schema::create('schedules', function (Blueprint $table) { $table->id(); $table->string('title'); $table->date('yyyymmdd'); $table->integer('user_id')->unsigned; $table->timestamps(); }); |
以下のようにマイグレーションを実行し、Scheduleモデルを作成し、ScheduleFactoryを作成します。
1 2 3 4 |
// php artisan migrate php artisan make:model Schedule php artisan make:factory ScheduleFactory |
ダミーデータを作成
生成された database\factories\ScheduleFactory.php ファクトリーに以下追加します。destinationメソッド内です。
1 2 3 4 5 6 7 8 9 10 |
public function definition() { return [ 'title' => $this->faker->realText(20), 'yyyymmdd' => $this->faker->dateTimeBetween($startDate = '-6 week', $endDate = '+9 week'), 'user_id' => $this->faker->numberBetween($min = 1, $max = 3), 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ]; } |
シーダーを作成します。
1 |
php artisan make:seeder SchedulesSeeder |
database\seeders\SchedulesSeeder.php が生成されます。
runメソッドの中は、
Schedule::factory()->count(70)->create();
とします。
php artisan db:seed –class=SchedulesSeeder
以下のように70件のダミーデータが生成されました!
ホワイトリストの設定、Usersテーブルとのリレーション設定
1 2 3 4 5 6 7 8 9 10 |
use HasFactory; protected $fillable = [ 'title', 'yyyymmdd', 'user_id', ]; //リレーション追加 public function user() { return $this->belongsTo(User::class); } |
1 2 3 4 5 |
// Scheduleとのリレーションを追加 public function schedules() { return $this->hasMany(Schedule::class); } |
Scheduleコントローラーの作成
コントローラーを作成します。
1 |
php artisan make:controller ScheduleController --resource --model=Schedule |
後ほど、コントローラー内を編集していきます。
ルーティングの設定
web.phpを編集します。以下 ルーティング設定を追記します。
1 2 3 4 5 6 7 |
//スケジュール Route::get('/schedules', 'App\Http\Controllers\ScheduleController@index')->name('schedule.index'); Route::get('/schedules/create', 'App\Http\Controllers\ScheduleController@create')->name('schedule.create')->middleware('auth'); Route::post('/schedules/store/', 'App\Http\Controllers\ScheduleController@store')->name('schedule.store')->middleware('auth'); Route::get('/schedules/edit/{schedule}', 'App\Http\Controllers\ScheduleController@edit')->name('schedule.edit')->middleware('auth'); Route::put('/schedules/edit/{schedule}','App\Http\Controllers\ScheduleController@update')->name('schedule.update')->middleware('auth'); Route::delete('/schedules/{schedule}','App\Http\Controllers\ScheduleController@destroy')->name('schedule.destroy')->middleware('auth'); |
indexメソッド
月毎のカレンダーにテーブルの情報を出力するために、コントローラーのindexメソッドから始めます。
GETパラメータpageが空の場合は、当月として変数pageに0が格納されます。何か月先か前かはGETパラメータpageで取得して、何年何月かを判定しています。schedulesテーブルからはwhere句で、該当月のレコードだけを配列Schedulesに取得するようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public function index() { $page = request()->input('page'); if(!$page){ $page=0; } $yyyy = date('Y',strtotime("+$page month")); $mm = date('m',strtotime("+$page month")); $days = date('d',mktime(0,0,0,date('m')+($page+1),0,date('Y'))); $schedules = Schedule::where('yyyymmdd', 'LIKE', $yyyy.'-'.$mm.'-%')->get(); //dd($schedules); return view('sche_index',compact('page','yyyy','mm','days','schedules')); } |
ブレードファイル resources\views\sche_index.blade.php を作成します。index.blade.phpとしても良かったのですが、ブログシステムで既に使っているため、sche_index.blade.phpとしました。階層を深くしてもよかったですね。
ブレードファイルの中で@php~ ゴリゴリPHPを書いています。配列schedulesの中身を、日毎の配列に入れなおしています。コントローラー側でやっても良いですが。
app.blade.phpは、Laravel10でブログシステム作成│ちからえもんWEB・WINDOWSプログラミング (chikaraemon.com)
をご参照ください。
sche_index.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
@extends('app') @section('content') <div class="w-75"> <div> <h3 style="font-size:1.45rem;">{{$yyyy}}年{{$mm}}月は、{{$days}}日まであります。</h3> <a href="{{ url('./schedules/') }}?page={{$page-1}}" class="btn btn-sm btn-secondary">前の月</a> <a href="{{ url('./schedules/') }}?page=0" class="btn btn-sm btn-secondary">今月</a> <a href="{{ url('./schedules/') }}?page={{$page+1}}" class="btn btn-sm btn-secondary">次の月</a> </div> @php foreach($schedules as $schedule){ //echo $schedule->yyyymmdd; //echo $schedule->title; //echo $schedule->user_id; //echo "<BR>"; for ($i = 1; $i <= 31; $i++){ if ($i < 10) { $i = '0' . $i; } if ( substr($schedule->yyyymmdd,8,2) == $i ){ if(isset($title[$i])){ $title[$i].="<div>".$schedule->title."</div>"; }else{ $title[$i] ="<div>".$schedule->title."</div>"; } $title[$i].="<div class='text-end'>"; $title[$i].="<span>by ".$schedule->user->name." </span>"; $title[$i].="<span><a href='".route('schedule.edit',[ $schedule->id, 'page' => request()->input('page') ])."'>編集</a></span>"; $title[$i].="</div>"; } } } @endphp </div> <table class="table w-75"> @for ($i = 1; $i <= $days; $i++) <tr> <td style="width: 25%;"> @php if ($i < 10) { $i = '0' . $i; } @endphp <div class=" @if(date('D', strtotime($yyyy.$mm.$i))=='Sun') text-danger @elseif(date('D', strtotime($yyyy.$mm.$i))=='Sat') text-primary @endif "> {{$yyyy}}/{{$mm}}/{{ $i }} {{date('D', strtotime($yyyy.$mm.$i))}} </div> </td> <td style="width: 65%;"> @php if(isset($title[$i])){ echo $title[$i]; } @endphp </td> <td> <a class="btn btn-sm btn-primary" href="{{ route('schedule.create',['dd' => $i, 'page' => request()->input('page')]) }}"> 登録</a> </td> </tr> @endfor </table> @endsection |
ちゃんとカレンダーが表示されました!また、schedulesテーブルの2023/01のレコードも出力されています。
次の月、前の月をクリックしてそれぞれの該当月のスケジュールも確認できます。
create、storeメソッド
コントローラーのcreateメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
*/ public function create() { $page = request()->input('page'); if(!$page){ $page=0; } $yyyy = date('Y',strtotime("+$page month")); $mm = date('m',strtotime("+$page month")); $dd = request()->input('dd'); //dd($dd); return view('sche_create',compact('yyyy','mm','dd','page')); } |
ブレードファイル resources\views\sche_create.blade.php を作成します。
sche_create.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
@extends('app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2 style="font-size:1rem;">登録画面</h2> </div> <div class="pull-right"> <a class="btn btn-success" href="{{ url('/schedules') }}?page={{ request()->input('page') }}">戻る</a> </div> </div> </div> <div style=""> <h2 style="font-size: 1.45rem;" class="mt-2">{{$yyyy}}年{{$mm}}月{{$dd}}日の予定を登録してください</h2> <form action="{{ route('schedule.store') }}" method="POST"> @csrf <div class="row w-75"> <div class="col-12 mb-2 mt-2"> <div class="form-group"> <input type="text" name="title" class="form-control" placeholder="予定"> </div> </div> <div class="col-12 mb-2 mt-2"> <input type="hidden" name="yyyy" value="{{$yyyy}}"> <input type="hidden" name="mm" value="{{$mm}}"> <input type="hidden" name="dd" value="{{$dd}}"> <input type="hidden" name="page" value="{{$page}}"> <button type="submit" class="btn btn-primary w-100">登録</button> </div> </div> </form> </div> @endsection |
コントローラーの store メソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public function store(Request $request) { $request->validate([ 'title' => 'required', 'yyyy' => 'required', 'mm' => 'required', 'dd' => 'required', ]); $schedule = new Schedule; $schedule->title = $request->input(["title"]); $schedule->yyyymmdd = $request->input(["yyyy"])."-".$request->input(["mm"])."-".$request->input(["dd"]); $schedule->user_id = \Auth::user()->id; $schedule->save(); $page = $request->input(["page"]); $yyyy = $request->input(["yyyy"]); $mm = $request->input(["mm"]); return redirect()->route('schedule.index',compact('page','yyyy','mm')) ->with('success','登録しました'); } |
登録の動作確認
2023/3/3の登録ボタンをクリックします。
2023年3月3日の予定登録フォームが表示されます。コントローラーから、yyyy,mm,dd,page 四つの変数から情報を受け取っていることが重要です。
1 2 3 4 5 |
@if ($message = Session::get('success')) <div class="alert alert-success w-75"> <p>{{ $message }}</p> </div> @endif |
edit、updateメソッド
次に予定を変更するためのeditメソッドです。フォームリクエストを受け取るために第二引数に$requestを指定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//引数 Request $request を追加 public function edit(Schedule $schedule,Request $request) { $schedules = Schedule::all(); $yyyy = substr($schedule->yyyymmdd,0,4); $mm = substr($schedule->yyyymmdd,5,2); $dd = substr($schedule->yyyymmdd,8,2); $page = $request->input(["page"]); if(!$page){ $page=0; } return view('sche_edit',compact('schedule','page','yyyy','mm','dd')); } |
ブレードファイル resources\views\sche_edit.blade.php を作成します。このフォームから変更と削除ができるようにしますので、二つ目のform~は削除フォームとなります。
sche_edit.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
@extends('app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2 style="font-size:1rem;">編集画面</h2> </div> <div class="pull-right"> <a class="btn btn-success" href="{{ url('/schedules') }}?page={{ request()->input('page') }}"> ページ番号{{ request()->input('page') }}に戻る</a> </div> </div> </div> <div style=""> <h2 style="font-size: 1.45rem;" class="mt-2">{{$yyyy}}年{{$mm}}月{{$dd}}日の予定を編集してください</h2> <form action="{{ route('schedule.update',$schedule->id) }}" method="POST"> @method('PUT') @csrf <div class="row w-75"> <div class="col-12 mb-2 mt-2"> <div class="form-group"> <input type="text" name="title" value="{{ $schedule->title }}" class="form-control" placeholder="タイトル"> </div> </div> <div class="col-12 mb-2 mt-2"> <input type="hidden" name="page" value="{{ request()->input('page') }}"> <button type="submit" class="btn btn-primary w-100">編集</button> </div> </div> </form> <form action="{{ route('schedule.destroy',$schedule->id) }}" method="POST"> @method('DELETE') @csrf <div class="row w-75"> <div class="col-12 mb-2 mt-2"> <input type="hidden" name="page" value="{{ request()->input('page') }}"> <button type="submit" class="btn btn-danger w-25">削除</button> </div> </div> </form> </div> @endsection |
updateメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public function update(Request $request, Schedule $schedule) { $request->validate([ 'title' => 'required', ]); $schedule->title = $request->input(["title"]); $schedule->user_id = \Auth::user()->id; $schedule->save(); $page = request()->input('page'); return redirect()->route('schedule.index', ['page' => $page]) ->with('success','更新しました'); } |
変更の動作確認
登録してある予定が変更できるのか動作を確認します。ひな祭りを編集します。編集リンクをクリックします。
予定を変更します。
変更が確認できました!
destroyメソッド
予定を削除するためのdestroyメソッドです。
1 2 3 4 5 6 7 |
public function destroy(Schedule $schedule) { $schedule->delete(); $page = request()->input('page'); return redirect()->route('schedule.index', ['page' => $page]) ->with('success',$schedule->title.'を削除しました'); } |
2023/3/3のひな祭りを削除します。下のように削除ができました!
今回は、Laravel の中に PHP的なプログラムを比較的ゴリゴリ書いてみましたが、結構楽しかったです!