作成日:2021/04/12 更新日:2023/03/03
#8 Laravelアプリでデータを新規登録する方法
①以前のデータの確認
続いて新規登録処理の実装に移りましょう。以前作成した「index.php」の、下記の部分です。
②登録ロジックを作成 bladeテンプレート(view)
今回もまずはview層から着手しましょう。drag-areaの時と同じ様に、layoutsフォルダに「registrations.blade.php」というファイルを作成します。
<form action="{{ url( 'register' )}}" method="POST">
{{ csrf_field() }}
<input type="text" name="inputName" placeholder="新メンバー名を入力">
<input type="submit" value="登録">
</form>
以前作成したindex.phpに記述した内容とほとんど変わりません。「csrf_field()」という記述は、後ほど説明いたします。
このファイルを「sortable.blade.php」でincludeさせます。
{{ csrf_field() }}
↓
<input type="hidden" name="_token" value="***********************************">
csrf_field()メソッドを実行するとinputタグが入力されます。
③画面表示ロジックを作成 bladeテンプレート(view)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>8001-cri-sortable</title>
<link href="{{ asset('css/style.css')}}" rel="stylesheet">
</head>
<body>
<div id="wrapper">
<div id="input_form">
@include('layouts.registrations') /* registrations.blade.phpを読み込む */
</div>
<div id="drag-area">
@include('layouts.drags')
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script src="{{ asset('js/main.js')}}"></script>
</body>
</html>
該当箇所にregistrations.blade.phpを読み込むように設定します。ファイル:resources/views/sortable.blade.php
④新規登録用のコントローラーを作成(controller)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Sortable;
class SortableController extends Controller
{
public function index(){
$sortable = Sortable::orderBy('id', 'asc')->get();
return view('sortable', [
'sortables' => $sortable
]);
}
public function register(Request $request){
$sortable = new Sortable;
$sortable->name = $request->inputName;
$sortable->save();
return redirect('/');
}
}
register()という新規登録用のメソッドを追加しました。namespaceがApp\Http\Controllersなので App/Http/Controllers/ 内にSortableController.phpという名前で保存します。
引数で渡している$requestには、ブラウザの画面で「登録」ボタンを押下した際に送信されるHTTPrequestの中身が入ります。
クラスをnewすることで、sortablesテーブルまでの接続指示を、および登録するnameカラムの値を格納したら save()メソッドで登録処理INSERTを実行させる処理、を$sortableの中にいれます。
全ての処理が完了したらredirect()メソッドでリダイレクト処理を実行します。 リダイレクト先は元々いた画面に戻りたいので「/」とします。
⑤ルーティングの設定(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('/', 'SortableController@index');
Route::post('/register', 'SortableController@register');
最後に、ルーティングファイルの修正です。これを忘れると、どんなにMVCで作り込んでも画面上で動作しないので要注意です。/registerがPOSTリクエストされると、コントローラーのregisterメソッドを呼び出します。
ここまで記述を終えたら、早速画面から登録処理を試してみましょう。
#9 LaravelでAjaxのデータを登録する方法
①以前のデータの確認
続いて新規登録処理の実装に移りましょう。以前作成した「index.php」の下記の部分です。
②Ajaxの修正とCSRF対策について。main.jsの修正
Ajaxの通信先をLaravelのアプリケーションに変更する必要があります。
$.ajaxSetup({ /* ①-追加 */
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type:'POST',
url: '/update', /* ②-変更 */
data: {
id :myNum,
left:myLeft,
top :myTop
}
}).done(function(){
main.jsを上記の様に修正しましょう。
①.ajaxのリクエスト通信にheadersを追加し、CSRFに関する記述をする
CSRFとは悪意のある攻撃(エクスプロイト)のことです。LaravelではPOSTされたデータやHTMLフォームから来たデータがCSRF攻撃だった場合に、それを防ぐ仕組みが用意されています。
TOKENとは暗号鍵やワンタイムパスワードなどを生成する仕組みのことです。
POSTやHTMLフォームからデータを受ける場合は、隠しCSRFトークンフィールドをmetaタグやフォームに埋め込み、データの有効性をチェックするようにしましょう。
②urlの値を「/update」へ変更する
以前は「localhost:8001」を指定していた部分です。あとでルーティングファイル「web.php」を修正し、「/update」が呼ばれたらControllerの更新処理を呼び出すように設定します。Ajaxのheadersに渡すためのCSRFトークンをHTMLに記述する
<meta name="csrf-token" content="{{ csrf_token() }}">
sortable.blade.php内のmetaタグ、content属性にcsrf_token()メソッドを入れておきます。
③Controllerに更新処理を追記する。
コントローラーのSortableController.phpに記述してあるregister()メソッドの下に、新たに update()メソッド を追記します。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Sortable;
class SortableController extends Controller
{
public function index(){
$sortable = Sortable::orderBy('id', 'asc')->get();
return view('sortable', [
'sortables' => $sortable
]);
}
public function register(Request $request){
$sortable = new Sortable;
$sortable->name = $request->inputName;
$sortable->save();
return redirect('/');
}
/* ↓↓↓ここに追記↓↓↓ */
public function update(Request $request){
$inputs = $request->all();
$s = new Sortable;
$sortable = $s->find($inputs['id']);
$sortable->left_x = $inputs['left'];
$sortable->top_y = $inputs['top'];
$sortable->save();
return redirect('/');
}
}
手順としては・Ajax通信で仮想サーバへ飛んできたHTTPRequestの内容を取得
・requestの中からidを取り出し、テーブルから該当するレコードを探しに行く
・該当するレコードのleft_xとtop_yカラムの値を更新し、更新登録を完了する。
・初期画面へリダイレクトする。
▼解説
$inputs = $request->all();
$inputsにAjax通信で飛んできたrequestの内容を代入する。Ajaxで送信した内容はHTTPRequestという形でwebサーバ(MAMPの仮想サーバ)に入ってきます。
そのrequestの中に、Ajaxで格納したdata(idやleft_x、top_yの座標)が入っているので、その値を取得するために上記の様な処理を行います。
$sortable = $s->find($inputs['id']);
idをキーに更新対象のレコードを特定する。find()メソッドで$sortableの中から該当するidを持っているレコードを探します。
※「$sortable」はModelの「Sortable.php」の内容を持っています。
$sortable->left_x = $inputs['left'];
$sortable->left_y = $inputs['top'];
$sortable->save();
データベース内の更新対象カラム「left_x」「top_y」に、更新する値を渡しsave()メソッドで更新登録する。
$sortable = $s->find($inputs['id']);
初期画面へリダイレクトする。
④ルーティングファイル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('/', 'SortableController@index');
Route::post('/register', 'SortableController@register');
Route::post('/update', 'SortableController@update');
URLで「/update」が呼ばれたときに、Controllerのupdateメソッド()を呼び出すようにします。
/updateというURLは先程記述した、Ajax通信が発生する際に呼ばれるURLです。
完成したLarabelアプリの図解
【前提】MAMP、Homebrew、Composer、VS Code、ブラウザ をインストールしておく
【初期設定】
・開発環境フォルダを作成
・フォルダに対しMAMPのhttpd-vhosts.confでバーチャルホストを設定
・ターミナルでComposerを使ってLaravel本体をインストールする
・Laravelの.envファイルをMAMP環境に編集
・Laravelの/config/database.phpを.envの内容に編集
・phpMyAdminでデータベースを作成
・ターミナルを使ってartisanコマンドでLaravelのマイグレーションファイルを作成
・Laravelの/database/migration/にあるマイグレーションファイルを編集
・ターミナルを使ってartisanコマンドでマイグレーションを実行(DBにテーブルができる)
#10 Laravelでアプリを作ってみよう
応用課題として自分用の「タスク管理ツール」を作成してみましょう。
レイアウト部分のHTMLとCSSは用意しました。後ほど使うのでダウンロードしておきましょう。HTML&CSSデータ ダウンロード
まずは学習してきた流れ通り、Laravelプロジェクトを作成するところから始めましょう。
ここでのLaravelのバージョンは8.75.0、PHPは7.4.1とします。
前準備
開発ディレクトリを作成
開発ディレクトリにLaravelプロジェクト「MyTASK」を作成
ComposerでLalavelをインストールしましょう。ここではプロジェクト名を「MyTASK」にしました。
cd 8027-MyTASK [enterkey]
composer create-project laravel/laravel MyTASK --prefer-dist
開発ディレクトリをMAMPでバーチャルホストを設定
MAMPでポート番号のバーチャルホストを設定します。#5 Laravelの環境構築を参考にしましょう。設定後にMAMPを再起動はお忘れなく。
Listen 8027
<virtualhost *:8027>
DocumentRoot "/Users/ユーザ名/job/stg/8027-MyTASK/MyTASK/public"
</virtualhost>
Laravel環境設定
①.envファイルのデータベース情報の設定②/config/database.phpで.env情報を設定
Laravelの環境設定を変更する .env ファイルを参考にしましょう。
DB_HOST=localhost
DB_PORT=8889
DB_DATABASE=cbc_mytask
DB_USERNAME=root
DB_PASSWORD=root
もし、DB名を間違えて起動した場合「php : Laravel SQLSTATE [HY000] [1049]不明なデータベース」と出ることがあります。その場合は、
$ php artisan config:cache
で、リフレッシュしてもう一度アクセスしてみましょう。データベースを作成し、マイグレーションを使ってテーブル、カラムを作成
ここではデータベースcbc_mytaskを作成し、テーブル名をtasks、カラムにidとタスクを入れるtaskというカラムを作りました。
$ php artisan make:migration create_tasks_table --create=tasks
マイグレーション設定のコマンドを実行。
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->integer('id')->autoIncrement();
$table->text('task')->nullable(false);
});
}
マイグレーションファイルでは、idにはオートインクリメント、メモを入れるテキストデータをtaskという名前のカラムを作ります。
$ php artisan migrate
マイグレーション実行
Modelを作る
#7 ③データを取得するモデルSortable.phpを作るを参照してみてください。ここではモデル名をTaskとしました。
$ php artisan make:model Task
アルチザンコマンドでTaskモデル(Task.php)を/app/Models/ディレクトリに作ります。ファイルの編集ですが今回も日付記録のカラムがないので、Task.php内のTaskクラスに、タイムスタンプfalseの設定を追記しておきましょう。
public $timestamps = false; /* 追加 */
Controllerを作る
コントローラーの理解
今回のアプリで行う処理は主に3つです。
1.初期表示(SELECT)・・・テーブルから全てのデータを取得し、タスク表示箇所へ反映する。
2.登録(INSERT)・・・入力されたタスク名をテーブルに登録する。
3.完了(DELETE)・・・完了ボタンが押されたら、そのタスクに該当するレコードをテーブルから削除する。(物理削除する)
2.登録(INSERT)・・・入力されたタスク名をテーブルに登録する。
3.完了(DELETE)・・・完了ボタンが押されたら、そのタスクに該当するレコードをテーブルから削除する。(物理削除する)
コントローラーを作る
TaskController.phpファイルを作ります。
$ php artisan make:controller TaskController
アルチザンコマンドで/app/Http/Controllers/ディレクトリにTaskController.phpを作ります。コントローラーに表示、登録、削除のメソッドを作成する
TaskControllerクラス内で、テーブル全件取得と、登録、削除のメソッドを作成します。
class TaskController extends Controller
{
public function テーブル全件取得メソッド(){
処理
}
public function 登録メソッド(){
処理
}
public function 削除メソッド(){
処理
}
}
登録のメソッドは#7 ④コントローラーのSortableController.phpを作るを参照しましょう。削除のメソッドはLaravelマニュアル モデル削除 を見ながら作りましょう。
またgoogleなどの検索エンジンで「Laravel 削除メソッド」で探してみましょう。
削除するときは、データベースを取得しているクラス「Task」にアクセスし、特定のidを特定して、削除するメソッドを実行します。 クラスにはスコープ演算子を使ってアクセスしてみましょう。
Class::静的プロパティ(変数)、Class::静的メソッド(関数)
「::(ダブルコロン)」はスコープ演算子
Class外部からClassをスコープ(範囲指定)して静的なプロパティ、メソッドにアクセスする。
(例)
class Aisatsu
{
public static $hello = 'おはよう';
public static function bye(){
return 'ばいばい';
}
}
echo Aisatsu::$hello;
echo Aisatsu::bye();
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Task; /* 名前空間を設定します */
class TaskController extends Controller
{
public function index(){ /* indexメソッドを追加します */
$task = Task::orderBy('id', 'asc')->get(); /* Taskクラスを使ってtasksテーブル全件取得を指示 */
/* task.blade.phpに対し(第1引数)、taskカラムのデータをtasksに渡す(第2引数) */
return view('task', [
'tasks' => $task
]);
}
public function register(Request $request){
$task = new Task;
$task->task = $request->task;
$task->save();
return redirect('/');
}
public function delete(Request $request){
$task = Task::find($request->id); /*Taskクラスを使って、ajaxで渡ってきたidをセットする*/
$task->delete(); /*指定されたidを削除する*/
/* $task = Task::find($request->id)->delete(); //これでも可 */
return redirect('/');
}
}
web.phpでルーティングを設定する
/routes/web.phpでルートURLが呼ばれたら、Controllerのindex()メソッドの処理を実行させます。#7 ⑤ルーティングのweb.phpを修正するを参考にしましょう。
/* Route::get('/', function () {
return view('welcome');
}); */
Route::get('/', 'App\Http\Controllers\TaskController@index');
Route::post('/register', 'App\Http\Controllers\TaskController@register');
Route::post('/delete', 'App\Http\Controllers\TaskController@delete');
bladeテンプレートでViewを作る
ダウンロードした過去制作のindex.phpを編集しながら、3つの機能ごとにファイルを分割しよう テンプレートファイルtask.blade.phpは/resources/views/ディレクトリに入れましょう。CSSやJSファイルは公開フォルダの/public/ディレクトリ内に入れます。
tasks.blade.phpに2つの機能ファイルを@includeさせましょう。
登録する部分は、index.htmlの「formタグ」部分をコピーして、#8 ②作ったregistrations.blade.phpを参考に、 作ってみましょう。
表示する部分は、index.htmlの「ループさせて表示させる」部分を探し出して、 #7 ②作ったdrags.blade.phpを参考に、作ってみましょう。
cssやjsを読み込ませる際にも{{ asset(***/***.***) }}で読み込ませましょう。
答え
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>MyTasks</title>
<link href="{{ asset('css/reset.css')}}" rel="stylesheet">
<link href="{{ asset('css/style.css')}}" rel="stylesheet">
</head>
<body>
<div id="wrap" class="wrap">
<div class="task">
<!-- タスク作成エリア -->
<div class="task__new">
<h2>新しいタスクを作成</h2>
@include('layout.regists')
</div>
<!-- タスク一覧表示エリア -->
<div class="task__area">
<h2>わたしのタスク一覧</h2>
<ul class="task__area-list">
@include('layout.myTasks')
</ul>
</div>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script src="{{ asset('js/main.js')}}"></script>
</body>
</html>
/resources/views/task.blade.php
<form action="{{ url( 'register' )}}" method="POST">
{{ csrf_field() }}
<input type="text" name="task" maxlength="30" placeholder="タスクを入力してください">
<input type="submit" value="追加">
</form>
/resources/views/layout/regists.blade.php
@foreach($tasks as $task)
<li>
<p>{{ $task->task }}</p>
<button class="delete_btn" data-id="{{ $task->id }}">完了</button>
</li>
@endforeach
/resources/views/layout/myTasks.blade.php
ajaxの通信ロジックを作る
$(function(){
$('.delete_btn').on('click', function(){
var Id = $(this).data('id');
/*console.log(Id);*/
if(confirm("タスクを完了してよいでしょうか?")){
/* ==========AJAX通信================= */
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type:'POST',
url: '/delete',
data: {
id: Id
}
}).done(function(){
/*console.log('成功');*/
location.reload();
}).fail(function(XMLHttpRequest, textStatus, errorThrown){
console.log(XMLHttpRequest.status);
console.log(textStatus);
console.log(errorThrown);
});
/* ==========/AJAX通信================= */
}
});
});
実際に動かしてみよう!
Laravelのデバッグバーをインストールする
Controllerの設定あたりでエラーが出ることが増えると思います。 そんなときはLaravelのデバッグツールを使ってエラーの原因を探ることができます。
$ composer require barryvdh/laravel-debugbar
アプリフォルダである「MyTASK」まで移動しcomposerでインストールします。
APP_DEBUG=true
.envファイルのAPP_DEBUGの値がtrueにっていることを確認。
$ php artisan config:cache
表示されないときはキャッシュをクリアしてみましょう。また、Laravel8のマニュアル を見て基本的な動作を習得しましょう。