読者です 読者をやめる 読者になる 読者になる

【Laravel5】開発する上で最低限必要そうなことをまとめておく

はじめに

最近流行りのLaravelを調べたのでまとめておく
実案件で使うかは未定だが実際使うときに簡単に導入できるようにというのが目的

やること

・1. Laravelインストール
・2. 設定ファイルなどを修正
・3. ページの作成手順(Routerの設定とViewとControllerの作成)
・4. DBを使う
・5. SQLをログに残す
・6. セッションを使う
・7. アプリ全体の共通処理を実装する(ログイン認証、ログ出力など)
・8. エラー処理
・9. バリデーション実装(入力フォームとか)
・10. ページネング

1. インストール

作業のながれは
・composerインストール(なければ)
・Laravelインストール

composerインストール

ダウンロード

> curl -sS https://getcomposer.org/installer | php -- --install-dir=/home/userdir/bin
> mv ~/bin/composer.phar ~/bin/composer

PATHを通す
~/.bash_profile

・・・
PATH=$PATH:$HOME/.composer/vendor/bin
・・・

反映

source ~/.bash_profile
Laravelインストール
cd /path/to
laravel new app // appはアプリごとに決める

ブラウザよりアクセスしてLaravelと書かれたページが表示されればOK
例) http://example.com

2. 設定ファイルなどを修正

アプリ全体の設定を行う
ドメイン
・環境(開発、Staging、本番など)
・DBサーバー設定

.env

APP_ENV=develop                          ## develop or stging or productionなど
APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxx= ## いじらない
APP_DEBUG=true                           ## trueだとエラー画面にデバッグ情報が表示されるので本番とかではfalseに
APP_LOG_LEVEL=debug                      ## ログ出力のポリシー設定(error、critical、alert、emergency)
APP_URL=http://example.com               ## アプリごとに設定

DB_CONNECTION=mysql                      ## データベース設定
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dbname
DB_USERNAME=username
DB_PASSWORD=password

MAIL_DRIVER=smtp                         ## メール設定
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

設定を反映

php artisan config:cache

3. ページの作成手順(Routerの設定とViewとControllerの作成)

今回はありがちな以下の3画面を作る想定
・一覧画面 http://example.com/
・新規登録画面 http://example.com/input
・新規登録確認画面 http://example.com/confirm
・登録処理 http://example.com/complete

で、confirmとcompleteはPOST送信とします

url振り分け(ルーティング)

app/Http/routes.php

Route::get('/', 'Index@index');            // app/Http/Controllers/index.php#indexメソッドが呼ばれる
Route::get('input', 'Input@index');        // app/Http/Controllers/input.php#indexメソッド
Route::post('confirm', 'Confirm@index');   // app/Http/Controllers/confirm.php#indexメソッド
Route::post('complete', 'Complete@index'); // app/Http/Controllers/compete.php#indexメソッド
ControllerとView作成

コマンドで作成

php artisan controller:make index.php

app/Http/Controllers/Index.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;

class Index extends Controller
{
    // 追加した
    public function index()
    {
        return view('index', [ "name" => "名前" ]);
    }
}

resources/views/index.blade.php

{{ $name }}

静的なページならこれで完成

4. DBを使う

DBサーバーへの接続先の設定などは既に済んでいるので実際に使い方。
接続先情報とか以外の設定(文字コードとか)はconfig/database.phpに設定してあるので必要なら編集

テーブル作成

とりあえず以下のルールで作っておくとよさそう
・テーブル名は複数形(testならtests)
・idというカラム名でオートインクリメントなプライマリキーをもつ
・created_at、modified_atをtimestamp型でもつ

上記の形で自分は特に困ることもないと思うのでこの通りにする

ちなみにMigrationという機能を使えばスキーマの変更が管理できる。
なので複数人で作業していてかつ各自がローカルの開発環境で開発している場合は使ったほうがよいかも。
自分は1人で作業することや共通の開発サーバーで作業することが多いのでとりあえず使わない

また、本番機とかでスキーマの変更するときは手順もちゃんと考慮しないといけないのでリリース作業とかで使うのもちょっと怖いかも。。。

Modelの作成

DB::select、DB::insert、DB::update、DB::deleteメソッドにSQL文を渡せば直接SQLを実行できる。
が、各テーブルごとにModelを継承したクラスを作っておけば簡単にDB処理できるメソッドが使える

DB:selectとかを使うにしてもControllerから直接呼ぶのではなくModel作ってそのメソッドから呼ぶ形にしておくのが良いかな。
別のフレームワークでもそうしてきたし。。。 

コマンドで作成

php artisan make:model Model/Test

app/Model/Test.php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Sample extends Model
{
}

これでModelであらかじめ用意されているメソッドが使えるようになる

Controllerから呼び出す
app/Http/Controllers/Index.php

use App\Model; ## 追加

class Test extends Controller
{
    ・・・

    public function index()
    {
        ## Modelのメソッドを呼び出す
        Model\Test::all();
    }
}

https://readouble.com/laravel/5.1/ja/queries.html
https://readouble.com/laravel/5.1/ja/eloquent.html
上記らへんにクエリビルダやormの使い方がのってるので都度確認しながら開発する

5. SQLをログに残す

基本的にシステムが落ち着くまでは自分は全て残しておきたいので全クエリ出してしまう
やり方は検索したらいっぱい出てきた

app/Providers/EventServiceProvider.php

public function register()
{
    \DB::listen(
        function($query) {
            \Log::debug("SQL LOG::", [$query->sql, $query->bindings, $query->time]);
       }
   );
}

6. セッションを使う

これだけか。。。

\Session::set("key", "value");
\Session::get("key");

7. アプリ全体の共通処理を実装する(ログイン認証、ログ出力など)

Middlewareクラスを作って適用させる流れになるみたい。
今回は全アクセス(デバッグor調査用途)をログ出力するMiddlewareを作る

コマンドで作成

php artisan make:middleware LogMiddleware

app/Http/Middleware/LogMiddleware.php

namespace App\Http\Middleware;

use Closure;

class LogMiddleware
{
    public function handle($request, Closure $next)
    {
        // 全アクセスのログを残す
        \Log::debug("[ACCESS]" . implode("\t", array(
            $request->ip(),
            $request->path(),
            $request->method(),
            $request->server("HTTP_USER_AGENT"),
        )));

        return $next($request);
    }
}

アプリ全体に適用する
app/Http/Kernel.php

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \App\Http\Middleware\LogMiddleware::class, // ★これを追加
];

今回はアプリ全体に適用したが、特定のURLのみに適用することも可

8. エラー処理

やりたいことは以下
・エラーログ出力
・アラートメール送信
・エラーページ表示

DBエラーなどの致命的なエラーは把握したいのでアラートを送信する形に。ログは後で調査できるように残しておく。
ログ出力はLaravelが勝手にやってくれるようなのでアラートメールの送信とエラーページ表示を実装する

アラートメール送信

SMTPサーバーの設定などは既に済んでいるので実装部分だけ

app/Exceptions/Handler.php

public function report(Exception $e)
{
    if (false === stristr(get_class($e), "NotFoundHttpException"))
    {
        \Mail::send([ "text" => "mail.alert" ], ["message" => $e->getMessage()], function($message)
        {
            $message->from("alert@exmaple.com", "alert mail");
            $message->to("to@example.com")->subject("alert mail");
        });
    }
    parent::report($e);
}
エラーページ表示

resources/views/errors/500.blade.phpを作成
.envのAPP_DEBUG=falseと設定

app/Exceptions/Handler.php

public function render($request, Exception $e)
{
    // ★追加
    if (!$this->isHttpException($e)) {
        abort(500);
    }
    return parent::render($request, $e);
}

【Laravel5】エラーページ(500.blade.php)が呼ばれないときの対応 - とりあえずphpとか
なぜこうしたかは長くなったのでこちらにまとめた

9. バリデーション実装(入力フォームとか)

デフォルトのままだとバリデーション結果のエラーメッセージが英語なので日本語にする

config/app.php

・・・
'locale' => 'ja', // enから変更
・・・

resources/lang/ja/validation.phpを作成
Laravel 5.1 日本語エラーメッセージファイル – ララ帳
内容をこちらのurlを参考に

設定を反映

> php artisan config:cache

入力フォームを作って実際に使ってみる

controller(チェックする側)

$validator = \Validator::make($input,[
    "title" => "required",
    "content" => "required"
]);

$validator->setAttributeNames([
    "title" => "タイトル",
    "content" => "本文",
]);

if ($validator->fails()) {
    redirect()->back()->withErrors($validator->errors())->withInput();
}

View(入力画面)

<?php foreach ($errors->all() as $error) { ?>
  <?php echo $error; ?><br />
<?php } ?>
<form method="post" action="/test/create/confirm">
  <input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
    タイトル:<input type="text" name="title" value="<?php echo old("title"); ?>" /><br/>
    本文:<textarea name="content" /><?php echo old("content"); ?></textarea><br/>
  <input type="submit" value="登録" />

10. ページング

必ず必要になる機能なのであとで使い方まとめる

その他メモ

・ログは日別に出力
レプリケーションなど複数DBに対応
・フロントと管理画面などエントリーポイントが複数ある場合
・Laravel自体が遅いという評判がいくつか見たので検証

さいごに

こんなものかな。なんかPHPフレームワークはどれも似たような感じになるのかなと感じる。
Laravelのormが優れているから使うっていう人もいるみたいなのでこれの使い方も調べてみる

viewに<?php 〜; ?>を直接書くのと、Formヘルパーとか使わないのは世間的にはNGなのだろうか。

以上です