nazolabo

フリーランスのWebエンジニアが近況や思ったことを発信しています。

Laravel5を試す

Laravelとか初めて使うよ!出たばっかりなので試す。

この記事はLaravel5.0が出たばかりに書いた内容です。最新の内容と必ず比較してください。

インストール

PHP5.5以上とmcrypt/openssl/mbstringとcomposerが入ってる前提。 まずインストーラのインストール

php composer.phar global require "laravel/installer=~1.1"

プロジェクトの作成

laravel new blog

とりあえず

$ php artisan -v
Laravel Framework version 5.0

Usage:
 [options] command [arguments]

Options:
 --help (-h)           Display this help message
 --quiet (-q)          Do not output any message
 --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 --version (-V)        Display this application version
 --ansi                Force ANSI output
 --no-ansi             Disable ANSI output
 --no-interaction (-n) Do not ask any interactive question
 --env                 The environment the command should run under.

Available commands:
 clear-compiled       Remove the compiled class file
 down                 Put the application into maintenance mode
 env                  Display the current framework environment
 help                 Displays help for a command
 inspire              Display an inspiring quote
 list                 Lists commands
 migrate              Run the database migrations
 optimize             Optimize the framework for better performance
 serve                Serve the application on the PHP development server
 tinker               Interact with your application
 up                   Bring the application out of maintenance mode
app
 app:name             Set the application namespace
auth
 auth:clear-resets    Flush expired password reset tokens
cache
 cache:clear          Flush the application cache
 cache:table          Create a migration for the cache database table
config
 config:cache         Create a cache file for faster configuration loading
 config:clear         Remove the configuration cache file
db
 db:seed              Seed the database with records
event
 event:generate       Generate the missing events and handlers based on registration
handler
 handler:command      Create a new command handler class
 handler:event        Create a new event handler class
key
 key:generate         Set the application key
make
 make:command         Create a new command class
 make:console         Create a new Artisan command
 make:controller      Create a new resource controller class
 make:event           Create a new event class
 make:middleware      Create a new middleware class
 make:migration       Create a new migration file
 make:model           Create a new Eloquent model class
 make:provider        Create a new service provider class
 make:request         Create a new form request class
migrate
 migrate:install      Create the migration repository
 migrate:refresh      Reset and re-run all migrations
 migrate:reset        Rollback all database migrations
 migrate:rollback     Rollback the last database migration
 migrate:status       Show a list of migrations up/down
queue
 queue:failed         List all of the failed queue jobs
 queue:failed-table   Create a migration for the failed queue jobs database table
 queue:flush          Flush all of the failed queue jobs
 queue:forget         Delete a failed queue job
 queue:listen         Listen to a given queue
 queue:restart        Restart queue worker daemons after their current job
 queue:retry          Retry a failed queue job
 queue:subscribe      Subscribe a URL to an Iron.io push queue
 queue:table          Create a migration for the queue jobs database table
 queue:work           Process the next job on a queue
route
 route:cache          Create a route cache file for faster route registration
 route:clear          Remove the route cache file
 route:list           List all registered routes
schedule
 schedule:run         Run the scheduled commands
session
 session:table        Create a migration for the session database table
vendor
 vendor:publish       Publish any publishable assets from vendor packages

とか出ればOK。コマンド眺めるだけでも充実してるのがわかる。 artisanはアルチザンと読むらしい。ちなみにlaravelはララベル。

ついでにサーバも立ち上げてみる。

$ php artisan serve
Laravel development server started on http://localhost:8000

昔はphp artisan serveとかあったらしいけど何故か消えたらしい。まあ別にphpコマンドで十分だから必要ないのかもしれない。

アプリ名の設定

php artisan app:name MyBlog

app以下のnamespaceが変わるだけっぽい。 ただしこのままだとcomposerの設定が残ってて動かないので、php composer.phar updateを一発叩く必要がある。

その他の設定

環境によってはstorageに書き込み権限が必要。 面倒だったらHomesteadというVagrant boxを使うと初期設定を全部スキップできる。

ルーティング

app/Http/routes.phpが最初に読まれるファイルになる。 ここに処理を直接書くこともできる。マイクロフレームワークっぽい。

// app/Http/routes.php

Route::get('/hello', function()
{
    return 'Hello World';
});

これでhttp://localhost:8000/helloにアクセスするとHello Worldと表示される。

ルーティング(コントローラー)

まあ正直これだとだるいので、コントローラーにも書ける。どっちも選べるのは良い。 routes.phpを見た時点で気がついているだろうけど、ルーティングに文字列を入れるとコントローラー指定になる。

// app/Http/routes.php
Route::get('/', 'WelcomeController@index');

でもこれでも個別で指定するの面倒なので

// app/Http/routes.php
Route::controller('article', 'ArticleController');

とかでコントローラーまとめて指定できる。 この場合、URLとメソッドの対応をどのようにすればいいのかと言うと、[リクエストメソッドの小文字][URLパラメータの頭大文字]という指定でできる。つまり/article/indexは、public function getIndex()となる。このへんリフレクションでやってるっぽいので、ちょっと遅いかもしれない。Route::get()のような指定方法のほうが高速に見える。コントローラー使わないのが不便だけど最速っぽい。 ちなみにいわゆるsnake_caseCamelCase変換ではなく、url-patternFunction_nameという変換が入る。ちょっと変な感じ。function getShow_user()みたいな変なメソッド名になる。 Controllerの書き方は他のやつをコピペするか、この後のCRUD自動生成で生成でも良い。 laravel-annotationsを入れるとアノテーションでも書ける。

CRUD自動生成

昔懐かしのscaffoldみたいなやつ。

php artisan make:controller ArticleController

で、routes.php

// app/Http/routes.php
Route::resource('article', 'ArticleController');

とすると、indexとかstoreとかshowとかってメソッドにすぐアクセスできるようになる。 昔懐かしのscaffoldと違うのは、中身は用意してくれないので、自分で書く必要がある。まあ管理画面作るくらいなら便利なんじゃないのって感じ。余計なお世話はしてくれない。

ビュー(テンプレート)

ビューはresources/views/に入れる。なんでControllerと同階層じゃなくてトップレベルなの?という疑問が残るが、それがいいと思ったのだろう。 テンプレートエンジンはBladeと呼ばれるLaravel用エンジンが使われる。{{ $hoge }}で変数を出力して、条件式などは@から始まる書式を使う。拡張子.blade.php。末尾phpである必要あるのかな?

// app/Http/Controllers/ArticleController.php

class ArticleController extends Controller {
     public function getIndex()
     {
        return view('article.index', ['hoge’=><fuga>']);
     }

とか作って

<!— resources/views/article/index.blade.php —>
@extends('app')

@section('content')
article index {{ $hoge }}
@endsection

で表示ができる。 ちなみに昔は{{ }}はエスケープせずに表示で、エスケープする場合は{{{ }}}だったらしいが、5からはどちらもエスケープするようになり、エスケープしない場合は{!! !!}という書式を使う必要がある。

モデル

モデルはデフォルトでapp/直下に置くらしい。うーん。 とりあえずここではそのままapp/直下に置くが、autoloadされるディレクトリであればどこでもいいらしいので、必要であれば変えれば良い。 app/Article.phpを作る。

<?php namespace MyBlog;
// app/Article.php

use Illuminate\Database\Eloquent\Model;

class Article extends Model {
     protected $table = 'articles';
}

スキーマはここには書かず、database/migrations/に書く。このファイルはartisanコマンドで生成する。

$ php artisan make:migration --table=articles create_articles
Created Migration: 2015_02_05_120749_create_articles

中身を書く

// database/migrations/[日付とか]_create_articles.php

     /**
      * Run the migrations.
      *
      * @return void
      */
     public function up()
     {
          Schema::create('articles', function(Blueprint $table)
          {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->dateTime('created_at');
            $table->timestamp('updated_at');
          });
     }

     /**
      * Reverse the migrations.
      *
      * @return void
      */
     public function down()
     {
          Schema::drop('articles');
     }

流す前にDBの設定をしておく。config/database.phpで設定する…と思いきや、ルートにある.envファイルを書き換えれば大抵は大丈夫なようになっている。.env.exampleをコピーして.envファイルを作り、DB_xxxを変更する。なおMySQLがデフォルト。 変更したらデータベースは事前に作っておいて、以下のコマンドを流す。

$ php artisan migrate:install
Migration table created successfully.

$ php artisan migrate:refresh
Nothing to rollback.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2015_02_05_120749_create_articles

こんな感じ。

とりあえずインタラクティブシェルで試す。

$ php artisan tinker
Psy Shell v0.3.3 (PHP 5.6.4 — cli) by Justin Hileman
>>> $articles = \MyBlog\Article::all();
=> <Illuminate\Database\Eloquent\Collection #00000000104d1a7300000001133ee921> {}
>>> $article = new \MyBlog\Article();
=> <MyBlog\Article #00000000104d1a7200000001133ee921> {
       incrementing: true,
       timestamps: true,
       exists: false,
       snakeAttributes: true,
       manyMethods: [
           "belongsToMany",
           "morphToMany",
           "morphedByMany"
       ]
   }
>>> $article->title = 'test';
=> "test"
>>> $article->body = 'test test';
=> "test test"
>>> $article->save();
=> true
>>> $articles = \MyBlog\Article::all();
=> <Illuminate\Database\Eloquent\Collection #00000000104d1a7000000001133ee921> {}
>>> $articles = \MyBlog\Article::all()[0];
=> <MyBlog\Article #00000000104d1a7800000001133ee921> {
       incrementing: true,
       timestamps: true,
       exists: true,
       snakeAttributes: true,
       manyMethods: [
           "belongsToMany",
           "morphToMany",
           "morphedByMany"
       ]
   }
>>> $articles = \MyBlog\Article::all()[0]->title;
=> "test"
>>> $articles = \MyBlog\Article::all()[0]->body;
=> "test test"
>>> \MyBlog\Article::all()[0]->delete();
=> true
>>>

画面に出してみる。

// app/Http/Controllers/ArticleController.php

     /**
      * Display a listing of the resource.
      *
      * @return Response
      */
     public function getIndex()
     {
        $articles = \MyBlog\Article::all();
        return view('article.index', ['articles'=>$articles]);
     }

     /**
      * Show the form for creating a new resource.
      *
      * @return Response
      */
     public function getCreate()
     {
        $article = new \MyBlog\Article();
        $article->title = 'test';
        $article->body = 'test test';
        $article->save();

        return redirect('article/index');
     }
<!— resources/views/article/index.blade.php —>
@extends('app')

@section('content')

@foreach ($articles as $article)
<section>
    <h3>{{ $article->title }}</h3>
    <p>{{ $article->body }}</p>
</section>
@endforeach

@endsection

これで/article/createを叩くと、延々とデータが増えるのを観察することができる。