はじめに
Laravel 5 Advent Calendarの12/25を担当するfumiyasacです。
今ではすっかりiOS(SwiftやObjective-C)やRuby on Railsばっかりやっていますが、一番開発歴の長い言語は実はPHPだったりします。別のところですでにAdvent Calendarの記事を1本書き上げた後だったのでなかなか時間が足りず説明がざっくりしすぎている部分があるかと思いますが、何卒宜しくお願い致します。
今回はできるだけお手軽にLaravel5.1の開発エッセンスを掴んで頂けるような形のサンプルを作成してみました。
■ Github Sample Code:
Laravel5.1でCRUDアプリケーションを作成する簡易チュートリアル
一応対象としているレベル感としては下記のいずれかに該当する方を想定した上でサンプルを作成しました。
- 他のPHPで作られたアプリケーション・フレームワークの経験はあるけどLaravel5.1はまだ触ったことがない
- Laravelを実務で使ったことがないからいきなりチュートリアルは若干不安なので簡単に予行演習をしておきたい
- Laravel4系は少し触ったことがあるけれどもLaravel5.1はまだ未体験ゾーン
- 取り急ぎはお試し環境で良いのでLaravel5.1を試してみたい
上記全て僕に当てはまる感じです笑(こんな中途半端なキャリアですみません…)
※がっちり開発環境を整えたい場合は下記の方法ではなくVPSやクラウドサーバー等をお借りして構築する方が良いですが、今回は自分の環境で手早く試すための環境構築方法になりますのでその点ご容赦頂ければと思いますm(_ _)m
それでは環境構築からさっそくはじめて参りたいと思います。
1. MAMPを使用して環境構築〜Laravel5.1をインストールまで
★1-1. MAMPでLaravel5.1の開発を始めるにあたっての設定
前提:環境構築や実践した環境に関して
私の環境で試したのでOSやMAMPのバージョンは下記の通りになっています。
- OS:10.10.5 Yosemite
- MAMP:Ver.3.4(2015.12.22時点での最新版)
- Laravel:5.1
※ MySQLはMAMPのものを使用しています。
※ こちらはまずはLaravel5.1の開発をサクッと試してみたい人向けの環境構築手順ですので、Vagarant等を使っての環境をお考えの場合は下記の記事をご参考にしていただければと幸いです。
- Laravel5.1をHerokuのPHP7でとりあえず動かす
- ConoHa VPSでLaravel5.1環境を構築
- Laravel5.1のインストール方法
- PHPフレームワーク「Laravel5」の環境を Vagrant, CentOS 6.6, SCLの PHP 5.4, Apache2.4, MariaDB 5.5 で作ってみた、その1
★1-2. まずはMAMPへComposerのインストール
Laravelをインストールする場合にはComposerが必須となります。お手元のMacにすでにComposerがどこでも実行できるような環境であればそのままLaravel5.1のインストールまで進んで問題ありませんが、Composerがない状態の場合を想定した場合は下記のような手順になります。
まずはターミナル(iTerm)を起動して下記のコマンドの通り進めていきます。
↓下記ターミナルでの確認&作業コマンド:
$ cd /Applications/MAMP/htdocs/
$ curl -sS https://getcomposer.org/installer | php
$ mv composer.phar /usr/local/bin/composer
$ composer create-project laravel/laravel <app name on my own.> 5.1 --prefer-dist
$ sudo chmod -R 777 <app name on my own.>/storage
※の部分には自分の好きなプロジェクト名を入れてください。
※注意点:sudo chmod -R 777 <app name on my own.>/storage
の部分に関しては、レンタルサーバーやVPSの本番環境で運用する場合はこのままではセキュリティ上よろしくないので開発環境限定ですのでご注意下さい。
下記の手順としては、
- MAMP内のhtdocsまで移動
- composerを入手する
- composerコマンドをどこからでも使用できるようにする(これをしない場合はコマンドは、
php composer.phar xxx
となります) - Laravel5.1をインストールするhtdocsへインストール(インストールが成功するとhtdocs配下にのフォルダーができます。)
- 自分が作ったLaravel5.1のアプリケーションのstorageディレクトリのパーミッションを変更する
というような流れになります。
※もし作ったプロジェクトのファイルを編集する際に「readonly」となってしまっている場合には、htdocsディレクトリまで戻って下記のコマンドを追加で実行してください。
↓下記ターミナルでのコマンド手順:
$ sudo chmod -R 775 <app name on my own.>
これでLaravel5.1のインストール作業自体は終了です。
★1-3. Mcryptに関するエラーがでてしまった場合の対処
もしMcryptでエラーが出てしまった場合には、現在読み込んでいるPHPのバージョンがMacに入っているものになっているのでPHPをMAMPのものに変更してあげてください。
Laravel5.1はPHPのバージョンが5.5.9以上が必要です。ですのでそれよりも高いMAMPのPHP(バージョン5.6.10)を読むようにします。
※この設定がないとLaravelで開発する上で超重要になるartisanコマンドが使えないのでここは必ず確認をしてください。
↓下記ターミナルでの確認&作業コマンド:
$ which php
/opt/local/sbin/php //現在のphpのパス
$ sudo vim ~/.bash_profile
export PATH=/Applications/MAMP/bin/php/php5.6.10/bin:$PATH //こちらを追記
上記の作業が終わったらターミナルを再起動し which php
で先ほど設定したPHPバージョンのパスになっていればOKです。
★1-4. MAMP内のVirtualhostの設定
そしてVirtualHostの設定を行います。下記のディレクトリ内にあるファイルを下記のように変更し、その後MAMPを再起動して下さい。(私の場合プロジェクト名を「christmas_menu」とし仮想のドメインは「christmas_menu」へと変更しました)
準備:MAMP内の設定変更
(/Applications/MAMP/conf/apache/extra/httpd-vhosts.conf)
<VirtualHost *:8888>
DocumentRoot "/Applications/MAMP/htdocs/christmas_menu/public"
ServerName christmas_menu.dev
ErrorLog /Applications/MAMP/logs/christmas_menu_error_log
CustomLog /Applications/MAMP/logs/christmas_menu_access_log common
</VirtualHost>
そしてVirtualHostの設定が完了しましたら、hostsの設定を行います。
今回は christmas_menu.dev:8888/
でブラウザからアクセスできるようにします。
↓下記ターミナルでの確認&作業コマンド:
$ sudo vim /etc/hosts
Password:
127.0.0.1 christmas_menu.dev //こちらを追記
ここまでの設定が終わりましたら、MAMPを再起動してください。
そしてその後にブラウザにて christmas_menu.dev:8888/
にアクセスしてみて下記のLaravel5のWelcomeページが出ていましたらLaravelのインストールは終了になります。
補足としてインストールされているLaravelのバージョンを確認する場合は下記のコマンドで実行して確認を行ってください。
↓下記ターミナルでの確認&作業コマンド:
$ cd <app name on my own.>
$ php artisan --version
Laravel Framework version 5.1.28 (LTS)
もし、うまくいっていない場合には再度上記の設定手順に関して抜けや漏れがないかを再度チェックしてみてください。
※過不足などがございましたら、お申し付け頂ければ幸いに思います。
2. MAMPのデータベース(MySQL)を利用するための設定
LarvalはMySQLはもちろんpostgreSQLやSQLiteにも対応していますし、また中にビルトインサーバーも入っています。
しかし今回はMAMP内のMySQLを使用しますのでその設定を行なっていきます。
Laravel内にはアプリケーションのルートディレクトリに.envファイルという環境に応じて環境設定を書くことができるファイルがありますのでそちらを少し変更します。また、database.phpにもMAMPのMySQLを使用する旨をお伝えしないといけないので設定を行なってあげます。
また事前にMAMP上でデータベースをあらかじめ作成しておいてください。
(christmas_menuという名前で作成しておきました。)
★2-1. .envファイルの変更
↓下記ターミナルでの確認&作業コマンド:
$ php artisan env
Current application environment: local
$ vim .env
//下記4つをMAMPの設定にする
DB_HOST=localhost
DB_DATABASE=christmas_menu
DB_USERNAME=root
DB_PASSWORD=root
上記の設定はMAMPの設定になります。
MySQLの接続情報はMAMPのスタートページで確認できます。
※注意点:こちらも本番で運用する際はデータベースのID/PASSがrootのままではセキュリティ上宜しくないので適宜変更をして下さい。
★2-2. database.phpの変更
//MAMP用に少し設定変更
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'christmas_menu'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'root'),
//MAMPのUnixSocketを追記
'unix_socket' => '/Applications/MAMP/tmp/mysql/mysql.sock',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
3. Composerで必要なライブラリのインストールと設定
今回のサンプルアプリケーションで使用するのは下記の2つのライブラリになります。
★3-1. Form用のヘルパー関数パッケージ:LaravelCollective/html
こちらはHTMLのヘルパーを提供してくれるライブラリになります。今回は入力フォームやボタン周りに関するHTMLの編集を簡単にするために今回は活用することにしました。
★3-2. 画像アップロード用パッケージ:CodeSleeve/laravel-stapler
こちらは画像ファイルをアップロードを便利にしてくれるライブラリになります。挙動や設定の方法に関しては、Ruby on RailsのPaperclipにインスパイアされて作られているので、一度Paperclipを使ったことがある方であればその方法に近しい形で実装ができます。
※個人的にかなり好きで気に入っているライブラリでしたので今回は独断と偏見で入れてみました。
※「画像アップロードのお話と僕が作っているもの」は昨年のLaravel AdventCalendarで私が書いたものになります(Laravel4.2のものですがご参考まで)
★3-3. JFYI 日本語化のライブラリ:laravel-ja/comja5
こちらは今回は一応入れただけの状態ではあるんですけど、実際に入れておくと便利かもしれません。
ファイルのコメントを日本語に翻訳してくれます。
★3-4. Composerを用いてインストールを行う
まずはcomposer.jsonに上記のライブラリのインストールをするために追記を行います。
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.1.*",
"laravelcollective/html": "~5.0", //追加
"laravel-ja/comja5": "^1.0", //任意
"codesleeve/laravel-stapler": "1.0.*" //追加
},
追記が終わりましたらライブラリをインストールします。
↓下記ターミナルでの確認&作業コマンド:
$ sudo composer update
インストールが完了するまで時間がかかるとは思いますが、気長に待ちましょう。
★3-5. インストールしたライブラリの有効化を行う
Composer経由でインストールしたらそのライブラリを有効化してあげます。
今回のサービス・プロバイダーやファサードの登録を行うついでだから他の部分の細かな設定も行なっておきましょう。
return [
//——(省略)—-
//タイムゾーンの設定
'timezone' => 'Asia/tokyo',
//言語を日本語にしておく
'locale' => 'ja',
//——(省略)—-
//サービス・プロバイダーの設定
'providers' => [
//——(省略)—-
Collective\Html\HtmlServiceProvider::class,
Codesleeve\LaravelStapler\Providers\L5ServiceProvider::class,
],
//ファサードの設定
'aliases' => [
//——(省略)—-
'Form' => Collective\Html\FormFacade::class, // 追加
'Html' => Collective\Html\HtmlFacade::class, // 追加
],
];
以上ここまでが下準備の段階になります。ちょっと長くって少々疲れたかもしれませんが、ここからがいよいよ開発スタートになります。それでは少し休憩をとって再開しましょう!
4. テーブル定義
ここからはやっと具体的な開発に入っていきます。環境構築の方にかなりのボリュームを割きましたが、ここからは実際に実装に直結するコードを書いていく部分になります。やはり自分の作ったアプリケーションが正しく動作するのは嬉しいものですので、もう少しお付き合い頂ければと思います。
★4-1. MAMPのMySQLに”topics”テーブルを作成する流れ
こちらもphpMyAdminを手動でいじることなく、artisanコマンドでテーブルのスキーマ定義を行うことができます。大まかな流れとしては、
- マイグレーションファイルを作成
- テーブルのスキーマを記述
- マイグレーションを実行
という順番になります。
★4-2. MAMPのMySQLに”topics”テーブルを作成
まずはマイグレーション用のファイルの雛形を作成してあげます。ここではテーブルの新規作成なので、create_[テーブル名の複数形]_table
としています。
↓下記ターミナルでの確認&作業コマンド:
php artisan make:migration create_topics_table
下記が今回作成したスキーマファイルになります。今回はLaravel-Staplerを使用するので画像ファイルに関するテーブルも一緒にこの段階で定義してあげます。
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTopicsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//topicsテーブルを生成する
Schema::create('topics', function(Blueprint $table)
{
$table->increments('id');
$table->string('title');
$table->text('body');
$table->date('published');
$table->timestamps();
//Add columns for Laravel Stapler
$table->string('eyecatch_file_name', 256);
$table->integer('eyecatch_file_size');
$table->string('eyecatch_content_type', 256);
$table->timestamp('eyecatch_updated_at');
/*
JFYI:laravel-stapler用のカラム追加
カラム名:eyecatch_file_name => varchar(256)
カラム名:eyecatch_file_size => int(11)
カラム名:eyecatch_comtent_type => varchar(256)
カラム名:eyecatch_updated_at => timestamp
*/
/*
JFYI:カラムの詳細設定をする場合はこちらを参考にしてみてください
http://laravel.com/docs/5.1/migrations#writing-migrations
*/
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//topicsテーブルを削除する
Schema::drop('topics');
}
}
マイグレーションファイルが完成したら、マイグレーションを実行してテーブル定義をMAMPのMySQLに反映させます。
※usersテーブル等のマイグレーションファイルがデフォルトで入っていると思いますがこれらは特に今回はいじらなくて大丈夫です。
↓下記ターミナルでの確認&作業コマンド:
php artisan migrate
下記のようにテーブル定義が下記のスクリーンショットのように、topicsテーブルが作成されて、スキーマきちんと反映されていれば設定完了になります。
マイグレーションファイルでの各々のカラムの詳細な設計に関しては下記が参考になりました。
5. モデルの定義と実装
ここではデータの振る舞いを決めるモデル部分の作成を行なっていきます。今回はデフォルトのモデルをそのまま使うわけではありませんが、一部の記述を除けばほとんど同じかと思います。
いよいよやっと実際の開発らしくなってきましたね。
★5-1. モデルTopic.phpを作成する
Laravel5系からはモデルファイルの定義場所はapp配下
に配置されるようになりました。
また今回は画像アップロード用のライブラリを使うのでデフォルトのモデルファイルを少しだけカスタマイズして使う形になります。大まかな流れとしては、
- モデルファイルの雛形を作成
- Topic.phpの編集する
という流れになります。
※こちらはもちろん手動で作成しても問題ありません。
※Laravel-Staplerに対応したモデルの書き方の詳細やその他設定等に関する情報は、前述したLaravel-StaplerのREADMEに詳細に掲載があります(若干怪しいところもありますが...)ので気になった方は是非とも参考にしてみてもよいと思います。
★5-2. Topic.phpの全文
まずは下記のコマンドを用いてモデルファイルの雛形を作成します。
↓下記ターミナルでの確認&作業コマンド:
※ちゃんとDBと接続できてクエリが実行されているかのチェックも含みます(空の配列が来ることを確認する)
$ php artisan make:model Topic
$ php artisan tinker //コンソールチェック
Psy Shell v0.6.1 (PHP 5.6.10 — cli) by Justin Hileman
>>> App\Topic::all()->toArray();
=> []
>>> exit
これで app/Topic.php
が作成されました。ただ文字データを登録するだけならこのままでも事足りるのですが今回は画像のアップロード機能があるので、その後は下記のソースのように作成されたTopic.phpを書き換えていきます。
<?php
namespace App;
use Codesleeve\Stapler\ORM\StaplerableInterface;
use Codesleeve\Stapler\ORM\EloquentTrait;
use Illuminate\Database\Eloquent\Model;
class Topic extends Model implements StaplerableInterface {
//Staplerの読み込み
use EloquentTrait;
protected $fillable = array('title', 'body', 'published', 'eyecatch');
//コンストラクタ
public function __construct(array $attributes = array()) {
//画像の投稿設定
$this->hasAttachedFile('eyecatch', [
//画像の切り取るサイズのパターン
'styles' => [
'large' => '640x480#',
'medium' => '300x200#',
'thumb' => '100x75#'
],
//格納ディレクトリ(public配下からのパス)
'url' => '/uploads/topics/:id/:style/:filename'
/* JFYI:S3を使用する際の設定のテンプレート的なもの(まだ未検証)
's3_client_config' => [
'key' => 'xxxx',
'secret' => 'xxxx',
'region' => 'xxxx'
],
's3_object_config' => [
'Bucket' => 'xxxx',
'ACL' => 'xxxx'
],
'storage' => 's3',
*/
]);
parent::__construct($attributes);
}
}
変数 $fillable
の中には実際にMAMPのMySQLに格納するものを設定します。
(今回はView側のinputタグのname属性に該当するものになります)
先ほどのLaravel-Staplerでの画像アップロードをするのでeyecatch
という要素を追加しています。
またその他に今回のTopic.phpのポイントをざっくりというと、
- Laravel-Staplerを使うにあたって必要なものを読み込む宣言をする
- Laravel-Stapler用にコンストラクタを定義する
- 定義したコンストラクタの中に画像の切り出しサイズや格納場所の指定をする
の3点になります。これでモデルファイルの設定は完了です。
(余談)前述した内容と重複するかもしれませんが、このLaravel-StaplerはRuby on Railsの画像アップロードで有名なGemの一つであるPaperclipにインスパイアされて作成されたLaravel用のライブラリになります。なので画像の切り出しや格納場所の設定はほとんどPaperclipと同じ書き方をしています。他にも他の言語のフレームワークの機能やライブラリからインスパイアされたものもあるかもしれませんので色々調べてみても面白いかもしれませんね。
6. コントローラーの定義と実装
モデルを作成したので、次はコントローラーを実装していきます。
今回はシンプルなMVCパターンに則ったアプリケーションを想定していますので下記のように、
- データ一覧表示
- データ個別表示
- データ1件新規追加
- 既存データ1件編集
- 既存データ1件削除
に関するアクションを記述していきます。
★6-1. TopicController.phpの作成
Laravel5系からはコントローラーファイルの定義場所はapp/Http/Controllers
に配置されるようになりました。
それでは上記の要件を満たすようなコントローラーを実際に作成していきます。
また今回はコントローラー内で画面から送られてきたデータに関するバリデーションを行うのでこの後の章で日本語のバリデーションを追加します。
コントローラー自体を作成する大まかな流れとしては、
- コントローラーファイルの雛形を作成
- TopicsController.phpの編集する
※こちらはもちろん手動で作成しても問題ありません。
↓下記ターミナルでの確認&作業コマンド:
$ php artisan make:controller TopicsController --plain
これでコントローラーの雛形ができましたので、その後は実際に上記の要件に関する処理をこのコントローラーへ追記をしていく形になります。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
//モデルの宣言
use App\Topic;
class TopicsController extends Controller
{
//一覧
public function index() {
//Topicsテーブルのデータをすべて取得する
$topics = Topic::all();
return view('topics.index', compact('topics'));
}
//表示
public function show($id) {
$topic = Topic::findOrFail($id);
return view('topics.show', compact('topic'));
}
//追加
public function add() {
return view('topics.add');
}
public function create(Request $request) {
//バリデーションを行う(正常:新規データ1件登録して一覧画面へ, 異常:メッセージを表示して入力画面へ)
//バリデーションメッセージは resources/lang/ja/validation.phpを参照
$this->validate($request, [
'title' => 'required|min:3', //最低3文字以上
'body' => 'required',
'eyecatch' => 'image|max:2000', //画像に関するバリデーション(画像形式とファイルサイズ)
'published' => 'required|date',
]);
//新規データ1件登録
Topic::create($request->all());
//一覧画面へリダイレクト
\Session::flash('flash_message', 'Topic successfully added!');
return redirect('/');
}
//編集
public function edit($id) {
//$idに該当するデータを1件取得する
$topic = Topic::findOrFail($id);
return view('topics.edit', compact('topic'));
}
public function update($id, Request $request) {
//$idに該当するデータを1件取得する
$topic = Topic::findOrFail($id);
//バリデーションを行う(正常:新規1件登録して一覧画面へ, 異常:メッセージを表示して入力画面へ)
//バリデーションメッセージは resources/lang/ja/validation.phpを参照
$this->validate($request, [
'title' => 'required|min:3', //最低3文字以上
'body' => 'required',
'eyecatch' => 'image|max:2000', //画像に関するバリデーション(画像形式とファイルサイズ)
'published' => 'required|date',
]);
//既存データ1件更新
$topic->fill($request->all())->save();
//一覧画面へリダイレクト
\Session::flash('flash_message', 'Topic successfully edited!');
return redirect('/');
}
//削除
public function delete(Request $request) {
//削除対象の$idを取得する
$target_id = $request->id;
//$idの形式が正しいかのチェック(注意:この部分は実際に使う場合はより厳密なチェックが必要)
if ($target_id && is_numeric($target_id)) {
//既存データ1件削除
$topic = Topic::findOrFail($target_id);
$topic->delete();
//削除成功時のメッセージを表示
\Session::flash('flash_message', 'Topic successfully deleted!');
} else {
//削除失敗時のメッセージを表示
\Session::flash('flash_message', 'Topic delete failed! Because something went wrong.');
}
//一覧画面へリダイレクト
return redirect('/');
}
}
上記のソースコードでの追加・変更・削除時の振る舞いの想定としては、
- 追加時:add ※画面表示 → create ※実際の処理
- 編集時:edit ※画面表示 → update ※実際の処理
- 削除時:delete ※実際の処理
のような形になります。
またデータidをキーとしたデータ抽出を行っている findOrFail
メソッドを使っています。
こちらは引数にidをして、該当idのレコードを1件取得し、該当のレコードがない場合は例外を返すメソッドになります。
★6-2. 日本語版のバリデーションの追加
コントローラー内でPOSTで渡ってきたデータに対してバリデーションを行っていますが、デフォルトでは英語表記になっています。
バリデーション時の文言もできれば日本語にしたいので、新たに日本語用のバリデーションファイルを作成します。
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
*/
"date" => ":attributeは正しい日付(yyyy-MM-ddの形式)ではありません。",
"min" => [
"string" => ":attributeは:min文字以上入力してください。",
],
"required" => ":attributeを入力してください。",
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
*/
'attributes' => [
'title' => 'タイトル',
'body' => '本文',
'published' => '公開日',
],
];
※ 今回はこのサンプルに合わせた必要最小限の実装になっています。
個人的にバリデーションの書き方が最初はPHPっぽくなくて若干戸惑いましたが今になってみると結構シンプルに書けるなと思います。
7. ルーティングの定義と実装
Laravel5系のルーティングはapp/Http/routes.php
に記載されています。
(Laraval4系とは大きく該当ファイルの格納場所が変更されていますのでLaravel4系を以前にお使いになっている方はびっくりするかもしれません)
今回は前述のコントローラーの部分でも作成した、
- データ一覧表示
- データ個別表示
- データ1件新規追加
- 既存データ1件編集
- 既存データ1件削除
に関するルーティングを定義してあげます。
今回はシンプルにModel, Controller, View, Routingだけを使ったサンプルでLaravelの他にもある便利機能に関してはそれほど使用していませんが、書いている部分も少ないのでご自分でお試しする際にもちょうど良い分量ではないかと思います。
★7-1. routes.phpの変更
デフォルトの状態ではWelcomeページのルーティングが貼られているだけなので、こちらを下記のように変更してあげます。
<?php
//全トピック表示画面
Route::get('/', 'TopicsController@index');
//トピックの新規追加画面
Route::get('/topics/add', 'TopicsController@add');
Route::post('/topics/create', 'TopicsController@create');
//任意idのトピック表示
Route::get('/topics/{id}', 'TopicsController@show');
//任意idのトピック編集
Route::get('/topics/edit/{id}', 'TopicsController@edit');
Route::post('/topics/update/{id}', 'TopicsController@update');
//任意idのトピック削除
Route::post('/topics/delete', 'TopicsController@delete');
上記のような形でリクエストの形式と対応するURLと対応するコントローラーのアクション名を記載します。
{id}の部分はTopicsテーブルのidが入る形になります。
★7-2. ルーティングかきちんと貼られているかの確認
プログラムで定義した後は、できるだけルーティングがしっかりと貼られているかの確認をしておきたいところです。(実際の仕事とかであればテストテストコード等によるチェックが一番良いとは思いますが、今回はこの部分は割愛)
設定したルーティングの確認は下記のコマンドで行うことができます。
↓下記ターミナルでの確認&作業コマンド:
$ php artisan route:list
+--------+----------+--------------------+------+----------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+--------------------+------+----------------------------------------------+------------+
| | GET|HEAD | / | | App\Http\Controllers\TopicsController@index | |
| | GET|HEAD | topics/add | | App\Http\Controllers\TopicsController@add | |
| | POST | topics/create | | App\Http\Controllers\TopicsController@create | |
| | POST | topics/delete | | App\Http\Controllers\TopicsController@delete | |
| | GET|HEAD | topics/edit/{id} | | App\Http\Controllers\TopicsController@edit | |
| | POST | topics/update/{id} | | App\Http\Controllers\TopicsController@update | |
| | GET|HEAD | topics/{id} | | App\Http\Controllers\TopicsController@show | |
+--------+----------+--------------------+------+----------------------------------------------+------------+
正しく設定ができているならば上記のような表示
これでコントローラーとURLの対応が完了しましたので、次はコントローラーの実装を行なっていきます。
8. ビューの定義と実装
Laravel5系からはビューファイルの定義場所はresources/views
に配置されるようになりました。
テンプレートはbladeをしており拡張子はxxx.blade.php
となります。ざっくりといえばその他PHPのテンプレートエンジンのSmartyやTwigと似たようなものです。
前の章で書いたコントローラーにそれぞれ対応するビューを記述していきます。また今回のコントローラー内では return view('ビューの配置場所', 渡す変数);
という形で対応するビューを表示させます。
今回のサンプルでの対応は下記のようになります。
- データ一覧表示:resources/views/topics/index.blade.php
- データ個別表示:resources/views/topics/show.blade.php
- データ1件新規追加:resources/views/topics/add.blade.php
- 既存データ1件編集:resources/views/topics/edit.blade.php
- 既存データ1件削除:なし
今回は各コンテンツの一番外の枠になるテンプレートを継承させて上記の各コンテンツのビューを当て込んでいくようなイメージになります。
また今回はデザインのフレームワークとしてTwitterBootstrapを使用しています。
TwitterBootstrapに関して詳しく見てみたい方は下記をご参考にして頂ければと思います。
★8-1. resources/views/layouts/app.blade.phpの新規作成
こちらは各コンテンツの一番外の枠になるテンプレートになります。
@yield('content')
の中に各々のコンテンツのテンプレートの内容がはめこまれていくようなイメージです。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>My Christmas Dinner List</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
</head>
<body style="padding-top:50px;" role="document">
<!-- 共通ナビゲーション -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">My Christmas Dinner List</a>
</div>
</div>
</div>
<div class="container">
@yield('content')
</div>
<hr>
<footer class="footer">
<div class="container">
<p>Copyright © 2015 just1factory All Rights Reserverd.</p>
</div>
</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>
ここでは、本当にヘッダーとフッターのサイトの外枠部分が定義だけがされている感じです。
★8-2. 各アクションに対応するbladeテンプレートの新規作成
1. データ一覧表示:resources/views/topics/index.blade.php
下記が該当のテンプレートになります。
※ここからは各テンプレートに関する詳細な解説は割愛しますが、各テンプレートで気をつけるポイントのみを適宜かいつまんで解説していきます。
<!-- resouces/views/topics/index.blade.php -->
@extends('layouts.app')
@section('content')
<h1>クリスマスに食べたい・作りたい料理のリスト</h1>
<hr>
@if(Session::has('flash_message'))
<div class="alert alert-success">
{{ Session::get('flash_message') }}
</div>
<hr>
@endif
@foreach($topics as $topic)
<article>
<table class="table table-bordered">
<tr class="info">
<th colspan="3"><span>[ID:{{ $topic->id }}]</span> <a href="{{ url('topics', $topic->id) }}">{{ $topic->title }}</a></th>
</tr>
<tr>
<td width="100"><b>サムネイル画像</b></td>
<td><b>本文</b></td>
<td width="100"><b>日付</b></td>
</tr>
<tr>
<td width="100"><img src="{{ $topic->eyecatch->url('thumb') }}"></td>
<td><div class="body">{{ str_limit($topic->body, 300, $end = '... [If you show more, please click title.]') }}</div></td>
<td width="100">{{ $topic->published }}</td>
</tr>
</table>
</article>
<hr>
@endforeach
{!! link_to('topics/add', '新規作成', ['class' => 'btn btn-primary']) !!}
@endsection
このファイルで気をつけるポイント:
下記でピックアップするポイントは
- ComposerでインストールしたLaravelCollective/htmlのメソッド
- Laravelであらかじめ用意されているHelper Functions
- Laravel-Staplerでの画像表示の際の書き方
を活用した書き方を利用しています。実際のリファレンスやURLのリンク先は英語になりますがドキュメントを深掘りするだけでもとても参考になります。
- ポイント1:アンカーリンクの記載
{!! link_to('topics/add', '新規作成', ['class' => 'btn btn-primary']) !!}
LaravelCollective/htmlのlink_toメソッドの使い方について(英語)
→ このメソッドはアンカーリンクを生成します(LaravelCollective/htmlを利用)。今回ではlink_to('リンク先', 'リンクに表示する文字', idやclass属性を設定した配列)
という形になります。
- ポイント2:出力文字数の制限
{{ str_limit($topic->body, 300, $end = '... [If you show more, please click title.]') }}`
str_limitメソッドの使い方について(英語)
→ 文字列の表示制限をしています(LaravelのHelper Functionsを利用)。str_limit('表示する文字列', 制限数, 文字列を制限数で切った後に表示する文字列)
という形で文字の表示制限をしています。
- ポイント3:画像のアップロード先URLの出力
{{ $topic->eyecatch->url('thumb') }}
Laravel-Staplerを利用した際のアップロード画像の表示方法(英語)
→ こちらはアップロードした画像のパスを表示します。実際にimgタグで表示する場合は<img src="{{ $topic->eyecatch->url('thumb') }}">
とします。
2. データ1件新規追加:resources/views/topics/add.blade.php
下記が該当のテンプレートになります。
※ 既存データ1件編集に関して:
resources/views/topics/edit.blade.phpは
{!! Form::text('title', null, ['class' => 'form-control']) !!}
{!! Form::textarea('body', null, ['class' => 'form-control']) !!}
の第2引数の部分にDBより取得した値が入る等若干の違いしかないのでここでは割愛します。
<!-- resouces/views/topics/add.blade.php -->
@extends('layouts.app')
@section('content')
<h1>料理のリストを新しく追加する</h1>
<hr>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
{!! Form::open(['url' => 'topics/create', 'files' => true]) !!}
<div class="form-group">
{!! Form::label('title', 'Title:') !!}
{!! Form::text('title', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('body', 'Body:') !!}
{!! Form::textarea('body', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('eyecatch', 'Eyecatch:') !!}
{!! Form::file('eyecatch', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('published', 'Publish On:') !!}
{!! Form::input('date', 'published', date('Y-m-d'), ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::submit('Add Topic', ['class' => 'btn btn-primary form-control']) !!}
</div>
{!! Form::close() !!}
@endsection
このファイルで気をつけるポイント:
- ポイント1:formタグの生成と画像のアップロードへの対応
{!! Form::open(['url' => 'topics/create', 'files' => true]) !!}
--- (省略) ---
{!! Form::close() !!}
LaravelCollective/htmlのFormタグの書き方について(英語)
→ フォームタグの生成もLaravelCollective/htmlのFormクラスのメソッドを使用して上記のように記述すると
<form method="POST" action="http://christmas_menu.dev:8888/topics/create" accept-charset="UTF-8" enctype="multipart/form-data">
--- (省略) ---
</form>
という感じでformタグを生成してくれます。また今回は画像のアップロードを含むのでenctypeの設定も必要なのですがこの部分は'files' => true
を追加すればOKです。
- ポイント2:inputタグのfile属性の設定方法
{!! Form::file('eyecatch', null, ['class' => 'form-control']) !!}
LaravelCollective/htmlのinputタグのfile属性の書き方について(英語)
→ 画像アップロードのエリア部分に関しては上記のように設定を行います。それ以外のinputタグやlabelタグの書き方もLaravelCollective/htmlのドキュメントに掲載されていますので是非参考にしてみて下さい。
3. データ個別表示:resources/views/topics/show.blade.php
下記が該当のテンプレートになります。
<!-- resouces/views/topics/show.blade.php -->
@extends('layouts.app')
@section('content')
<article>
<h1>{{ $topic->title }}</h1>
<hr>
<section style="padding-bottom: 50px;">
<img src="{{ $topic->eyecatch->url('large') }}">
<hr>
<p class="lead">{{ $topic->body }}</p>
<hr>
<p class="lead">{{ $topic->published }}</p>
<hr>
<div style="margin-bottom: 75px;">
<div class="pull-left">
{!! link_to('/', '一覧へ戻る', ['class' => 'btn btn-info']) !!}
{!! link_to('topics/edit/' . $topic->id, '編集する', ['class' => 'btn btn-primary']) !!}
</div>
<div class="pull-right">
{!! Form::open(['url' => 'topics/delete']) !!}
{!! Form::hidden('id', $topic->id, ['class' => 'form-control']) !!}
{!! Form::submit('削除する', ['class' => 'btn btn-danger']) !!}
{!! Form::close() !!}
</div>
</div>
<hr style="clear:both;" />
</section>
</article>
@endsection
このファイルで気をつけるポイント:
- ポイント1:表示する画像サイズの設定
<img src="{{ $topic->eyecatch->url('large') }}">
→ こちらはLaravel-Staplerで設定した画像のサイズ定義の文字列を入れます。今回の画像サイズはTopic.phpで以下のように設定をしてあります。
//画像の切り取るサイズのパターン
'styles' => [
'large' => '640x480#',
'medium' => '300x200#',
'thumb' => '100x75#'
],
今回の設定ではアップロードした画像に関しては下記のようなルールでそれぞれのサイズを決定しています。
- large → 640x480# (画像サイズはwidth=640,height=480,画像はクロップする)
- medium → 300x200# (画像サイズはwidth=300,height=200,画像はクロップする)
- thumb → 100x75# (画像サイズはwidth=100,height=75,画像はクロップする)
表示する画像を指定する場合にはurl('画像サイズの文字列')
と設定をしてあげればOKです。
Viewまわりに関しては非常にざっくりとした説明で恐縮ですが、このbladeがなかなか強力なテンプレートファイルでこれのおかげで個人的な感想にはなってしまいますが、慣れると非常に気持ち良くサクサク書いていけるので気に入っています。
9. これからLaravelを始める・深堀りする際にお役に立ちそうなサイトまとめ
Laravel自体はまだまだ歴史が浅く、日本での知名度も他のフレームワークに比べれば若干低い感じはありますが、モダンな開発スタイルや頻繁な機能追加やバージョンアップ等種々の事から、最近では日本でもLaravelを採用している企業様やWebサービス等も次第に増えつつあります。
下記にささやかではありますが、Laravelの知識をさらに深堀りする上で参考になりそうなサイトを数点ほどピックアップしておきます。
- Laravel公式ドキュメントVer5.1 (英語)
- laraveltricks (英語)
- CRUD (Create Read Update Delete) in a Laravel App (英語)
-
ララ帳 はじめての LARAVEL 5.1
- minotaur #Laravel5
- kore1server
- Laravel 5.1 基本のタスクリスト
情報サイトやブログで調べると最近は日本語の情報が増えつつありますが、英語のサイトでも丁寧にコードを掲載してくれている場合が多いのでとても助かっています。
あとがき
こちらのチュートリアルは、私が初めてLaravelを触った際にプラクティスとして作成していたサンプルアプリケーション(当時のバージョンは4.2)を今回のAdventCalendarでの公開用に私なりに手順をまとめ、Laravel5.1に対応させたものになります。
実際に私はPHPのフレームワークはCakePHPからスタートし他の言語(Ruby, Objective-C, Swift)も触るのですが、Laravelは最初の環境構築は若干ハマりつつも実に便利機能やライブラリがたくさんあったこと、コミュニテイ等でも質問したりする機会に恵まれたこと等もあり、今後もたとえ実務で使わないとしても個人的なテーマとしては是非とも追いかけていきたいと思います。
まだまだチュートリアルの完成度としては、不完全な部分も多いかもしれませんが、Laravelというフレームワークに興味や関心を抱いた方が少しでも参考になり、躓くような事が少なくできればという思いでおりますので、ご質問や改善要望・不具合報告等がありましたらご遠慮なくお申し付け頂ければ幸いです。
追記とその他
2016/04/16:
画像に関するバリデーションが抜けていたので追加しました。
2016/01/26:
この日に開催された「Laravelリファレンス出版記念イベント」にてこちらのQiita記事をお見せした際にいくつか「この部分を加筆するとさらに良いのではないか」というアドバイスを頂きましたので、一部注意事項の加筆とView周りのポイントを詳細を追記しました。貴重なアドバイス本当にありがとうございました!
2015/12/26:
Githubに誤りがありましたのでこちら正しいものへ差し替えました。申し訳ございませんでした。
2015/12/28:
記事の軽微な修正とGithubの方へのこのサンプルの登録データのSQLファイルを追加しました。
2016/01/01:
Laravalのバージョン指定(5.1)を行ってのインストールコマンドの修正と補足事項(インストールされているLaravelのバージョン確認方法)を追記しました。