LaravelでTodoリストを実装してみよう!~実装編1:Todo一覧の閲覧機能を実装~
はじめに
前回の記事で環境構築を済ませたので、今回はTodoリストの機能を一つずつ作っていこうと思います。
前回の記事はこちら↓
テーブルの作成
まずは、Todoリストのデータを格納するテーブルを作ります。
マイグレーションファイルを生成
テーブルの設計ファイルを生成するには以下のコマンドを実行します。
todolists
の部分がテーブル名になるので好きな名前を付けてください。
sail artisan make:migration create_todolists_table
コマンドを実行すると、以下のようなファイルが生成されます。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('todolists', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('todolists');
}
};
up
メソッドの中で呼び出されているcreate
メソッドで、$table->型名(カラム名)
のように記述していくことで、テーブルのカラムを設定することができます。
前々回の設計編でTodolistsテーブルを以下のように定義したので、それに合わせて書き換えていきます。
Todolistsテーブルの設計
カラム名 | 説明 |
---|---|
ID(PK) | Todoをユニークに識別するためのID |
ユーザーID(FK) | どのユーザーのTodoかを識別するためのIDでユーザーテーブルからの外部キー |
内容 | どんなTodoかを記録するカラム |
期限 | いつまでに終わらせるかを記録するカラム |
完了状態 | そのTodoが完了したものかを判別するカラム(True/False) |
作成日時 | いつ作成されたのかを記録するカラム |
更新日時 | いつ更新されたかを記録するカラム |
public function up(): void
{
Schema::create('todolists', function (Blueprint $table) {
$table->id();
+ $table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
+ $table->string('content');
+ $table->date('deadline');
+ $table->boolean('status')->default(0);
$table->timestamps();
});
}
user_id
は外部キーなのでforeignId('user_id')->constrained('users')
を用いて外部キーであることとどこのテーブルから持ってきているのかを指定します。
cascadeOnDelete()
を指定した場合、外部キー下のテーブル(今回はusersテーブル)から引っ張ってきているIDの持つレコードが削除されたら、一緒にcascadeOnDelete
を指定されたレコードも削除されます。
今回のTodoアプリの場合は、ユーザーが削除されたら、ユーザーが作成したTodoも一緒に削除されるということです。
$table->boolean('status')->default(0)
は、完了状態を表すstatus
カラムをboolean型
にしてデフォルトの値を0
に設定しています。
マイグレーション
前節で、todolists
テーブルの設計ができたので、mysql
に反映していきます。
データーベースに反映するには、以下のコマンドを実行します。
sail artisan migrate
処理が完了したら、テーブルが作られているか確認してみましょう。
まずmysql
にアクセスします。
sail mysql
次に、todolists
テーブルがきちんと生成されている確認するために、以下のコマンドを実行します。
show columns from todolists
テーブルが生成されていれば、以下のようなテーブルが表示されると思います。
+------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| user_id | bigint unsigned | NO | MUL | NULL | |
| content | varchar(255) | NO | | NULL | |
| deadline | date | NO | | NULL | |
| status | tinyint(1) | NO | | 0 | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+-----------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
これで、Todolists
テーブルを無事つくりことができました!
Eloquentモデルの生成
前節で、生成したいテーブルを設計してデーターベースに反映しました。
次に、PHPからデーターベースを操作するためにEloquent ORMのモデルを作成します。
Eloquent ORMとは、Lravel利用されるオブジェクトリレーショナルマッパー(ORM)です。
ORMとは、リレーショナルデーターベースとオブジェクトを相互変換して、オブジェクト指向プログラミング言語を用いて、データーベースを操作するための機能やソフトウェアのことを指します。
実際に、モデルを生成していきましょう。生成するには以下のコマンドを実行します。
sail artisan make:model Todolist
処理が完了すると、app/Models/Todolist.php
というファイルが生成されます。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Todolist extends Model
{
use HasFactory;
}
簡素な記述ですが、これでEloquentモデルとして機能します。
これで、データーベースを操作する準備が整いました。
シーディングとファクトリーの生成
次に、疑似データを生成して、実際にテーブルにデータを挿入してみましょう!
このような疑似データを生成する機能をLaravelは備えているようです。
それが、Seeder
とFactory
です。
Seeder
とは、データベースにデータの初期値を挿入するための機能で、Factory
とは、Eloquentモデルに対してデフォルトの属性値を設定する機能です。
Factory
で生成する疑似データの形を記述して、Seeder
で生成する命令を記述するイメージです。
(少なくとも私は、このイメージで理解しています。間違ってたらごめんなさい)
実際に、Factory
とSeeder
を生成して、疑似データを作っていきましょう。
ファクトリーの生成
まず、Factory
を生成します。生成には以下のコマンドを実行します。
sail artisan make:factory TodolistFactory --model=Todolist
--model=モデル名
で、関連付けるEloquentモデルを指定します。
今回はTodolist
モデルのファクトリーを作りたかったので、Todolist
モデルを指定しています。
処理が終了すると、database/factories/TodolistFactory.php
というファイルが生成されます。
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Todolist>
*/
class TodolistFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
//
];
}
}
definition
メソッドの内容を以下のように加筆します。
public function definition(): array
{
return [
+ 'user_id' => 1,
+ 'content' => $this->faker->realText(30),
+ 'deadline' => $this->faker->date(),
+ 'status' => $this->faker->boolean(),
];
}
$this->faker
はダミーを生成してくれるFakerライブラリを呼び出しています。
それぞれのカラムに適した型のダミーを生成しています。
Seederの生成:TodoSeeder
Factory
を記述したので、続いてSeeder
を生成して記述していきます。
Seeder
を生成するには以下のコマンドを実行します。
sail artisan make:seeder TodoSeeder
処理が完了すると、database/seeders/TodoSeeder.php
が生成されます。
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class TodoSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}
TodoSeeder.php
を以下のように書き換えます.
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
+ use App\Models\Todolist;
class TodoSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
+ Todolist::factory()->count(30)->create();
}
}
factory()->count(30)->create()
で、Factory
設定した属性のダミーを30個生成します。
Seederの生成:UserSeeder
Todolists
テーブルには外部キーとしてUsers
テーブルのid
を参照しているので、Users
テーブルのダミーデータも生成します。
以下のコマンドを実行して、Users
テーブルのSeeder
を生成します。
sail artisan make:seeder UserSeeder
Todolists
と同じ要領で、UserSeeder.php
を書き換えていきます。
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class UserSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
User::factory()->create();
}
}
ダミーデータ生成
それでは、実際に以下のコマンドを実行して、ダミーデータを生成してみましょう!
sail artisan db:seed
実際に生成できたのか確認してみます。まずは、mysql
にアクセス!
sail mysql
ひとまずUsers
のダミーデータを確認しましょう。
select * from users;
以下のような、何かしらのレコードが入っていればOK!
+----+-----------+------------------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
| id | name | email | email_verified_at | password | remember_token | created_at | updated_at |
+----+-----------+------------------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
| 1 | Test User | test@example.com | 2024-04-24 05:19:59 | $2y$12$AWig4FfBKdyEnfX7ofOxteu3nGkYilAzN.bQydyRn9HwzbaD.tNaS | Oq1Kyv2z1p | 2024-04-24 05:19:59 | 2024-04-24 05:19:59 |
+----+-----------+------------------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
1 row in set (0.00 sec)
続いて、Todolists
のほうも確認!
select * from todolists;
Empty set (0.01 sec)
あれ?何も生成されてない。。。?
では、生成したいダミーデータを指定してシーディングしてみます。(exitでmysqlから抜けるの忘れずに!)
sail artisan db:seed --class=TodoSeeder
処理が終了したら再度mysql
にアクセスして確かめてみましょう
sail mysql
select * from todolists;
+----+---------+-------------------------------+------------+--------+---------------------+---------------------+
| id | user_id | content | deadline | status | created_at | updated_at |
+----+---------+-------------------------------+------------+--------+---------------------+---------------------+
| 1 | 1 | The twelve jurors were all. | 1980-12-29 | 1 | 2024-04-24 05:21:32 | 2024-04-24 05:21:32 |
////省略/////
| 29 | 1 | Gryphon, and the Hatter went. | 1972-02-13 | 0 | 2024-04-24 05:21:32 | 2024-04-24 05:21:32 |
| 30 | 1 | He looked at Two. Two began. | 1979-07-23 | 1 | 2024-04-24 05:21:32 | 2024-04-24 05:21:32 |
+----+---------+-------------------------------+------------+--------+---------------------+---------------------+
30 rows in set (0.00 sec)
30個ダミーデータが生成されています!
先ほど生成されなかったのは、おそらくusers
テーブルのid
を外部キーとして持っており、外部キーであるuser_id
がない場合、レコードを削除する設定にしているので、todolists
テーブルのダミーデータがusers
テーブルのデータより先に作られた場合、参照元であるusers
テーブルのデータがないことになるので、ダミーデータが生成された瞬間に削除されていると考えられます。
ダミーデータを日本語化したい人向け
ダミーデータを日本語化するには、.env
ファイルを以下のように書き換えます。
APP_LOCALE=ja
APP_FALLBACK_LOCALE=ja
APP_FAKER_LOCALE=ja_JP
それでは、再度シーディングを実行して、日本語になる確認します。
テーブルをマイグレーションしなおしてからシーディングするには、以下のコマンドを実行します。
sail artisan migrate:refresh --seed
念のため、TodoSeeder
を指定してシーディングしておきます。
sail artisan db:seed --class=TodoSeeder
mysql
にアクセスしてデーターベースを確認してみましょう。
sail mysql
select * from todolists;
+----+---------+--------------------------------+------------+--------+---------------------+---------------------+
| id | user_id | content | deadline | status | created_at | updated_at |
+----+---------+--------------------------------+------------+--------+---------------------+---------------------+
| 1 | 1 | ?????????????????????????????? | 1990-08-22 | 1 | 2024-04-25 19:15:20 | 2024-04-25 19:15:20 |
/// 省略 ///
| 29 | 1 | ?????????????????????????????? | 1985-03-29 | 1 | 2024-04-25 19:15:20 | 2024-04-25 19:15:20 |
| 30 | 1 | ?????????????????????????????? | 2019-04-18 | 1 | 2024-04-25 19:15:20 | 2024-04-25 19:15:20 |
+----+---------+--------------------------------+------------+--------+---------------------+---------------------+
30 rows in set (0.00 sec)
あれ?うまく日本語化できてない。。。。
おそらく文字化けの類だと思われるので、文字コードを確認。
show variables like '%char%';
+--------------------------+--------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql-8.0/charsets/ |
+--------------------------+--------------------------------+
8 rows in set (0.01 sec)
以下の記事によると、文字コードをlatin1
からutf8mb4
にしてあげるとよいらしい。
以下のコマンドで、プロジェクトのディレクトリ直下にmy.cnf
ファイルを作ります。
touch my.cnf
my.cnf
ファイルを以下のように書き換えます。
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
[client]
default-character-set=utf8mb4
続いて、docker-compose.yml
ファイルのmysql
の設定を以下のように書き換えます。
~~~~~~~~~~~~ 省略 ~~~~~~~~~~~~
mysql:
image: 'mysql/mysql-server:8.0'
ports:
- '${FORWARD_DB_PORT:-3306}:3306'
environment:
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
MYSQL_ROOT_HOST: '%'
MYSQL_DATABASE: '${DB_DATABASE}'
MYSQL_USER: '${DB_USERNAME}'
MYSQL_PASSWORD: '${DB_PASSWORD}'
MYSQL_ALLOW_EMPTY_PASSWORD: 1
volumes:
- 'sail-mysql:/var/lib/mysql'
- './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
+ - './my.cnf:/etc/my.cnf'
networks:
- sail
healthcheck:
test:
- CMD
- mysqladmin
- ping
- '-p${DB_PASSWORD}'
retries: 3
timeout: 5s
~~~~~~~~~~~~ 省略 ~~~~~~~~~~~~
各々のファイルを編集し終えたら、以下のコマンドで一度コンテナを終了させてから、起動しないします。
sail down
sail up -d
コンテナの起動を確認出来たら、mysql
にアクセスして、文字コードが変わっているか確認します。
sail mysql
show variables like '%char%';
+--------------------------+--------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql-8.0/charsets/ |
+--------------------------+--------------------------------+
8 rows in set (0.00 sec)
ちゃんと、utf8mb4
に代わっているようです。
もう一度、todolists
テーブルの中身を確認してみましょう。
select * from todolists;
+----+---------+--------------------------------------------------------------------------------------------+------------+--------+---------------------+---------------------+
| id | user_id | content | deadline | status | created_at | updated_at |
+----+---------+--------------------------------------------------------------------------------------------+------------+--------+---------------------+---------------------+
| 1 | 1 | 知しょうぶだと言いうちに進すすきの本の電燈でんとうと思った。 | 1996-02-09 | 0 | 2024-04-25 20:19:13 | 2024-04-25 20:19:13 |
| 2 | 1 | 歌い出してそれをくらいていました。(ザネリがやはげしいんで。 | 1997-07-16 | 0 | 2024-04-25 20:19:13 | 2024-04-25 20:19:13 |
~~~~~~~~~~~~~ 省略 ~~~~~~~~~~~~~
| 30 | 1 | んぼうにどこでした。そこにこんなほんという光をあけていまの。 | 2003-10-25 | 1 | 2024-04-25 20:19:13 | 2024-04-25 20:19:13 |
+----+---------+--------------------------------------------------------------------------------------------+------------+--------+---------------------+---------------------+
30 rows in set (0.00 sec)
ちゃんと日本語が表示されました!
コントローラーの作成
次に、モデルやビューを制御するコントローラーを作成して行きます。
コントローラーファイルの生成
以下のコマンドを実行して、コントローラーを生成していきます。
sail artisan make:controller Todolist/TodolistController --invokable
処理が終了すると、app/Http/Controllers/Todolist/TodolistController.php
というファイルが生成されます。
中身は以下の通り。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TodolistController extends Controller
{
/**
* Handle the incoming request.
*/
public function __invoke(Request $request)
{
//
}
}
コントローラーファイルの編集
TodolistController.php
の内容を以下のように書き換えます。
////////// 省略 //////////
+ use App\Models\Todolist;
use Illuminate\Http\Request;
class TodolistController extends Controller
{
/**
* Handle the incoming request.
*/
public function __invoke(Request $request)
{
+ $todolists = Todolist::where([['status', '=', 0]])->get();
+ return view('todolist.todolist')->with([
+ 'todolists' => $todolists]);
}
}
Todolist::where([['status', '=', 0]])->get();
によって、todolists
テーブルのstatus
カラムが0
のレコードを取得しています。
return view('todolist.todolist')->with(['todolists' => $todolists]);
でresources/views/todolist/todolist.blade.php
(次章で作ります)を呼び出しています。
その際、データベースから取得したデータであるtodolists
もtodolist.blade.php
に渡しています。
ルーティング
コントローラーを作り終わったので、ビューを作成する前に、ルーティングを設定して画面をブラウザに表示できる状態にしましょう。
ルーティングを設定するには、routes/web.php
に書き加えていきます。
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Route::get('todolist', \App\Http\Controllers\Todolist\TodolistController::class)
->name('todolist');
ひとまずこれでOKです!
ビューの作成
いよいよ画面表示部分であるビューを作成していきます。
設計時に書いた完成予想画面はこんな感じ。
Viteのインストール
まず最初に、Vite
をインストールしていきます。
Viteは、非常に高速な開発環境を提供してくれる、コードを本番用に構築する最新のフロントエンド・ビルド・ツールです。Laravelでアプリケーションを構築する場合、通常、Viteを使用してアプリケーションのCSSとJavaScriptファイルを本番環境用のアセットへ構築することになります。
Vite
をインストールするには、以下のコマンドを実行します。
sail npm install
Taidwindcssのインストール
ビュー作成作業に入る前に、Tailwindcssをインストールする。
Tailwindcss
とは画面の装飾を行うcss
のフレームワークの一種です。
比較的簡単かつ効率よく画面の装飾できるので、採用しています!
(ともっともらしいこと言ってみましたが、最初に触った教本がtailwindを使っていただけです。。。)
以下のコマンドを実行して、tailwindcss
をインストールします。
sail npm install -D tailwindcss postcss autoprefixer
sail npx tailwindcss init -p
処理が終了すると、tailwind.config.js
とpostcss.config.js
というファイルが生成されます。
それぞれのファイルの中身は以下の通り。
/** @type {import('tailwindcss').Config} */
export default {
content: [],
theme: {
extend: {},
},
plugins: [],
}
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
tailwind.config.js
を以下のように書き換えます。
/** @type {import('tailwindcss').Config} */
export default {
content: [
+ "./resources/**/*.blade.php",
+ "./resources/**/*.js",
+ "./resources/**/*.vue",
],
theme: {
extend: {},
},
plugins: [],
}
その後、resources/css/app.css
を以下のように書き換えます。
@tailwind base;
@tailwind components;
@tailwind utilities;
以下のコマンドを実行して、CSSサーバーを起動するとCSSがページに適用されます。
sail npm run dev
あとは、画面を作る際に、<head>
に @vite(['resources/css/app.css', 'resources/js/app.js'])
Bladeディレクティブを追加したら終わりです。
ビューファイルの生成
以下のコマンドを実行して、ビューファイルを作成します。
sail artisan make:view todolist.todolist
処理が終了すると、resources/views/todolist/todolist.blade.php
が生成されます。
コンポーネントの作成:レイアウト編
ここから画面をコーディングしていくのですが、画面のレイアウトやボタン等をいちいちべた書きしていくのは非効率なので、パーツに分けてコンポーネントとしてあらかじめ作っておきます。
コンポーネントファイルの生成は、以下のコマンドを実行します。
sail artisan make:component layout.layout --view
処理が終了すると、resources/views/components/layout/layout.blade.php
が生成されます。
layout.blade.php
には、主に<head>
部分を記述していきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@vite(['resources/css/app.css', 'resources/js/app.js'])
<title>{{ $title ?? Todoアプリ }}</title>
</head>
<body class="bg-gray-100">
{{ $slot }}
</body>
</html>
{{slot}}
に子要素(より詳細なレイアウトなど)が入ります。
Tailwindcssはclass
にCSSを直接記述することでCSSを反映させます。
bg-gray-100
は背景色を指定しています。
続いて、ヘッダーとフッターを記述した少し詳細なレイアウトを記述します。
同じ要領でコンポーネントファイルを生成します。
sail artisan make:component layout.todolist-single --view
処理が終了すると、resources/views/components/layout/todolist-single.blade.php
が生成されます。
todolist-single.blade.php
を以下のように書き換えます。
<div class="flex flex-col h-screen">
<header class="flex fixed top-0 bg-green-500 w-full items-center">
<h1>
<a href={{ route('todolist') }} class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-10 h-10">
<path d="M11.7 2.805a.75.75 0 0 1 .6 0A60.65 60.65 0 0 1 22.83 8.72a.75.75 0 0 1-.231 1.337 49.948 49.948 0 0 0-9.902 3.912l-.003.002c-.114.06-.227.119-.34.18a.75.75 0 0 1-.707 0A50.88 50.88 0 0 0 7.5 12.173v-.224c0-.131.067-.248.172-.311a54.615 54.615 0 0 1 4.653-2.52.75.75 0 0 0-.65-1.352 56.123 56.123 0 0 0-4.78 2.589 1.858 1.858 0 0 0-.859 1.228 49.803 49.803 0 0 0-4.634-1.527.75.75 0 0 1-.231-1.337A60.653 60.653 0 0 1 11.7 2.805Z" />
<path d="M13.06 15.473a48.45 48.45 0 0 1 7.666-3.282c.134 1.414.22 2.843.255 4.284a.75.75 0 0 1-.46.711 47.87 47.87 0 0 0-8.105 4.342.75.75 0 0 1-.832 0 47.87 47.87 0 0 0-8.104-4.342.75.75 0 0 1-.461-.71c.035-1.442.121-2.87.255-4.286.921.304 1.83.634 2.726.99v1.27a1.5 1.5 0 0 0-.14 2.508c-.09.38-.222.753-.397 1.11.452.213.901.434 1.346.66a6.727 6.727 0 0 0 .551-1.607 1.5 1.5 0 0 0 .14-2.67v-.645a48.549 48.549 0 0 1 3.44 1.667 2.25 2.25 0 0 0 2.12 0Z" />
<path d="M4.462 19.462c.42-.419.753-.89 1-1.395.453.214.902.435 1.347.662a6.742 6.742 0 0 1-1.286 1.794.75.75 0 0 1-1.06-1.06Z" />
</svg>
<p class="text-2xl">Todoアプリ</p>
</a>
</h1>
</header>
<div class="flex w-full justify-center items-center flex-grow py-10">
<div class="max-w-screen-lg w-auto">
{{ $slot }}
</div>
</div>
<footer class="flex fixed bottom-0 bg-green-500 w-full justify-center items-center">
©2024 Kenberu
</footer>
</div>
ここまで出来たら、resources/views/todolist/todolist.blade.php
を編集してページを表示させてみましょう!
<x-layout.layout title="リスト | Todoアプリ">
<x-layout.todolist-single>
{{-- ここに内容が入る --}}
</x-layout.todolist-single>
</x-layout.layout>
CSSサーバーが立ち上がっているのをきちんと確認して、http://localhost/todolist
にアクセスします。
以下のような画面になっていれば、正常に動作しています。
コンポーネントの作成:ボタン編
続いて、Todo一覧画面ので使うボタンを作っていきます。
上と同じ要領でボタンのコンポーネントファイルを生成します。
sail artisan make:component element.button-a --view
処理が終了すると、resources/views/components/element/button-list.blade.php
ファイルが生成されます。
button-list.blade.php
ファイルを以下のように書き換えます。
@props([
'href' => '',
'theme' => '',
])
@php
if (!function_exists('getThemeClassForButtonA')) {
function getThemeClassForButtonA($theme) {
return match ($theme) {
'add' => 'py-2 px-4 text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-500',
'undo' => 'py-2 px-4 text-white bg-green-500 hover:bg-green-600 focus:ring-green-500',
'edit' => 'py-4 px-4 text-white bg-green-500 hover:bg-green-600 focus:ring-green-500',
default => '',
};
}
}
@endphp
<a href="{{ $href }}" class="
inline-flex justify-center
ml-4
border border-transparent
shadow-sm
text-lg
font-medium
rounded-md
focus:outline-none focus:ring-2 focus:ring-offset-2
{{ getThemeClassForButtonA($theme) }}">
{{ $slot }}
</a>
次に、Todoを完了したときに押す完了ボタンを作ります。
sail artisan make:component element.button-check --view
生成されたresources/views/components/element/button-check.blade.php
ファイルを以下のように書き換えます。
<form action="{{ route('checktodo', ['todoId' => $todoId]) }}" method="POST">
@method('PUT')
@csrf
<button type="submit" class="
inline-flex justify-center
ml-4
py-2 px-2
text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-500
border border-transparent
shadow-sm
text-lg
font-medium
rounded-md
focus:outline-none focus:ring-2 focus:ring-offset-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
</svg>
</button>
</form>
さらに、Todoを削除するときに押す削除ボタンを作ります。
sail artisan make:component element.button-deltodo --view
生成されたresources/views/components/element/button-deltodo.blade.php
ファイルを以下のように書き換えます。
<form action="{{ route('deletetodo', ['todoId' => $todoId]) }}" method="POST" onclick="return confirm('削除してもよろしいですか?');">
@method('DELETE')
@csrf
<button type="submit" class="
inline-flex justify-center
ml-4
py-4 px-4
text-white bg-red-500 hover:bg-red-600 focus:ring-red-500
border border-transparent
shadow-sm
text-lg
font-medium
rounded-md
focus:outline-none focus:ring-2 focus:ring-offset-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
</button>
</form>
Todo一覧画面の作成
必要なパーツはすべて作ったので、いよいよTodo一覧画面を作成していきましょう!
resources/views/todolist/todolist.blade.php
ファイルを以下のように書き換えます。
@props([
'user_name' => '',
'todolists' => [],
])
<x-layout.layout title="リスト | Todoアプリ">
<x-layout.todolist-single>
<ul class=" font-medium justify-start w-max">
<li class="flex sticky top-10 mb-4 lg:col-span-1 items-center text-xl bg-gray-100 border-b-4 border-gray-500">
<div class="flex ml-4 w-10">
</div>
<div class="flex ml-3 w-96">
「{{ $user_name }}」さんのTodo
</div>
<div class="flex ml-3 w-32">
期限
</div>
<div class="flex w-8">
</div>
<div class="flex w-8">
</div>
</li>
@if ($todolists->isEmpty())
<li class="flex h-full w-auto justify-center items-center mb-4">
<div class="h-full justify-center text-4xl">Todoを入力してください</div>
</li>
@else
@foreach($todolists as $todo)
<li class="flex lg:col-span-1 items-center justify-start mb-4">
<div class="flex items-center">
<x-element.button-check :todoId="$todo->id"></x-element.button-check>
</div>
<p class="ml-3 text-xl w-96 text-gray-600">
{{ $todo->content }}
</p>
<p class="ml-3 text-xl w-32 text-gray-600">
{{ $todo->deadline }}
</p>
<x-element.button-a :href="route('todolist')" theme="edit">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8">
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
</svg>
</x-element.button-a>
<x-element.button-deltodo :todoId="$todo->id"></x-element.button-deltodo>
</li>
@endforeach
@endif
<li class="flex flex-wrap sticky bottom-6 lg:col-span-1 justify-center items-center text-xl bg-gray-100 border-t-4 border-gray-500">
<div class="flex flex-wrap w-1/2 p-2 justify-evenly">
<x-element.button-a :href="route('todolist')" theme="add">Todo登録</x-element.button-a>
<x-element.button-a :href="route('todolist')" theme="undo">Todo復元</x-element.button-a>
</div>
</li>
</ul>
</x-layout.todolist-single>
</x-layout.layout>
ファイルを保存してから、CSSサーバーが立ち上がっているのをきちんと確認して、http://localhost/todolist
にアクセスします。
以下のような画面になっていれば、正常に動作しています。
おわりに
かなり長くなりましたが、以上でTodo一覧画面は一応完成です。
まだ、完了ボタンや削除ボタンの機能を実装していないので、ボタンを押すがエラーが出ますが、次回以降実装することできちんと動くようになります。
次回は、Todo追加機能を作っていく予定です!
ではまた!!
Discussion