LaravelでTodoアプリを作成していきます。
Contents
環境構築を実施していない方はこちら
完成版はこちら
DockerのPHPコンテナにログイン
$ docker compose exec php bash
Laravel インストール
$ composer create-project laravel/laravel="7.*" laravel
データベースの設定
$ vi .env
Mysqlを使用する場合
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=todo
DB_USERNAME=todo
DB_PASSWORD=todo
SQLiteを使用する場合
DB_CONNECTION=sqlite
$ cd database
$ touch database.sqlite
アプリケーションの設計
- モデル名は「Todo」とします
- テーブル名は「todos」になります。
- コントローラー名は「TodosController」とします
テーブル構成
- id
- body:todoの内容
- created_at
- updated_at
※idとcreated_atとupdate_atは自動で作成されます。
実装
モデルとマイグレーションファイルの作成
$ cd .. (プロジェクトフォルダ直下に戻る)
$ php artisan make:model Todo --migration
Model created successfully.
Created Migration: 2019_12_14_015752_create_todos_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateTodosTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('todos', function (Blueprint $table) {
$table->id();
+ $table->text('body');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('todos');
}
}
不要なマイグレーションファイルの削除
$ cd database/migrations
$ls -al
total 20
drwxr-xr-x 7 root root 224 Sep 18 09:18 .
drwxr-xr-x 6 root root 192 Sep 7 14:33 ..
-rw-r--r-- 1 root root 798 Sep 7 14:33 2014_10_12_000000_create_users_table.php
-rw-r--r-- 1 root root 683 Sep 7 14:33 2014_10_12_100000_create_password_resets_table.php
-rw-r--r-- 1 root root 820 Sep 7 14:33 2019_08_19_000000_create_failed_jobs_table.php
-rw-r--r-- 1 root root 876 Sep 7 14:33 2019_12_14_000001_create_personal_access_tokens_table.php
-rw-r--r-- 1 root root 608 Sep 18 09:21 2021_09_18_091856_create_todos_table.php
$ rm 2014_10_12_000000_create_users_table.php
$ rm 2014_10_12_100000_create_password_resets_table.php
$ rm 2019_08_19_000000_create_failed_jobs_table.php
$ rm 2019_12_14_000001_create_personal_access_tokens_table.php
マイグレーションの実行
$ php artisan migrate
Migrating: 2021_09_18_100152_create_todos_table
Migrated: 2021_09_18_100152_create_todos_table (0.07 seconds)
ルーティングの作成
$ vi routes/web.php
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
//以下をコメントアウトする
//Route::get('/', function () {
// return view('welcome');
//});
use Illuminate\Routing\Route;
Route::get('/','TodosController@index');
Route::resource('todos','TodosController');
コントローラーの作成
$ php artisan make:controller TodosController
$ vi
Todosコントローラーでは、todoの一覧、新規登録処理、削除処理、更新処理を書いていきます。
<?php
namespace App\Http\Controllers;
use App\Http\Requests\TodoRequest;
use Illuminate\Http\Request;
use App\Todo;
class TodosController extends Controller
{
public function index() {
$todos = Todo::all();
return view('todos.index')->with('todos',$todos);
}
public function store(TodoRequest $request) {
$todo = new Todo();
$todo->body = $request->body;
$todo->save();
return redirect('/');
}
public function destroy(todo $todo) {
$todo->delete();
return redirect('/');
}
public function edit(todo $todo) {
return view('todos.edit')->with('todo',$todo);
}
public function update(TodoRequest $request,todo $todo) {
$todo->body = $request->body;
$todo->save();
return redirect('/');
}
}
リクエストバリデーターを作成
$ php artisan make:request TodoRequest
Request created successfully.
$ vi app/Http/Requests/TodoRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class TodoRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'body' => 'required'
];
}
public function messages()
{
return [
'body.required' => '入力してください。'
];
}
}
見た目の部分(View)の作成
todo一覧ページ
$ cd resources/views
$ mkdir todos (todos関連のディレクトリを作成)
$ cd todos
$ vi index.blade.php (viewファイルの作成)
<!doctype html>
<html lang="ja">
<head>
<title>Jum Todoリスト</title>
<!-- 必要なメタタグ -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
<div class="container" style="margin-top:50px;">
<h1>Todoリスト追加</h1>
<form action='{{ url('/todos')}}' method="post">
{{csrf_field()}}
<div class="form-group">
<label >やることを追加してください</label>
<input type="text" name="body"class="form-control" placeholder="todo list" style="max-width:1000px;">
</div>
<button type="submit" class="btn btn-primary">追加する</button> </form>
<h1 style="margin-top:50px;">Todoリスト</h1>
<table class="table table-striped" style="max-width:1000px; margin-top:20px;">
<!-- <thead>
<tr>
<th></th><th></th><th></th>
</tr>
</thead> -->
<tbody>
@foreach ($todos as $todo)
<tr>
<td>{{$todo->body}}</td>
<td><form action="{{ action('TodosController@edit', $todo) }}" method="post">
{{ csrf_field() }}
{{ method_field('get') }}
<button type="submit" class="btn btn-primary">編集</button>
</form>
</td>
<!-- 削除ボタン -->
<td><form action="{{url('/todos', $todo->id)}}" method="post">
{{ csrf_field() }}
{{ method_field('delete') }}
<button type="submit" class="btn btn-danger">削除</button>
</form>
</td>
<!-- 削除した際にポップ画面で確認をする -->
<!-- <td><a class="del" data-id="{{ $todo->id }}" href="#">削除</a>
<form method="post" action='{{ url('/todos', $todo->id) }}' id="form_{{ $todo->id}}">
{{ csrf_field() }}
{{ method_field('delete') }}
</form>
</td> -->
</tr>
@endforeach
</table>
</div>
<!-- オプションのJavaScript -->
<!-- 最初にjQuery、次にPopper.js、次にBootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script>
(function() {
'use strict';
var cmds = document.getElementsByClassName('del');
var i;
for (i = 0; i < cmds.length; i++) {
cmds[i].addEventListener('click', function(e) {
e.preventDefault();
if (confirm('are you sure?')) {
document.getElementById('form_' + this.dataset.id).submit();
}
});
}
})();
</script>
</body>
</html>
todo編集ページ
$ cd resources/views/todos
$ touch edit.blade.php
<!doctype html>
<html lang="ja">
<head>
<title>Jum Todoリスト</title>
<!-- 必要なメタタグ -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
<div class="container" style="margin-top:50px;">
<h1>Todoリスト更新</h1>
<form action='{{ url('/todos',$todo->id) }}' method="post">
{{csrf_field()}}
{{ method_field('patch')}}
<div class="form-group">
<label >やることを更新してください</label>
<input type="text" name="body"class="form-control" value="{{ $todo->body }}" style="max-width:1000px;">
</div>
<button type="submit" class="btn btn-primary">更新する</button>
</form>
</div>
<!-- オプションのJavaScript -->
<!-- 最初にjQuery、次にPopper.js、次にBootstrap JS -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script>
(function() {
'use strict';
var cmds = document.getElementsByClassName('del');
var i;
for (i = 0; i < cmds.length; i++) {
cmds[i].addEventListener('click', function(e) {
e.preventDefault();
if (confirm('are you sure?')) {
document.getElementById('form_' + this.dataset.id).submit();
}
});
}
})();
</script>
</body>
</html>
完成です!!
スポンサーリンク
スポンサーリンク