localdisk

PHP とか Java とか Web とか好きなことを書きます。

他のフレームワークでも使える Laravel-Elixir

今日の記事は www.adventar.org のフライングです。12/2 分になります。

rails-assets サポート終了?

先日 Rails 界隈このような話題がTLを賑やかせていました。 github.com

僕自身はPHPerなので横目で見ていたのですが「Laravel-Elixir便利なので、他のフレームワーク使いの人にもおすすめしたいなぁ」と思いたち、来月の Advent Calendar をフライングしている次第。

Laravel-Elixir とは

gulp のタスク群を使いやすくまとめたものと思ってくださって結構です。Laravel という PHP フレームワークの1ツールとして作られているので初期設定はLaravelに最適化されていますが、変更可能(後述)なのでRailsや他のフレームワークにも適用できると思います。

Laravel-Elixir で何ができるのか?

いわゆる asset 管理と言われるものはたいていできます。

欲しいものは大体揃ってるんじゃないかなと思います。あとはテスト支援としてテストファイルを監視して

の実行が可能です。

Laravel-Elixir のインストール

インストールする前に Node.js と Gulp のインストールを済ませておいてください。PHP は必要ないです。

僕は以下の環境で動かしています

$ node -v
v5.1.0
$ npm -v
3.3.12

多分 node のバージョンは ver.4 でも動くと思います。

以下のような package.json を用意してください。

{
  "private": true,
  "devDependencies": {
    "gulp": "^3.8.8"
  },
  "dependencies": {
    "laravel-elixir": "^3.0.0"
  }
}

で、

$ npm install

ちょっと時間がかかる(5分程度)ので作業の合間にやっておくのがおすすめです。

ディレクトリ構成

ディレクトリ構成はこんな感じ。ディレクトリはだいたい変更可能。

project
 ├── gulpfile.js   // Laravel-Elixir でやりたいことを書く
 ├── node_modules  // いろいろはいってる
 ├── package.json   
 ├── public
 │   ├── build  // バージョン指定した場合の出力先
 │        ├── css
 │        └── js
 │   ├── css   // CSS の出力先
 │   └── js    // JavaScript の出力先
 ├── resources
     └── assets
         ├── coffee  // CoffeeScript 書くところ
         ├── css     // CSS 書くところ
         └── js      // Javascript 書くところ
         ├── less    // LESS 書くところ
         ├── sass    // Sass 書くところ

使ってみる

では、使ってみましょう。まず resources/assets/sassapp.scss というファイルを作って CSS を書きます。それから gulpfile.js

var elixir = require('laravel-elixir');

elixir(function(mix) {
    mix.sass('app.scss');
});

と書いて gulp コマンドを打つと…

➜  laravel-elixir  gulp
[20:24:46] Using gulpfile ~/Projects/laravel-elixir/gulpfile.js
[20:24:46] Starting 'default'...
[20:24:46] Starting 'sass'...

Fetching Sass Source Files...
   - resources/assets/sass/app.scss


Saving To...
   - public/css/app.css

[20:24:46] Finished 'default' after 344 ms
[20:24:47] gulp-notify: [Laravel Elixir] Sass Compiled!
[20:24:47] Finished 'sass' after 474 ms

簡単ですね。ちなみに gulp watch しておくと、ファイル監視してくれるので保存されるタイミングでコンパイルが走ります。便利。Minify したい場合は gulp --production とすれば Minify されます。デプロイする際はこのオプションを付けておきたいですね。

バージョン(フィンガープリンティング)

あとはバージョンについて触れてみます。先ほどの gulpfile.js を以下のように編集してみましょう。

var elixir = require('laravel-elixir');

elixir(function(mix) {
    mix.sass('app.scss')
       .version('css/app.css'); // ここを追加
});

すると…

➜ laravel-elixir  gulp
[20:35:20] Using gulpfile ~/NetBeansProjects/laravel-elixir/gulpfile.js
[20:35:20] Starting 'default'...
[20:35:20] Starting 'sass'...

Fetching Sass Source Files...
   - resources/assets/sass/app.scss


Saving To...
   - public/css/app.css

[20:35:20] Finished 'default' after 340 ms
[20:35:20] gulp-notify: [Laravel Elixir] Sass Compiled!
[20:35:20] Finished 'sass' after 474 ms
[20:35:20] Starting 'version'...

Fetching Version Source Files...
   - public/css/app.css


Saving To...
   - public/build

[20:35:20] Finished 'version' after 52 ms

version というタスクが実行されました。この結果 public/build/cssapp-6ac487d735.css というファイルが出力されます。app- から先の乱数の部分は実行するたびに変化します。で、ここからが肝ですが version タスク実行時、public/buildrev-manifest.json というファイルが出力されます。このファイルを見てみると…

{
  "css/app.css": "css/app-6ac487d735.css"
}

となっています。このファイルを読み込んで HTMLlink 要素や script 要素を書けばよいわけですね。PHPの人は Illuminate/Foundation/helpers.phpelixir 関数をパクっちゃえばおk。他の言語の人はヘルパーメソッドを作ればいけるはずです。

<?php
if (! function_exists('elixir')) {
    /**
     * Get the path to a versioned Elixir file.
     *
     * @param  string  $file
     * @return string
     *
     * @throws \InvalidArgumentException
     */
    function elixir($file)
    {
        static $manifest = null;

        if (is_null($manifest)) {
            $manifest = json_decode(file_get_contents(public_path('build/rev-manifest.json')), true);
        }

        if (isset($manifest[$file])) {
            return '/build/'.$manifest[$file];
        }

        throw new InvalidArgumentException("File {$file} not defined in asset manifest.");
    }
}

framework/helpers.php at 5.1 · laravel/framework · GitHub

設定の変更

他のフレームワークを使っている人はこのディレクトリ構成がきっと合わないと思います。Laravel-Elixir はディレクトリの設定を設定ファイルに外出ししてるので自由に変更することができます。設定値は node_modules/laravel-elixir/Config.js にあります。この設定を gulpfile.js で上書きしてやると良い感じになります。とりあえずディレクトリ周りだけ、抜き出しておきます。

設定 初期値
elixir.config.assetsPath resources/assets
elixir.config.publicPath public
elixir.config.appPath app
elixir.config.css.folder css
elixir.config.css.outputFolder css
elixir.config.sass.folder sass
elixir.config.less.folder less
elixir.config.js.folder js
elixir.config.js.outputFolder js
elixir.config.coffee.folder coffee
elixir.config.versioning.buildFolder build

多分ですが、Rails だとこんな感じ?(全然自信ない)

var elixir = require('laravel-elixir');

// 設定値を上書き
elixir.config.assetsPath = 'app/assets/';
elixir.config.js.folder  = 'javascripts'

elixir(function(mix) {
    mix.sass('app.scss')
       .babel('app.js');
});

最後に

いかがでしたでしょうか? 僕が好んで使っている Laravel-Elixir の魅力が他の人に少しでも伝われば幸いです。他の機能は Laravel Elixir 5.1 Laravel を見てください。いろいろできますよ。メソッドチェインでさらさら書けるのはやはりよいものです。

最後に自分が使ってる gulpfile.js を例に出しておきます。

var elixir = require('laravel-elixir');

elixir(function(mix) {
    mix.sass('app.scss')
        .browserify('app.js')
        .copy(
        'node_modules/font-awesome/fonts',
        'public/build/fonts'
        ).version(['css/app.css', 'js/app.js']);
        .browserSync({proxy: 'works.dev'});
});

こんな感じ。やってることを軽く説明すると

  • resources/assets/sass/app.scss を sass コンパイル
  • resources/assets/js/app.js を browserify. この時 babelifypartialify も走ってるっぽい
  • font-awesome の font ファイル一式を public/build/fonts にコピー
  • public/css/app.csspublic/js/app.js をバージョン化
  • 最後に BrowserSync*1

参考

宣伝

年明けに Laravel の本が出ます。LTS である 5.1 を対象にして書いています。とても良い本に仕上がってると思います。よろしくお願いします。

www.amazon.co.jp

で、この本の出版記念というか販促も兼ねてと言うか 12/2 19:30 から Fukuoka.php Vol.16 で喋らせて頂きます。内容としては、出版間近の本の内容とリリース間近っぽい 5.2 の新機能の解説をします。こちらもよろしくお願いします

*1:実は最近使ってなかったり…。待ちきれずF5押してしまう

Lumen の設定を上書きする方法

こういう時は .env を…。あれ…ない。では、config ディレクトリ…ない。

まぁ答えは Configuration にあります。Lumen の設定はデフォルトでは vendor/laravel/lumen-framework/config にあります。今回の場合は database.php ですね。大体の場合は .env に書けばいいのですが*1今回の例のように .env では上書きが不可能なときはプロジェクトのルートに config ディレクトリを作成し vendor/laravel/lumen-framework/config/database.php をコピーして変更したい部分を修正すれば OK です。

以上 Laravel(Lumenも) 答えるマンでした。Laravel 答えるマンは Laravel/Lumen に関する質問を随時お待ちしております。

*1:bootstrap/app.php の Dotenv::load(DIR.'/../'); のコメントを外すのを忘れないように。僕はしょっちゅう忘れてます。てかこれはデフォルトで外れててほしい。

Laravel 本がでますよ

明けましておめでとうございます。今年もよろしくお願いします。

…半年くらいブログ書いてないんですね。どうなってるんだ。

それはともかくとして、今年はじめから一生懸命書いていた Laravel 本が 4/21 に出版されます!

Laravelエキスパート養成読本[モダンな開発を実現するPHPフレームワーク!] (Software Design plus)

Laravelエキスパート養成読本[モダンな開発を実現するPHPフレームワーク!] (Software Design plus)

Laravel エキスパート養成読本というタイトルですが、対象者は初〜中級者でしょうか。怖くないので買ってください。

目次はこんな感じです。

Chapter1. Laravel をはじめよう
Chapter2. MVC モデルが基礎からわかる
Chapter3. IoC コンテナ、ファサード、サービスプロバイダ、Eloquent
Chapter4. Laravel 5 新機能紹介!
Special. PHP フレームワーク最新事情
Chapter5. 実践!REST API アプリケーション

僕は、Chapter3 を担当しました。Laravel を始めた人がハマりがちであったりピンと来ない箇所である IoCコンテナ*1やサービスプロバイダ、ファサードについてと Eloquent について解説させていただきました。

本を書くのは初めてだったのですが、ブログ書くのと違って本書くのは大変だなぁと思いました。楽しかったのですが、仕事が忙しかったのもあってヒィヒィいってました。編集を担当して下さった @ghtakaya さんにはご迷惑をお掛けしました…。

内容としては Laravel4 を中心に Laravel 5 での変更点を付記してあるという感じです。

Laravel 5 については Chapter4 で一章割いているのでそちらでキャッチアップできるかと思います。@ex_takezawa さん担当なのでバッチリだと思います。

とうわけでよろしくお願いします。予約も始まってますよ!あと、電子書籍も出るみたいです。

追記(2015/04/30)

正誤表が出来ました。こちらのレビューが甘くて申し訳ないです…。

あと電子版も発売されました!まだの方はぜひ!

Laravelエキスパート養成読本[モダンな開発を実現するPHPフレームワーク!]:書籍案内|技術評論社

*1:Laravel5 からサービスコンテナに名前が変わりました

Fukuoka.php Vol.14 で喋ってきました

ブログを書くまでが勉強会です。

当日喋ったスライドはこちら。

今年のPHPカンファレンスですが、福岡から参加した人はあまり多くなかったようで、こんな話があってめっちゃ楽しかったよ!というと、PHPはどんどん進化してるので未来は明るいし、僕らも継続して学んでいくことで、もっとうまくPHPを扱えるようになろう!のが少しでも伝わればよいなぁと。

で、こっちが PHP5.6 の話。地味だけどなかなかよい改善がされてます。で、PHP5.6 では実務的にどういった変化が起こるのか?という視点でお話させていただきました。スライドにも書いてますが、定数でスカラー式が扱えること、定数/関数で名前空間を扱えること。可変長引数の登場で3つの関数がオワコンになるんじゃないの?と。

  • define
  • func_get_args
  • function_exists

ですね。

他の方の発表の感想

これからのCMSマーケットトレンドとPHP by @ takufujita

これからのCMSマーケットトレンドとPHP (for fukuoka.php)

"エンプラCMS" というのを初めて知ってあまりの高機能っぷりにびっくりした。テンプレートの管理やテンプレートのブロックもバージョンを持てるようになってたり、マーケティング的な機能も入ってたりしてる。
僕最近 CMS に興味持てなくなってて、あまりウォッチしてなかったんですが、エンプラCMSに俄然興味が沸いてきました。弄りがいがありそう。

自己紹介 by @murasakipinko



多分 JS Girls 的なアレだと思います。楽しみですね!

PHP の H はどこへ向かうのか by @msng

ノーズライドで流れるようなトーク。僕もトーク力を高めればならない。話自体はWebサービスとHypertextの話でした。Webサービスの最近のトレンドにまつわるアレコレ。僕 @msng さんが 天一botの作者だと知らなかった。

LT

@cakephper

VAddy の Jenkins プラグイン作ったよというのとmoment.jsが便利という話

@udzura


php-mruby のごしょうかい // Speaker Deck

SOAやMicroServicesのつなぎの部分でmrubyを使う話。これ聞きながら
(´-`).。oO( ペパボのサービス、Ruby or PHP なのでつなぎはJVMでいいような…JRubyやQuercusあるし…) と思いました。 見当違いな発言っぽいので削除しました。

懇親会

AM4時までありました。非常に愉快でした。

参考リンク

  • @udzuraさんの感想
    • 自分が尊敬してる人のブログに名前が載るとニヤニヤしちゃいます。

PHP カンファレンス 2014 に行ってきました

10/11 に行われた PHPカンファレンス2014 に行ってきました。

僕は打ち合わせがあったので前日入りして、夜は Laravel 好きの皆さんと飲み会しました。


参加メンバー

  • @kurikazu
    • 幹事あざっした!オサレなお店でデートで来たらいいだろうなーと思いました。
    • 飲んだお店。炙屋小鉄
    • あと優先LANアダプタ貸していただいてありがとうございます!
  • @syossan27
    • 飲み会中に彼女持ちということが発覚。たっぷり悪態をつきました。
  • @ex_takezawa
    • Yahoo!JAPAN への転職おめでとうございます。
  • @blue_goheimochi
    • 障害対応で来れなかった人
    • PHP カンファレンスには徹夜明けで来てた
    • ほんとおつかれさまでした…ご挨拶できて良かったです

ここからPHPカンファレンス本番。二日酔い気味でしたがちゃんと基調講演から聞きました。
では、セッション等の感想をば。

基調講演

PHPカンファレンス皆勤のひろかわさん。

  • PHP 5.6 は地道な改善が行われた
  • HHVM の登場
  • PHP 7

PHPコアから読み解くPHP5.5

  • Yahoo! JAPAN のこもいけさん
    • あとのセッションに PHPにおけるI/O多重化とyield というのがあって、これも Yahoo! JAPAN@hiraku さんの発表。Yahoo! JAPAN では空前の yield ブームが来ているのかもしれない
  • zend_execute からのくだりは「なるほど、わからん」としか言いようがなかった。こもいけさんがどうこうではなく、僕の理解力の問題です。

ブースを見て回ったよ

2コマほど集中力全開で聞いてたら頭が沸騰してきたのでブースをみてまわることに。色々みてまわりました。


ツイートしたらタオルあげる!と言われたので律儀にツイートしてます。
印象に残ってるブースを3 + 1 .

Unity ブース

Oculus Rift と連動させてて、ちょう空いてたので見せてもらいました。すげぇ…俺、もう、2次元に住んじゃうよ…と思った。

EC Cube ブース

高橋さんとお話させていただいた。どうも EC Cube はリライトする予定らしいです。色々計画している模様。楽しみです。Laravel をベースにしたら全力でコントリビュートする所存。

BASE ブース

(生えふしんだ!生えふしんだ!)ってなってた。
BASE Developersを作ったというのとBASE SECURITY CHALLENGEとのこと。

アシアルブース

誰もいなかった…@anatooさんに挨拶したかったのと Monaca について聞いてみたかった。残念
あとはteratail【テラテイル】|思考するエンジニアのためのQAプラットフォームを運営しているレバレジーズのブースなどにお邪魔しました。Laravel の質問に答えてるのは僕ですと自己紹介しました。

PHPにおけるI/O多重化とyield

ここからセッションに復帰。またもや yield の話。

今まであんまり積極的に使おうと思ってなかった generator ですが、このセッション聞いて俄然興味が湧いてきました。が、なかなか難しいのでhirak/co-httpclient · GitHubを読んで勉強したい所存。

HHVM + Hack == PHP++

本日のメインイベント。発表者の Paul さんも素晴らしかったし、翻訳した方も同じくらい素晴らしかった。HPHPc があえなく死んでしまった…という話でぐっと観衆の心を掴んでそこからはもう怒涛の如くという感じ。ちょっとまだ個人的に興奮が収まってなくてうまく言語化できないのでPHPカンファレンス2014でHHVM/Hackの話を聞いて感動した - As a Futurist...を参考にしてください。
途中からですが、Ustream で動画も見れるみたいです。
Ustream.tv: ユーザー phpstudy: phpcon2014-main, phpcon2014-main. コンピュータ
「日本では CentOS が人気なんだけど HHVM はバイナリを提供する予定はあるか?」という質問に「CentOS はつらい」回答しているところがもうたまりませんでした。

LT CMS/DB

途中までなんかフラフラしてました。まともに聞いたのは「LT CMS/DB PHP&NewSQL;で考える次世代アプリケーション」で夢あふれるセッション。フィットしそうな案件があったら試してみたい。

LT無差別級

どれも素晴らしいLTでした。残念なのが5分で収まらないものが多く「最後まで聞かせてくれ!頼むから!」という感じなのでした。ドラは無慈悲だ。

懇親会 + LT

LT 募集ということなので、Laravel5 のことを喋らせて頂いた。が、時間が足りず言いたいことが半分も言えず非常に残念。@ex_takezawa がネット環境を貸してくれて助かりました。ありがとうございます!
懇親会では @uzulla さんにお会いできたのが嬉しかった。色々とお話できました。にしし。@tanakahisateruガンダムLTが素晴らしかった。あと、何故か司会をしてた @shin1x1@msngお疲れ様でした。

打ち上げ

懇親会が終わった後は関西勢と一緒にレバー食べたり中華食べたりお酒飲んだりしました。途中から@yohgakiさんともご一緒させていただきました。楽しかったなー。

まとめ

いやぁ、この2日間はリア充といっても過言ではない!というかこの2日間びっくりするくらい楽しかったので来てよかったとおもいました。次回は 2015/10/3 とのことで今から楽しみです。PHPカンファレンススタッフに感謝感謝、そして僕の話し相手になってくれた方にも感謝。
ではまた来年!!

PHPカンファレンス行ってきます

今週土曜日 (10/11) に PHPカンファレンス2014 が開催されます。実のところ初参加でして、楽しみ半分不安半分といったところです。
"ぼっちになっても泣かない" を目標に楽しみたい所存です。

当日見ようと思っているプログラムはこちら。

基調講演
基本。
PHPコアから読み解くPHP5.5
面白そう。PHP5.6の話もあるといいなー。
フリマアプリ「メルカリ」の超高速開発を支える PHP
ここは迷ってて、もしかしたら「mysqlnd 徹底解説」に行くかも。
PHPにおけるI/O多重化とyield
もしかしたらお昼ごはん食べてるかもしれません。
HHVM + Hack == PHP++
通訳ありなのが助かります。一番楽しみにしてるセッション。2番めに楽しみな「Good Parts of PHP and The UNIX Philosophy」が聞けないのが残念…。
休憩
14:50 - 15:20は特にこれはというものはなし。「PHP&NewSQLで考える次世代アプリケーション」だけ気になってるのでこれだけは聞く予定。
LT
楽しみにしてるのは、「PHPでAIプログラミングコンテスト準優勝するまでの軌跡」と「良いことも悪いこともぜんぶPHPが教えてくれた」と「PHPNGの現状を知る」と「中年以降エンジニアの成長戦略

以上。楽しみだ!

Laravel 5 はこう変わる! メソッドインジェクションとFormRequest編

注意!

このエントリは 2014/09/30 時点の情報です。これからどんどん変わっていく可能性があるので鵜呑みはダメ、絶対。

はじめに

11月にリリースされる Laravel5 の変更点を説明していきます。前回は

Laravel4 では存在しなかった FormRequestメソッドインジェクションについて説明します。個人的には一番の目玉です。

メソッドインジェクション

Laravel4 にもあった Ioc コンテナは今までコンスタラクタインジェクションしかできませんでした。

<?php

class HomeController extends Controller 
{
    /**
     * User 
     * 
     * @var \App\User
     */
    private $user;

    /**
      * コンストラクタインジェクション
      */
    public function __construct(User $user)
    {
        $this->user = $user;
    }
}

Laravel5 ではメソッドインジェクションが可能になったのでこうかけるようになりました。

<?php

class HomeController extends Controller 
{
    public function index(User $user)
    {
        // インジェクションされてる!
        dd($user);
    }

これは嬉しい変更ですね。助かります。

FormRequest

さて、メソッドインジェクションを踏まえて FormRequest の説明をします。FormRequest は既存の Request クラス(Laravel4 でいうところの Input + Request クラス)にValidationと認証機能(?)を足したものです。

まずは作ってみましょう。

php artisan make:request App\\Http\\Requests\\HomeRequest

ポイントは名前空間\\ で区切ってやるのがポイントです。ここらへん以前は(3日前くらい)は名前空間を付ける必要がなかったのですが、現時点では必要です。もしかしたらいらなくなるかもしれません(Laracasts を収録した段階では必要なかった模様)。すると app/Http/Requests にこんな感じのファイルが出来上がります。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class HomeRequest extends FormRequest
{

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
                //
        ];
    }

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return false;
    }

}

rules メソッドauthorize が実装されています。rules は Validaiton ルールを書く場所です。

<?php
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name'     => 'required',
            'email'    => 'required|email',
            'password' => 'required|min:8',
        ];
    }

こんな感じに書いて…コントローラーにインジェクションすると、Validation が自動に実行されます。Validation がうまく行かなかった時はデフォルトで前画面に戻ります。挙動を変えたい場合は FormRequestredirect フィールドを定義してください。細かい挙動は Illuminate\Foundation\Http\FormRequest#getRedirectUrl を参照してください

<?php
    public function store(HomeRequest $request)
    {
        dd($request->all());
    }

今までは Controller に書いたり Ardent のように Eloquentメソッドをオーバーライドして Model 側で Validation を実行させたりしていましたが、この変更で決着をみたんじゃないかと思います。

Validaitonの必要がない場合は \Illuminate\Http\Request をインジェクションするのもありですね。

<?php
    public function store(Illuminate\Http\Request $request)
    {
        dd($request->all());
    }

でも、これルートパラメータと相性悪いかもしれませんね。調査しきれていないので解決方法があるかもしれませんが。


で次の、authorize メソッドなんですが、これイマイチどう使えばいいかわかってません。 認証されたかどうかのチェックなら AuthFilter 使えばいいしなぁ…。一応説明するとこのメソッドfalse を返すと 403 が返却されます。 true を返すと次の処理へ進みます。forbiddenResponse をオーバーライドすることで挙動を変えることができます。

終わりに

ちょっと長めになりましたが、Validation の手間が大幅に軽減されたのは嬉しい限りです。リリースが楽しみですね。
次回は新たに追加された ServiceProvider の話か、route:cache の話をしたいと思います。

Laravel 5 はこう変わる! ディレクトリ構造編

注意!

このエントリは 2014/09/30 時点の情報です。これからどんどん変わっていく可能性があるので鵜呑みはダメ、絶対。

はじめに

Laravel 5 は現在絶賛開発中で現行の 4.2.9 と比較するとかなり大きく変更されます。11月にリリース予定ですが、その前に先取りして主な変更点を何回かにわけてブログに書き残しておこうと思います。

一応 PHP カンファレンスが始まる前には書き終わりたいと思っていますが、我慢できない人は What's New in Laravel 5.0 のスクリーンキャストを見るとよくわかります。

Laravel5 のインストール

Composer でインストールできます。

composer create-project laravel/laravel forder-name dev-develop

ディレクトリ構造

かなり変わりました。軽く解説していきます。tree 構造はこちら。

root.
├── app
│   ├── Console
│   ├── Http
│   │   ├── Controllers
│   │   ├── Filters
│   │   └── Requests
│   └── Providers
├── bootstrap
├── config
│   ├── local
│   ├── packages
│   └── testing
├── database
│   ├── migrations
│   └── seeds
├── public
│   └── packages
├── resources
│   ├── lang
│   │   └── en
│   └── views
│       └── emails
│           └── auth
├── storage
│   ├── cache
│   ├── logs
│   ├── meta
│   ├── sessions
│   ├── views
│   └── work
├── tests
└── vendor

Laravel4 との対比はこんな感じ。

Laravel4 Laravel5
app/commands app/Console
app/config config
app/controllers app/Http/Controllers
app/database database
app/lang resources/lang
app/models app
app/start ない
app/storage storage
app/tests tests
app/views resources/virews
app/filters.php 廃止(app/Providers/FilterServiceProviderに定義)
app/routes.php app/Http/routes.php
bootstrap bootstrap
public public


大きな変更点として app 周りがガラッと変わっています。これ、ディレクトリ構造だけではなくて Laravel4 では 自作するController/Model/Command名前空間の修飾を必要としませんでしたが*1 Laravel5 からは名前空間は必須となります。手数が増えるかわりに自由度が上がった感じでしょうか。個人的には歓迎しています。

個人的には Modelapp の下にあるのがもにょりますが、自由に変更できるので、まぁいいかと。

ちょっとした注意点

  • sqlite ファイルが変更になりました。
Laravel4 Laravel5
app/database/production.sqlite storage/database.sqlite(ファイルはないので作る必要があります)
  • global.php はなくなりました。
    • 次回説明しますが、ServiceProvider が全面にでてきたのであんまり困らないと思います。

次回は、ServiceProvider と FormRequest の話を書きます。

*1:composer.json の classmap

Laravel で xhprof を手軽につかう

f:id:localdisk:20140911161541p:plain


「推測するな。計測せよ」

と偉い人が言っていました。先人に倣って僕も頑張ろうと思います。…というのも自分が今作ってるアプリが特定の条件で極端に遅くなるという現象に遭遇したからですが。

というわけで Facebook 謹製*1 の xhprof を使ってみることにします。後継と言われている uprofiler はまだ HomeBrew ではインストールできなかったので。

PHP と xhprof のインストール

brew install php55 php55-mcrypt php55-xhprof

簡単ですね。mcrypt 入れてるのは Laravel で必要だからです。

xhprof_html/xhprof_lib を任意の場所にコピーする

mkdir $HOME/.xhprof
cp /usr/local/Cellar/php55-xhprof/{なんかユニークな文字列が入る}/xhprof_html $HOME/.xhprof/xhprof_html
cp /usr/local/Cellar/php55-xhprof/{なんかユニークな文字列が入る}/xhprof_lib $HOME/.xhprof/xhprof_lib

Laravel のコードに xhprof を仕込む

アプリケーションイベントを使うのが簡単でよいです。

<?php
// app/start/global.php
App::before(function()
{
    // xhprof を有効にする
    xhprof_enable(XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);
});
// shutdown
App::shutdown(function()
{
    // 計測する
    $xhprof_data = xhprof_disable();
    $XHPROF_ROOT = '/Users/localdisk/.xhprof';
    $APP_NAME = 'app_name';
    require_once $XHPROF_ROOT . '/xhprof_lib/utils/xhprof_lib.php';
    require_once $XHPROF_ROOT . '/xhprof_lib/utils/xhprof_runs.php';
    $xhprof_runs = new XHProfRuns_Default();
    $run_id = $xhprof_runs->save_run($xhprof_data, $APP_NAME);
    // ログに xhprof 用の URL が出力されます
    Log::debug("http://localhost:8001/index.php?run={$run_id}&source={$APP_NAME}");
});

今回はタイトルにあるように手軽さを重視していますが、Laravel 的には Middleware を作って ServiceProvider に登録するのがよいと思います。設定も思いのままですし、アプリケーションのコードを修正する必要がなくなります。

あとは $HOME/.xhprof/xhprof_html をルートにしてPHPのビルトインサーバーを起動させておき、app/storage/logs/laravel.log に出力された URL にアクセスすればOKです。

最後に宣伝

明日 InnoCafe 開発コミュニティサミット in 福岡 - イノベーター・ジャパン | Doorkeeper という集まりがあります。東京と福岡のコミュニティについて面白い話が聞けるのでよかったら遊びに来てください。
翌日である 9/13 は ヌーラボさんのオフィスをお借りしてもくもく会をします。こちらもきっと楽しいと思いますのでよかったらどうぞ。

*1:だと思ってたけど違う人がメンテしてる?

CakePHPer のための Laravel 入門 - ブログチュートリアル2

CakePHPer のための Laravel 入門 - ブログチュートリアル1 - localdiskの続きです。

Postコントローラの作成

cake-to-laravel/app/controllers に 投稿記事(posts)に対するコントローラを作成します。

<?php
class PostController extends BaseController
{
    
}

全てのコントローラーは BaseController クラスを拡張する必要があります*1。では、一つメソッドを作って呼び出してみましょう。

<?php
class PostController extends BaseController
{
    public function getIndex()
    {
        // URL を echo する
        echo Request::url();
    }

}

コントローラを呼び出すのにはルートの定義が必要です。cake-to-laravel/app/routes.phpを以下のように編集します。

<?php
// コントローラを登録
Route::controller('posts', 'PostController');

では、http://localhost:8000/posts/indexをブラウザでアクセスしてみましょう。アクセスした URL が表示されるはずです。

次は前回作成したモデルを表示させてみましょう。コントローラを以下のように編集します。

<?php
class PostController extends BaseController
{
    public function getIndex()
    {
        return View::make('posts.index', ['posts' => Post::all()]);
    }

}

Post ビューの作成

Post モデルの内容を表示するシンプルなビューを作りましょう。ビューの設置場所は cake-to-laravel/app/views になります。今回はそこに posts というフォルダを作ってその中に index.php というファイルを作りましょう。

<h1>Blog posts</h1>
<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Created</th>
    </tr>
    <!-- ここから、$posts配列をループして、投稿記事の情報を表示 -->
    <?php foreach ($posts as $post): ?>
    <tr>
            <td><?php echo $post->id; ?></td>
            <td>
                <!-- link_to_action を使うと定義されていなければエラーになる -->
                <?php echo link_to("posts/view/{$post->id}", $post->title) ?>
            </td>
            <td><?php echo $post->created_at ?></td>
        </tr>
    <?php endforeach; ?>
</table>

シンプルですよね。煩わしい配列がないところが特に。
ビューの中のリンク(投稿記事のタイトルから/posts/view/some_idというURLへのリンク)をクリックすると、Laravelは、そのアクションはまだ定義されていません、エラー画面を表示します。*2
では、エラーを撲滅するべく表示用のメソッドを実装しましょう。

<?php
class PostController extends BaseController
{
    public function getIndex()
    {
        return View::make('posts.index', ['posts' => Post::all()]);
    }
    
    public function getView($id)
    {
        // この状態だと $id が URL に付加されてない場合は ErrorException が発生する
        // $id あってもなくてもよい場合は getView($id = null) とすればよい
        // Model::findOrFail を使うとモデルが見つからなかった場合
        // ModelNotFoundException を発生させる
        return View::make('posts.view', Post::findOrFail($id));
    }
}

記事の追加

続きはあとで。

*1:実際は Controller クラスを継承していればよい

*2:NotFoundHttpExceptionが発生します