イントロダクション
このクイックスタートガイドではデータベースマイグレーション、Eloqunet ORM、ルーティング、バリデーション、ビュー、Bladeテンプレートといった、Laravelフレームワークの基本を紹介します。Laravelフレームワークや一般的なPHPフレームワークに全く触れたことのない初心者の方にとって、よい入門となるでしょう。既にLaravelや他のフレームワークを使用しているのでしたら、より上級者向けに書かれたもう一つのクイックスタートが適しています。
Laravelの持つ機能の基本的な部分を試せるように、完了したいタスク全てを管理できるシンプルなタスクリストを構築してみます。(典型的なToDoリスト)このプロジェクトの最終の完全なソースコードはGitHubから取得可能です。
インストール
もちろん、最初にLararavelフレームワークを真新しくインストールする必要があります。Homestead仮想マシーンか、フレームワークを実行するために選択したローカルのPHP環境を使用します。ローカル環境が整ったら、Composerを使用しLaravelフレームワークをインストールできます。
composer create-project laravel/laravel quickstart --prefer-dist
このクイックスタートの残りの部分をただ読み進めることもできますが、ソースコードをダウンロードしてローカルマシーンで実行したい場合は、Gitリポジトリーをクローンし、依存パッケージをインストールします。
git clone https://github.com/laravel/quickstart-basic quickstart
cd quickstart
composer install
php artisan migrate
ローカル開発環境の構築についてのドキュメントは、Homesteadとインストールのドキュメントを参照してください。
データベースの準備
データベースマイグレーション
最初に全タスクを保持しておくためのデータベーステーブルを定義する、マイグレーション(migration:移行)を使ってみましょう。Laravelのデータベースマイグレーションはスラスラ書ける記述的なPHPコードを用いて、データベーステーブルの構造を定義し修正するための簡単な方法を提供しています。チームメンバーへ個別で用意しているデータベースのコピーへカラムを各自自分で追加するように伝える代わりに、あなたがソース管理にPushしたマイグレーションを実行してもらえます。
では、全タスクを保持するデータベーステーブルを構築しましょう。Artisan
CLIは様々なクラスの生成に利用でき、Laravelプロジェクトを構築するためにたくさんタイプする手間を省いてくれます。今回はtasks
テーブルのために、新しいデータベースマイグレーションをmake:migration
コマンドを使って生成します。
php artisan make:migration create_tasks_table --create=tasks
マイグレーションはプロジェクトのdatabase/migrations
ディレクトリーの中に設置されます。お分かりでしょうが、make:maigration
コマンドは、マイグレーションファイルへ自動増分IDとタイムスタンプの追加を始めに定義しています。このファイルを編集し、タスクの名前を保存するstring
カラムを追加しましょう。
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTasksTable extends Migration
{
/**
* マイグレーション実行
*
* @return void
*/
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
/**
* マイグレーションの巻き戻し
*
* @return void
*/
public function down()
{
Schema::drop('tasks');
}
}
マイグレーションを実行するには、migrate
Artisanコマンドを使います。Homesteadを使っている場合、ホストからは直接データベースへ接続できないため、このコマンドは仮想マシーンで実行してください。
php artisan migrate
このコマンドは全データベーステーブルを生成します。お好きなクライアントを使用し、データベーステーブルを調べてもらえば、マイグレーションで定義したカラムを含んだ新しいtasks
テーブルを見つけることができるでしょう。次に、タスクを表すEloquent
ORMモデルを定義しましょう!
Eloquentモデル
EloquentはLaravelのデフォルトORM(object-relational mapper)です。Eloquentは明確に定義された「モデル」を用いることで、苦労せずにデータベースへのデータ保存/取得を行わせてくれます。通常各Eloquentモデルは、一つのデータベーステーブルに対応します。
では、作ったばかりのtasks
データベーステーブルに対応するTask
モデルを定義してみましょう。このモデルを生成するために、再度Artisanコマンドを使用します。この場合はmake:model
コマンドを使用します。
php artisan make:model Task
このモデルはアプリケーションのapp
ディレクトリーに設置されます。デフォルトではこのクラスは空です。データベーステーブルはモデルの複数形の名前だと想定されているため、Eloquentモデルがどのテーブルに対応するかを明確に宣言する必要はありません。ですから、この場合Task
モデルはtasks
データベーステーブルと対応していると想定しています。空のモデルは次のようになっています。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
//
}
アプリケーションにルートを追加してから、Eloquentモデルについて更に学びましょう。もちろん、ご自由にEloquentの完全なドキュメントを読んで、更に情報を学んでもかまいません。
Routing
ルートのスタブを定義
次に、アプリケーションにいくつかルートを追加しましょう。ルートはユーザーがページにアクセスするために指定するURLを実行するコントローラーか無名関数を指定するために使用します。Laravelの全ルートはデフォルトで、新しいプロジェクトに必ず含まれているapp/Http/routes.php
ファイルの中で定義します。
このアプリケーションでは、最低3つのルートが必要になることがわかっています。全タスクをリスト表示するルート、新しいタスクを追加するルート、既存のタスクを削除するルートです。では、app/Http/routes.php
ファイルでこれらのルートを全部スタブ(空の代用コード)で定義しましょう。
<?php
use App\Task;
use Illuminate\Http\Request;
/**
* 全タスク表示
*/
Route::get('/', function () {
//
});
/**
* 新タスク追加
*/
Route::post('/task', function (Request $request) {
//
});
/**
* 既存タスク削除
*/
Route::delete('/task/{id}', function ($id) {
//
});
ビューの表示
次に/
ルートを完成させましょう。このルートでは、新しいタスクを追加するフォームを含み、同時に現在の全タスクをリストするHTMLテンプレートを表示しましょう。
Laravelの全HTMLテンプレートはresources/views
ディレクトリーに設置されます。ルートからこれらのテンプレートの一つを返すためにview
ヘルパが使えます。
Route::get('/', function () {
return view('tasks');
});
もちろん、このビューは実際に定義する必要がありますので、早速とりかかりましょう!
レイアウトとビューの作成
このアプリケーションは新しいタスクを追加するためのフォームを含み、同時に現在のタスクをリストするビューを一つだけ持ちます。ビューを想像するために役立つように、基本的なBootstrapのCSSスタイルを適用した、最終段階のアプリケーションのスナップショットをご覧ください。
レイアウト定義
ほとんど全てのアプリケーションでは同じレイアウトをページに渡り共有します。たとえばこのアプリケーションは全ページ(一つ以上のページが存在する場合)で表示する、典型的なトップナビバーがあります。LaravelはBladeテンプレートを使い、こうしたページ間共通のフューチャーを簡単に共有できるようになっています。
前に説明したように、Laravelの全ビューはresources/views
に設置されます。ですから新しいレイアウトビューもresources/views/layouts/app.blade.php
として定義します。.blade.php
拡張子はビューを表示するときにBladeテンプレートエンジンを使用することをフレームワークへ指示します。もちろんLaravelでも普通のPHPテンプレートが使用できます。しかしBladeなら簡潔できれいなテンプレートを書くための便利なショートカットが利用できます。
app.blade.php
ビューは以下のような構成になるでしょう。
// resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<title>Laravel Quickstart - Basic</title>
<!-- CSSとJavaScript -->
</head>
<body>
<div class="container">
<nav class="navbar navbar-default">
<!-- ナビバーの内容 -->
</nav>
</div>
@yield('content')
</body>
</html>
レイアウトの@yield('content')
の部分に注目です。これはレイアウトを拡張する全部の子ページが、自身のコンテンツを親へ注入できる場所を指定するための特別なBladeディレクティブ(指定子)です。次に、このレイアウトを使用しメインコンテンツを表示する、子のビューを定義しましょう。
子ビューの定義
素晴らしい。アプリケーションのレイアウトは完成しました。次に新しいタスクを作成するためのフォームと、存在する全タスクを同時に表示するビューを定義する必要があります。resources/views/tasks.blade.php
を定義しましょう。
Bootstrap CSSの定形コードを省いて、重要な部分に焦点を当てましょう。完全なソースコードはGitHubからダウンロードできることは覚えておいてください。
// resources/views/tasks.blade.php
@extends('layouts.app')
@section('content')
<!-- Bootstrapの定形コード… -->
<div class="panel-body">
<!-- バリデーションエラーの表示 -->
@include('common.errors')
<!-- 新タスクフォーム -->
<form action="/task" method="POST" class="form-horizontal">
{{ csrf_field() }}
<!-- タスク名 -->
<div class="form-group">
<label for="task" class="col-sm-3 control-label">Task</label>
<div class="col-sm-6">
<input type="text" name="name" id="task-name" class="form-control">
</div>
</div>
<!-- タスク追加ボタン -->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="submit" class="btn btn-default">
<i class="fa fa-plus"></i> タスク追加
</button>
</div>
</div>
</form>
</div>
<!-- TODO: 現在のタスク -->
@endsection
簡単な説明
先に進む前に、このテンプレートについて多少説明しましょう。最初に@extends
ディレクティブにより、resources/views/layouts/app.blade.php
に定義したレイアウトを使用することをBladeに指示しています。@section('content')
から@endsection
の間のコンテンツが、app.blade.php
レイアウトの中の@yield('content')
ディレクティブの場所に挿入されます。
これでアプリケーションの基本レイアウトとビューが定義できました。このビューフォームを/
ルートで実行することを思い出してください。
Route::get('/', function () {
return view('tasks');
});
次に、フォーム入力を処理し、データベースに新しいタスクを追加するPOST /task
ルートのコードを追加しましょう。
注意:
@include('common.errors
)ディレクティブはresources/views/common/errors.blade.php
のテンプレートをロードします。このテンプレートは定義していませんが、すぐに行います!
タスク追加
バリデーション
これでビューにフォームが用意できましたので、フォームの入力の正当性を確認し(バリデーション)、新しいタスクを作成するPOST /task
ルートへコードを追加しましょう。最初に、入力のバリデーションです。
このフォームでは、name
フィールドの入力が必須で、内容が255
文字以下であることを確認しましょう。バリデーションに失敗したら、ユーザーを/
のURLへリダイレクトし、同時に以前の入力とエラーをsessionへフラッシュデータとして保存します。
Route::post('/task', function (Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
]);
if ($validator->fails()) {
return redirect('/')
->withInput()
->withErrors($validator);
}
// タスク作成…
});
$errors
変数
一休みして、この例の->withErrors($validator)
の部分について解説しましょう。->withErrors($validator)
の呼び出しは、指定されたバリデター(validator)インスタンスのエラーをフラッシュデータとしてセッションへ保存し、ビューの中で$errors
変数としてアクセスできるようにしてくれます。
フォームのバリデーションエラーを表示するために@include('common.errors')
ディレクティブをビューで使用したことを思い出してください。common.errors
によりバリデーションエラーを同じ形式で、全ページに渡り簡単に表示できるようにしています。このビューの内容を定義しましょう。
// resources/views/common/errors.blade.php
@if (count($errors) > 0)
<!-- フォームのエラーリスト -->
<div class="alert alert-danger">
<strong>おや?何かがおかしいようです!</strong>
<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
注意:
$errors
変数は全てのLaravelビューの中で参照できます。バリデーションエラーが存在しない場合は、ViewErrorBag
の空のインスタンスです。
タスク作成
これで入力のバリデーションは処理できました。新しいタスクを実際に作成するためにルート処理の定義を続けましょう。新しくタスクを生成したら、ユーザーを/
のURLへリダイレクトします。タスクを作成するには、新しいEloquentモデルに対しプロパティーを生成し、値を設定した後に、save
メソッドを使用します。
Route::post('/task', function (Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
]);
if ($validator->fails()) {
return redirect('/')
->withInput()
->withErrors($validator);
}
$task = new Task;
$task->name = $request->name;
$task->save();
return redirect('/');
});
いいですね!これでタスクを作成できるようになりました。次に存在する全タスクをリストするビューを追加していきましょう。
既存タスクの表示
最初に、/
ルートを編集し、既存の全タスクをビューに渡しましょう。view
関数は第2引数に、ビューで使用するデータを配列で受け付けます。配列のキーはビューの中で変数となります。
Route::get('/', function () {
$tasks = Task::orderBy('created_at', 'asc')->get();
return view('tasks', [
'tasks' => $tasks
]);
});
データを渡したら、tasks.blade.php
ビューの中でタスクを反復処理し、テーブルとして表示します。とても早く通常のPHPコードにコンパイルできる@foreach
Blade構造文で簡単にループが記述できます。
@extends('layouts.app')
@section('content')
<!-- タスクフォームの作成… -->
<!-- 現在のタスク -->
@if (count($tasks) > 0)
<div class="panel panel-default">
<div class="panel-heading">
現在のタスク
</div>
<div class="panel-body">
<table class="table table-striped task-table">
<!-- テーブルヘッダー -->
<thead>
<th>Task</th>
<th> </th>
</thead>
<!-- テーブルボディー -->
<tbody>
@foreach ($tasks as $task)
<tr>
<!-- タスク名 -->
<td class="table-text">
<div>{{ $task->name }}</div>
</td>
<td>
<!-- TODO: 削除ボタン -->
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
@endsection
タスクアプリケーションはほとんど完成です。しかし、終了した既存タスクを削除する手段がありません。次に実装しましょう。
タスク削除
削除ボタンの追加
コード中、削除ボタンを設置する場所に"TODO"を残してあります。では、tasks.blade.php
ビューのタスクリストの各行に、削除ボタンを追加しましょう。小さなボタンひとつのフォームをリストの各タスクごとに作成します。ボタンがクリックされると、DELETE /task
リクエストがアプリケーションに送信されます。
<tr>
<!-- タスク名 -->
<td class="table-text">
<div>{{ $task->name }}</div>
</td>
<!-- 削除ボタン -->
<td>
<form action="/task/{{ $task->id }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button>タスク削除</button>
</form>
</td>
</tr>
見せかけのメソッドの説明
削除ボタンフォームのmethod
がPOST
を使用しているのにかかわらず、定義しているルートはRoute::delete
である点に注目です。HTMLフォームはGET
とPOST
HTTP動詞のみを許しています。そのため、フォームのDELETE
リクエストを見せかける手段が必要になります。
フォームの中でmethod_field('DELETE')
関数の結果を出力することにより、DELETE
リクエストへ見せかけることができます。Laravelはこれを認識し、実際のHTTPリクエストメソッドをオーバーライドします。生成されるフィールドは次の内容です。
<input type="hidden" name="_method" value="DELETE">
タスク削除
最後に指定したタスクを実際に削除するロジックをルートへ追加しましょう。IDでモデルを取得し、モデルが存在しない場合は404例外を投げるEloquentのfindOrFail
メソッドが使えます。モデルを取得したら、delete
メソッドを使用すれば、そのレコードを削除できます。レコードが削除されたら、ユーザーを/
のURLへリダイレクトします。
Route::delete('/task/{id}', function ($id) {
Task::findOrFail($id)->delete();
return redirect('/');
});