Laravel学習のため、プロジェクト作成しブラウザからのDB操作(新規追加、編集、削除)を自分でやってみる。
##目次
- composerのインストール
- laravelのインストール
- laravelサーバーの起動
- DBにsqliteを設定
- モデルとマイグレーションの作成
- マイグレーションでDBのテーブルにカラムを追加
- コントローラの作成
- ルーティングの設定
- seederを使ってテストデータをDBに設定
- 一覧画面の作成(ブラウザにDBの全データを表示)
- 詳細ページの作成
- 編集機能の作成
- 削除機能の作成
##1. composerのインストール [composerのインストール方法](https://qiita.com/yuta-> 38/items/ca900b5c84e04ff71832)を参照。
##2. laravelのインストール
$ composer create-project laravel/laravel [プロジェクト名] --prefer-dist
指定したプロジェクト名でフォルダが作成される。
・--prefer-dist
オプション
高速ダウンロード用。
このオプションをつけると圧縮されていないファイルを優先してダウンロードする。また、すべてのVSC(バージョン管理ソフト)を取得しないので軽量となる。
##3. laravelサーバーの起動
php artisan serve
$ php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
表示されたURLにアクセス
http://127.0.0.1:8000
上記画面が表示されればOK。
サーバーの停止はctrl + c
。
##DBにsqliteを設定 使用が簡単かつmacにデフォルトでインストールされているsqliteをDBに使用する。
laravelインストール時のデフォルトのDBはMySQLのため、環境ファイルの設定を一部変更する。
###.envファイルの変更
ルートディレクトリ直下にある.envファイルを開き、以下コードを変更する。
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
↓ 以下に変更
DB_CONNECTION=sqlite
###DB用のファイルを作成する
database/database.sqliteを作成する。
プロジェクトのルートディレクトリで以下を実行。
$ touch database/database.sqlite
##モデルとマイグレーションの作成
DBのテーブルに対応するモデルと、テーブルにカラムを追加したり型指定するマイグレーションファイルを作成する。
$ php artisan make:model [モデル名] -m
- artisanコマンドの
make:model
でモデルを作成する。 -
-m
オプションでマイグレーションファイルも同時生成。(--migrate
の省略形) - モデル名は冒頭大文字の単数形。単語をつなげる場合はキャメルケースにする(例:MakerCode)
**▼モデルの命名規則** DBのテーブル名は複数形とし、Model名はその単数形とする。
・DBのテーブル名: 複数形のスネークケース
・対応するModel名: 冒頭大文字のキャメルケース
<例1>
・DBのテーブル名: articles
・対応するModel名: Article
<例2>
・DBのテーブル名: maker_codes
・対応するModel名: MakerCode
**▼(例)Productモデルを作成**
$ php artisan make:model Product -m
Model created successfully.
Created Migration: 2021_01_15_022833_create_products_table
2つのファイルが生成される。
・マイグレーション
database > migrations > タイムスタンプ_create_テーブル名_table.php
###(補足)モデルとマイグレーションファイルを別々に作る場合
マイグレーションファイルは作成用のartisanコードがあるので、それを使って生成できる。
$ php artisan make:model Product
$ php artisan make:migration create_products_table
##マイグレーションでDBのテーブルにカラムを追加する ###マイグレーションファイルの編集 作成したいカラムを追記する。デフォルトでidとtimestampsのカラムがある。
up関数の中に追記する。
・$table->型('カラム名')
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('product_name')->unique(); //追加
$table->integer('price'); //追加
$table->boolean('is_stocked')->nullable(); //追加
$table->timestamps();
});
}
必要に応じて、unique()
やnullable()
などの修飾子をつけることができる。
###カラムタイプと修飾子 他にもたくさんのカラムタイプが用意されている。 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/104ead98-9054-2d4c-a9c7-4314d713144b.png) 続きは以下リンク参照。
###マイグレーションの実行 作成したマイグレーションファイルの内容をテーブルに反映する。
php artisan migrate
**▼migrationの実行例**
$ php artisan migrate
Migration table created successfully.
Migrating: 2021_01_15_022833_create_products_table
Migrated: 2021_01_15_022833_create_products_table (0.90ms)
テーブルの作成に成功。
エラー発生時
Illuminate\Database\QueryException
Database (/laravel/test-pj/database/database.sqlite) does not exist. (SQL: PRAGMA foreign_keys = ON;)
対策:$ touch database/database.sqlite を実行
##コントローラの作成 DBにデータを追加・読み込み・編集・削除(CRUD操作)するためにコントローラを作成する。
作成時にオプションで-r
をつけると、CRUD操作のためのアクションが記載されたコントローラを作成することができる。
$ php artisan make:controller [コントローラ名] -r
-
-r
は--resource
の省略形 - コントローラ名は冒頭大文字で、後ろに
Controller
をつける(例:ProductController) - app > Http > Controllerの中にファイルが生成される
--resourceオプションで作成したコントローラを特別にリソースコントローラと呼ぶ。
**▼ProcuctControllerの作成例** create, show, editなどCRUD操作に必要なアクションの外枠を既に記述してくれている。 あとは実際の処理を各アクションの中に記述するだけの状態。
$ php artisan make:controller ProductController -r
Controller created successfully.
▼ファイルの中身
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
##ルーティングの設定 先ほど作成したコントローラの各アクションをルートに登録する。
ルーティングは、app > routes > web.php に記述する。
リソースコントローラのルート登録は、Routeファサードのresourceメソッドで簡単にできる。
Route::resource('$URI', 'コントローラ名');
- $URIは複数形のパスを指定する。
**▼実例**
Route::resource('products', 'ProductController');
▼ルートの登録状況を確認
・$ php artisan route:list
$ php artisan route:list
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
| | GET|HEAD | api/user | | Closure | api |
| | GET|HEAD | products | products.index | App\Http\Controllers\ProductController@index | web |
| | POST | products | products.store | App\Http\Controllers\ProductController@store | web |
| | GET|HEAD | products/create | products.create | App\Http\Controllers\ProductController@create | web |
| | GET|HEAD | products/{product} | products.show | App\Http\Controllers\ProductController@show | web |
| | PUT|PATCH | products/{product} | products.update | App\Http\Controllers\ProductController@update | web |
| | DELETE | products/{product} | products.destroy | App\Http\Controllers\ProductController@destroy | web |
| | GET|HEAD | products/{product}/edit | products.edit | App\Http\Controllers\ProductController@edit | web |
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
リソースコントローラの各アクションがルート登録されている。
Laravel8.xでエラーが出た場合は、RouteServiceProvider.phpのコメントアウトを解除する
###(補足)sqliteにテーブルが作成されているか確認する
sqliteにアクセスするためには、sqlite3
コマンドで、database.sqliteを開く。
ルートディレクトリで以下を実行。
・$ sqlite3 database/database.sqlite
$ sqlite3 database/database.sqlite
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
#テーブル一覧を表示
sqlite> .table
failed_jobs password_resets users
migrations products
#productsテーブルの構造(schema)を表示
sqlite> .schema products
CREATE TABLE IF NOT EXISTS "products" (
"id" integer not null primary key autoincrement,
"product_name" varchar not null,
"price" integer not null,
"is_stocked" tinyint(1) not null,
"created_at" datetime null,
"updated_at" datetime null
);
productsテーブルがあり、指定したカラムを持っていることがわかる。
▼sqlite3の主なコマンド
コマンド | 内容 |
---|---|
.tables | テーブル一覧を表示 |
.schema [テーブル名] | 指定したテーブルのスキーマ定義を表示 |
.exit | sqliteを終了 |
.help | ヘルプを表示 |
##seederを使ってテストデータをDBに設定する seeder(シーダ)とは、DBを手軽にテストするために、テストデータをDBに設定する機能。
$ php artisan make:seeder シーダ名
- シーダ名は、[テーブル名]TableSeeder とするのが一般的
- 保存先: app > database > seeders
なかなか便利な機能で、deleteやedit機能などでデータをあれこれ変更した後に、seederをDBに送ればまた初期のデータを復活させることができる。
**▼実例**
$ php artisan make:seeder ProductTableSeeder
Seeder created successfully.
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class ProductTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
}
}
run関数を持ったクラスが生成される。
###seederの編集
seederファイルのrun関数の中に処理を記述する。
今回はクエリビルダで記述する。冒頭でDBファサードのuse宣言をが必要。
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB; //追加
class ProductTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//以下追加
DB::table('products')->insert([
[
'product_name' => 'iPhone6s',
'price' => 62000,
'is_stocked' => false
],
[
'product_name' => 'iPhone8',
'price' => 84000,
'is_stocked' => true
],
[
'product_name' => 'iPhone12',
'price' => 120000,
'is_stocked' => true
]
]);
}
}
今回はクエリビルダで記述しているが、Eroquentでも問題ない。
###seederをDBに反映する seederをDBに反映する際は、基本的に`DatabaseSeeder.php`を使う。 そのため、作成したクラスを`DatabaseSeeder.php`の中で呼び出す。
public function run()
{
$this->call(ProductTableSeeder::class);
}
DatabaseSeeder.phpをメインとして使うとseederファイルを複数に分割している場合も容易にDBに反映できる。
#Composerのオートローダを再生成する
$ composer dump-autoload
#DatabaseSeeder.phpを実行する
$ php artisan db:seed
**▼実際の処理例**
$ composer dump-autoload
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
Generated optimized autoload files containing 4618 classes
$ php artisan db:seed
Seeding: Database\Seeders\ProductTableSeeder
Seeded: Database\Seeders\ProductTableSeeder (9.16ms)
Database seeding completed successfully.
以上でseederで作成したデータをDBに反映完了。
**▼(補足)別のseederファイルを直接DBに反映する** DatabaseSeeder.phpではなく、別途作成したseederファイルのみ読み込ませたい場合は、`--class`オプションでseederを指定する。
php artisan db:seed --class=ProductTableSeeder
###DBのデータを確認する ####・DBのデータを抽出してみる artisanコマンドのtinkerを使って、Laravelの対話モードに入り、Eloquentのallメソッドで指定したモデルのすべてのデータを取得する。
$ php artisan tinker
>>>[モデルの完全な名前空間]::all();
対話モードはexit
で抜ける。
tinkerの元の意味は小さな改善をすること。phpの対話モードでコマンドを一つづつ実施することが由来している?
**▼実例**
$ php artisan tinker
Psy Shell v0.10.5 (PHP 7.3.11 — cli) by Justin Hileman
>>>
>>> App\Models\Product::all();
=> Illuminate\Database\Eloquent\Collection {#4309
all: [
App\Models\Product {#4308
id: "1",
product_name: "iPhone6s",
price: "62000",
is_stocked: "0",
created_at: null,
updated_at: null,
},
App\Models\Product {#4307
id: "2",
product_name: "iPhone8",
price: "84000",
is_stocked: "1",
created_at: null,
updated_at: null,
},
App\Models\Product {#4298
id: "3",
product_name: "iPhone12",
price: "120000",
is_stocked: "1",
created_at: null,
updated_at: null,
},
],
}
>>>
>>> exit
Exit: Goodbye
指定したデータが取得できている。
####・sqliteで確認する
ルートディレクトリで以下を実行。
・$ sqlite3 database/database.sqlite
テーブルの中のデータをすべて表示(SQL)
・select * form [テーブル名]
$ sqlite3 database/database.sqlite
sqlite> select * from products;
1|iPhone6s|62000|0||
2|iPhone8|84000|1||
3|iPhone12|120000|1||
sqlite> .exit
##一覧画面の作成(ブラウザにDBの全データを表示) 取得した全データを表示する一覧画面を作成する。
###コントローラのindexアクションを編集する
以前に作成したコントローラのindexアクションの戻り値にDBのすべてのデータを指定する。
Eloquentを使うため冒頭に使用するモデルのクラスをuse宣言する。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Product; //追記
class ProductController extends Controller
{
public function index()
{
$productsInfo = Product::all(); //追記
return $productsInfo; //追記
}
//以下略
(参考)Eroquetとは?
###サーバーを起動する
$ php artisan serve
を実行する。
$ php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
###ブラウザで表示する URIにindexに対応するルートを入力する。(ここでは /products)
ルートは、
$php artisan route:list
コマンドで確認できる。
取得したデータの表示に成功。取得データをそのまま返しているのでデータはJSON形式で表示される。
###ビューの作成 取得データを見やすく表示するためにビューを作成する。 ビューは resources > views 配下に、拡張子`.blade.php` で保存する。
今回は、productsディレクトリを作成し、外側となるbase.blade.phpとメイン部分となるindex.phpを用意する。
####レイアウトの作成
layoutsディレクトリの中にbase.blade.php
を作成する。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title')</title>
</head>
<body>
<h1>@yield('title')</h1>
@yield('content')
</body>
</html>
###メインビューの作成
index.blade.phpを作成する。
@extends('.products.layouts.base')
@section('title', '製品一覧')
@section('newLink')
<a href="/products/create">新規作成</a>
<hr>
@stop
@section('content')
@foreach ($products as $product)
<div>
<h2>{{$product->product_name}}</h2>
<p>・製品価格:{{number_format($product->price)}}円</p>
<p>・在庫:
@if ($product->is_stocked) あり
@else なし
@endif
</p>
<a href="/products/{{$product->id}}/edit">編集する</a> |
<a href="/products/{{$product->id}}">商品詳細</a>
<hr>
</div>
@endforeach
@stop
後々作成する、新規作成、編集、商品詳細ページへのリンクも設置してある。
(参考)section, yield, extendsについて
###コントローラでビューを指定 ProductControllerのindexアクションで、作成したビュー(index.blade.php)を開くように処理を変更する。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Product; //追記
class ProductController extends Controller
{
public function index()
{
$productsInfo = Product::all();
return view('products.index', ['products' => $productsInfo]); //変更
}
//以下略
-
view
をviewヘルパーと呼び、指定したビューを開く。その際、第2引数でデータを渡せる。 - resource > products > index.blade.phpは、products.indexとして指定。
- 第2引数の書き方: ['変数名' => 渡すデータ]
**▼ブラウザの表示** 保存して、サーバー起動`php artisan serve` し、URIを入力する。
DBから取得したデータが成形して表示されている。
##詳細ページの作成 商品詳細ページを作成する。
###コントローラの編集
ProductControllerのshowアクションを編集する。
public function show($id)
{
//受け取ったidの製品情報を格納
$product = Product::find($id);
return view('products.show', ['product' => $product]);
}
URLのproductsの後ろのデータが$id
として渡される。
findメソッドを使って、指定したidのデータを変数$productに格納する。
###ビューの編集(show.blade.php) resources > products 配下にshow.blade.phpを作成する。
@extends('.products.layouts.base')
@section('title', '製品詳細')
@section('content')
<div>
<h2>{{$product->product_name}}</h2>
<p>・製品価格:{{number_format($product->price)}}円</p>
<p>・在庫:
@if ($product->is_stocked) あり
@else なし
@endif
</p>
<a href="/products/{{$product->id}}/edit">編集する</a> |
<a href="/products">製品一覧に戻る</a> |
@component('components.delete-txt', ['product'=>$product])
@endcomponent
<hr>
</div>
@stop
あとは、http://127.0.0.1:8000/products/1 のように、末尾でidを指定すると製品詳細ページが開く。
編集と削除リンク先は後ほど作成。
**▼(補足)削除機能のボタン** 削除機能はcomponentとして読み込んでいる。詳細の機能は最後の削除機能で作成する。
@component('components.delete-txt', ['product'=>$product])
@endcomponent
##新規追加機能の作成 ###ルーティングの確認 DBに保存するには、createアクションを実行し、storeアクションを行う。
ルートを確認すると、/products/createでcreateアクションを実行、/productsにPOSTでアクセスするとstoreアクション実行となる。
$ php artisan route:list
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
| | POST | products | products.store | App\Http\Controllers\ProductController@store | web |
| | GET|HEAD | products/create | products.create | App\Http\Controllers\ProductController@create | web |
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
###createビューの作成 新規作成ページとして、create.blade.phpを作成する。
@extends('.products.layouts.base')
@section('title', '製品の新規追加')
@section('content')
<form action="/products" method="post">
@csrf
<div>
<label for="product_name">製品名:</label>
<input type="text" name="product_name" required autoforcous>
</div>
<div>
<label for="price">製品価格:
</label>
<input type="text" name="price" required>
</div>
<div>
<label for="stock">在庫有無:</label>
<select name="stock">
<option value="1">あり</option>
<option value="0">なし</option>
</select>
</div>
<div>
<div>
<input type="submit" value="送信">
</div>
</form>
@stop
・@csrf
クロスサイトリクエストフォージェリ対策として必須。
(参考)Laravel公式 CSRF保護
@csrf
の記述がないと、submit後に419のエラーページに飛ばされる。(419はLaravel独自のエラーページ)
###コントローラの編集 新規追加のためには、createアクションとstoreアクションの2つに処理を追加する。
####createアクション
createアクションでは、上記で作成したビューを表示させるのみ。
public function create()
{
return view('products.create');
}
###storeアクション
storeアクションでは、submitで送られてきたデータを受け取り、DBに保存する処理を記述する。
public function store(Request $request)
{
$product = new Product;
$product->product_name = $request->product_name;
$product->price = $request->price;
$product->is_stocked = $request->stock;
$product->save();
return redirect('products/'.$product->id);
}
・$product = new Product;
Productモデルからインスタンスを作成し、変数に代入。
この変数に各データを保存していく。
・$request->[name属性]
submitで送られてきたデータは$request
に保存されている。
name属性を指定してデータを取得する。
・$product->save();
すべてのデータを格納したら、saveメソッドでDBに保存する。
・return redirect('products/'.$product->id);
新たに作成した製品詳細ページにリダイレクトする。
####ブラウザで開く ブラウザでcreateページを開く。 http://127.0.0.1:8000/products/create
↓ 送信
新規保存し、新しい製品詳細ページの表示に成功。
##編集機能の作成 ###ルーティングの確認 既存商品の情報を編集するには、editアクションとupdateアクションを使う。
$ php artisan route:list
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
| | PUT|PATCH | products/{product} | products.update | App\Http\Controllers\ProductController@update | web |
| | GET|HEAD | products/{product}/edit | products.edit | App\Http\Controllers\ProductController@edit | web |
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
products/{product}/edit
にアクセスして、商品の編集を行い、products/{product}
にPUT|PATCHでアクセスすればDBの情報を更新できる。
###編集ページの作成 編集用のビュー、edit.blade.phpを作成する。 基本的にはcreate.blade.phpと同じ。PUTでアクセスするために擬似メソッドを設置する。
▼create.blade.phpとの違い
- formタグのactionでパスが変わる。
- 擬似フォームメソッドの
@method('PUT')
を設置。 - inputタグにvalue属性で既存の設定データを表示。
- 在庫の有無に合わせてselectタグの初期値を設定。
- submitボタンのvalueを更新に変更。
@extends('.products.layouts.base')
@section('title', '製品の編集')
@section('content')
<form action="/products/{{$product->id}}" method="post">
@csrf
@method('PUT')
<div>
<label for="product_name">製品名:</label>
<input type="text" name="product_name" value="{{$product->product_name}}" required autoforcous>
</div>
<div>
<label for="price">製品価格:
</label>
<input type="text" name="price" value="{{$product->price}}" required>
</div>
<div>
<label for="stock">在庫有無:</label>
<select name="stock">
@php
$selected = "selected";
if ($product->is_stocked)
$selected = ""
@endphp
<option value="1">あり</option>
<option value="0" {{$selected}}>なし</option>
</select>
</div>
<div>
<input type="submit" value="更新">
</div>
</form>
@stop
・擬似フォームメソッド HTMLフォームは`PUT`, `PATCH`, `DELETE`リクエストを作成できないため(対応していない)、`_method`を偽装する必要がある。
・<input type="hidden" name="_method" value="リクエストメソッド名">
type="hidden"をつけると画面上に表示していないデータを送信することができる。_method
というキー名で、指定したリクエストメソッドを値として送信している。
▼putを使う方法
送信ボタンの上に以下タグを設置する。
<input type="hidden" name="_method" value="put">
<input type="submit" value="更新">
これを、laravelの擬似フォームメソッドを使うととても簡単にかける。
@method('PUT')
・(参考)Laravel公式 擬似フォームメソッド
>(補足)PUTとPATCHの違い PUTはすべてのデータをまるごと変更する場合に使い、PATCHは一部のデータを変更する場合に使うらしい。 ここでは、PUTとPATCHどちらを使っても同じ結果になる。
###コントローラの編集 editアクションとupdateアクションを編集する。
####editアクション
Productモデルの指定したidのデータを取得してビューに渡す。
public function edit($id)
{
$product = Product::find($id);
return view('products.edit', ['product'=>$product]);
}
####updateアクション
記述はstoreアクションとほぼ同じ。
最初にProductモデルの新規インスタンスではなく、指定したidのデータを取得する。
受け取ったデータ$request
を代入し、save
でDBに保存する。
public function update(Request $request, $id)
{
$product = Product::find($id);
$product->product_name = $request->product_name;
$product->price = $request->price;
$product->is_stocked = $request->stock;
$product->save();
return redirect('products/'.$product->id);
}
##削除機能の作成 ###ルーティングの確認
$ php artisan route:list
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
| | DELETE | products/{product} | products.destroy | App\Http\Controllers\ProductController@destroy | web |
+--------+-----------+-------------------------+------------------+------------------------------------------------+------------+
products/{product}
にDELETEでアクセスすればデータを削除できる。
###削除コンポーネントを作成する
削除ボタンは編集と詳細ページに設置する。laravelの機能であるコンポーネント化し簡単に呼び出しを行う。
コンポーネントはボタンとテキストの2種類を用意する。
####ファイルの作成
resources > views > componentsの配下に、ファイルを2つ作成する。
▼削除ボタンコンポーネント
<form action="/products/{{$product->id}}" method="post" id="delete-btn">
@csrf
@method('DELETE')
<input type="submit" name="" value="削除">
</form>
・acrtion属性の値に"/products/{{$product->id}}"
を設定。
formはDELETEメソッドをサポートしていないため、ここではpostを指定。
・@csrf
クロスサイトリクエストフォージェリ防止機能を追加(必須!)
・@method('DELETE')
擬似フォームメソッドでDELETEを指定。これでdeleteメソッドで通信できるようになる。
▼削除テキストコンポーネント
<form action='/products/{{$product->id}}' method='POST' id='dlt-txt'>
@csrf
@method('DELETE')
<a onclick='document.getElementById("dlt-txt").submit()'>削除する</a>
</form>
inputタグをテキストに変更するため、JavaScriptのsubmit
メソッドを使用。
formタグにid="dlt-btn"
を指定し、sbumitの対象をdocument.getElementById(dlt-btn)
とする。
以上でコンポーネントが完成。
####componentの仕組み 前述のコードで既にcomponentの呼び出し処理は記述してあるが、componentの仕組みについて。
Laravelではblade.php
ファイルをコンポーネントとして呼び出すことができる。
extends
, yield
, section
の簡易的な機能のようなもの。
コンポーネントの呼び出しはとても簡単で、呼び出したいところに以下のコードを記述する。
@component('ビューのパス', ['変数名'=>渡したいデータ])
@endcomponent
ビューのパスは相対ではなく、viewsフォルダからの絶対パスとなる。
このため、products > edit.blade.php から components >
delete-text.blade.phpを呼び出したい場合は、components.delete-txt
とする。
第2引数はデータを渡したいときに使う。読み込むのみでデータを渡す必要がない場合は不要。
###ブラウザの表示(削除機能の確認)
↓ 商品詳細(iPhone8)
↓ 削除
削除成功。
バリデーション、CSSの調整はないが、LaravelのCRUD操作の基本はおさえられた。