localdisk

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

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が発生します

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

CakePHPer のための Laravel 入門 - インストール - localdisk の続き。

さて、前回はインストール、環境の設定(localに設定しました)、拡張のインストールを行いました。今回はメインである CakePHP のブログチュートリアルを Laravel で実装してみましょう。

データベースの設定

まずは、cake-to-laravel/app/config/local/database.php を設定しましょう。前回触れましたが、Laravel は環境ごとの設定を容易に作成することができます。今回は local 環境のデータベースを SQLite を使用する設定を行います。たった一行追加するだけです。

<?php

return array(
    'default'     => 'sqlite', // <- ここを追加!
    'connections' => array(
        'mysql' => array(
            'driver'    => 'mysql',
            'host'      => 'localhost',
            'database'  => 'homestead',
            'username'  => 'homestead',
            'password'  => 'secret',
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
        ),
        'pgsql' => array(
            'driver'   => 'pgsql',
            'host'     => 'localhost',
            'database' => 'homestead',
            'username' => 'homestead',
            'password' => 'secret',
            'charset'  => 'utf8',
            'prefix'   => '',
            'schema'   => 'public',
        ),
    ),
);

これで local 環境は、SQLite を使用することになります。

マイグレーション

Laravel では、データベースのスキーマコントロールにマイグレーションを使用します。CakePHP でも同様のことができますがプラグインが必要です。まずはマイグレーションを使用できるようにするために以下のコマンドをターミナルから実行してください。

$ php artisan migrate:install

コマンドを実行したあと、以下のように表示されれば成功です。

Migration table created successfully.

テーブルの作成

マイグレーションの設定ができたら posts テーブルを作成しましょう。ターミナルで以下のコマンドを実行してください。

$ php artisan generate:migration create_posts_table

コマンド実行すると以下のように表示されます。

Created: /Users/localdisk/NetBeansProjects/cake-to-laravel/app/database/migrations/2014_08_03_061640_create_posts_table.php
Generating optimized class loader 

はい、作成できましたね。ではこのファイルを覗いてみましょう。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreatePostsTable extends Migration
{

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function(Blueprint $table)
        {
            $table->increments('id');
            $table->timestamps();
        });
    }

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

}

ちゃんと出来ていますね。では、 up メソッドを修正しましょう。2行追加するだけです。

<?php
class CreatePostsTable extends Migration
{

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('title', 50); // 追加
            $table->text('body'); //  追加
            $table->timestamps();
        });
    }
}

修正したら、以下のコマンドを実行して posts テーブルを作成します。

$ php artisan migrate

コマンド実行すると以下のように表示されます。

Migrated: 2014_08_03_061640_create_posts_table

はい、これでテーブルができました。次はモデルを作成しましょう。

Post テーブルの作成

posts テーブルと対になる Post モデルを作成します。ターミナルで以下のコマンドを実行してください。

$ php artisan generate:model Post 

コマンド実行すると以下のように表示されます。

Migrated: 2014_08_03_061640_create_posts_table

これで Post モデルが作成されました。

<?php

class Post extends \Eloquent {
	protected $fillable = [];
}

シード

作成した posts テーブルに表示用の初期値を設定します。

$  php artisan generate:seed posts 

コマンド実行すると以下のように表示されます。

Created: /Users/localdisk/NetBeansProjects/cake-to-laravel/app/database/seeds/PostsTableSeeder.php  

これで PostsTableSeeder.php が作成されました。では、内容を確認してみましょう。

<?php

// Composer: "fzaninotto/faker": "v1.4.0"
use Faker\Factory as Faker;

class PostsTableSeeder extends Seeder
{

    public function run()
    {
        $faker = Faker::create();

        foreach (range(1, 10) as $index) {
            Post::create([
            ]);
        }
    }

}

生成されたファイルには Faker の記述がありますが、今回は使用しません。結構便利なライブラリなので、興味があるならぜひ使用してみてください。
では、ブログチュートリアルにそってデータを作成していきましょう。

<?php

class PostsTableSeeder extends Seeder
{

    public function run()
    {
        Post::create([
            'title' => 'タイトル',
            'body'  => 'これは、記事の本文です。'
        ]);
        Post::create([
            'title' => 'またタイトル',
            'body'  => 'そこに本文が続きます。'
        ]);
        Post::create([
            'title' => 'タイトルの逆襲',
            'body'  => 'こりゃ本当にわくわくする!うそ。'
        ]);
    }

}

そして DatabaseSeeder.php を以下のように修正します。

<?php

class DatabaseSeeder extends Seeder
{

    /**
     * データベースシード(初期値設定)を実行
     *
     * @return void
     */
    public function run()
    {
        Eloquent::unguard();
        // PostTableSeeder を実行する

        $this->call('PostsTableSeeder');
    }

}

では、db:seed コマンドを実行して初期値をテーブルに設定しましょう。

$ php artisan db:seed

コマンド実行すると以下のように表示されます。

Seeded: PostsTableSeeder

これでデータベースに初期値が設定されました。

続く!

CakePHPer のための Laravel 入門 - インストール

CakePHP のブログチュートリアルを Laravel で実装してみました。手順をなるだけ詳細に説明します。CakePHPer で Laravel に興味を持っている人に参考になれば幸い。

Laravel のインストール

必要なもの

laravelja.phar

Laravel のインストーラー phar ファイルをダウンロードします。

  1. @HiroKwsさんの作成したインストーラー日本語版をダウンロードします
    1. laravel.phar
  2. ターミナルで以下のコマンドを実行します。
    1. $ php laravelja.phar new -l ja -s cake-to-laravel
    2. すると cake-to-laravel というディレクトリの下に Laravel がインストールされます。
    3. phar ファイルでのインストールは Composer のそれと比べて早いのと日本語化されたメッセージファイルがインストールされるのでおすすめ。
  3. インストールされた Laravel は最新版ではない(4.2.1)ので composer update します。
    1. $ composer update
    2. これで 4.2.7 にバージョンアップされます (2014/08/02 現在)
    3. 川瀬さんが対応してくれました!ブログ書いててよかった!

環境を設定する

Laravel も他のフレームワークと同じく手軽に複数の環境を扱うことができます(local / testing / staging / production) 。環境の設定は cake-to-laravel/bootstrap/start.php 内の $app->detectEnvironment で行います。デフォルトの環境は production です。環境はホスト名で決定します。 例外として* は全てに当てはまります。今回は local に設定します。cake-to-laravel/bootstrap/start.php を以下のように設定してください。

<?php
$env = $app->detectEnvironment(array(
    'production' => array('production.host'), // production のホスト名
    'staging'    => array('staging.host'),  // ステージングのホスト名
    'local'      => array('*'),  // それ以外はローカル
));

開発中は local に設定しておきましょう。

設定ファイルについて

Laravel の設定ファイルは app/config にあります。この下に環境名(今回の場合は local)の名前のついたディレクトリを作成し、オーバーライドしたい同名の設定ファイルを設置することによって、環境ごとの設定を行うことができます。

必須パッケージをインストールする

以下2つのパッケージをインストールします。

composer.json を編集

cake-to-laravel の直下の composer.json を以下のように書き換えてください。コピペでOK。

{
    "name": "laravel/laravel",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "require": {
        "laravel/framework": "4.2.*"
    },
    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php"
        ]
    },
    "require-dev": {
        "barryvdh/laravel-ide-helper": "1.*",
        "way/generators": "dev-master"
    },
    "scripts": {
        "post-install-cmd": [
            "php artisan clear-compiled",
            "php artisan optimize"
        ],
        "post-update-cmd": [
            "php artisan clear-compiled",
            "php artisan ide-helper:generate",
            "php artisan optimize"
        ],
        "post-create-project-cmd": [
            "php artisan key:generate"
        ]
    },
    "config": {
        "preferred-install": "dist"
    },
    "minimum-stability": "stable"
}

app.php を編集

cake-to-laravel/app/config/app.phpproviders の配列に以下を追加します。

<?php
return array(
    'providers'       => array(
        ・・・
        'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
        'Way\Generators\GeneratorsServiceProvider',
    ),
);

ファイルを編集したら $ composer update してください。

動作確認

では、Laravel の動作確認をしてみましょう。ターミナルで以下のコマンドを入力して下さい。

$ php artisan serve

すると

Laravel development server started on http://localhost:8000

とターミナルに表示されると思います。ブラウザから http://localhost:8000 にアクセスしてみてください。

f:id:localdisk:20140803034528p:plain

上記画面が、ブラウザに表示されれば正常に処理されています。

続く!

Laravel の unique ルールとソフトデリート

先月中旬から東京に出張行ってるんですが、通勤のストレス*1から部屋(くっそ狭いマンスリーマンション)で勉強する気力が沸かなかったのですが、1ヶ月弱経ちまして少しは回復したのでまずはブログでリハビリ。

フォーラムに投稿された質問

メールアドレスを他の人と被らないよう、バリデーションを「users,mail_address」としました。
usersテーブル自体はソフトデリートを有効にしています。 この場合、削除したユーザのメールアドレスと、新しく登録するユーザのメールアドレスが同じ場合、 バリデーションに引っ掛かって登録することができません。
どうにかソフトデリートとユニークなメールアドレスを両立させる方法はないでしょうか。

[解決済み] バリデーションで「unique」を指定した際のソフトデリートとの連携について - laravel.jp

Laravel の Validator からはモデルがソフトデリート(論理削除を簡単に実装できる機能)を使ってるかどうかわからないので unique ルールを適用したら削除したモデルがひっかかって辛いという話です。

再現するとこんな感じです。

<?php

// マイグレーションファイル(抜粋)
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('email');
            $table->softDeletes();
            $table->timestamps();
        });
    }
}
// シードファイル(抜粋)
class UserTableSeeder extends Seeder
{

    public function run()
    {
        // Model の $unguarded を true にすると楽
        // これ豆知識な
        User::unguard();
        User::create([
            'email' => 'test@example.com'
        ]);
    }

}
Route::get('unique', function()
{
    User::destory(1); // 削除した!
    $email = 'test@example.com';
    $v     = Validator::make(['email' => $email], ['email' => 'unique:users']);
    // 削除したけどバリデーションはエラー!
    var_dump($v->fails());
});

ソフトデリートの場合、削除されるとカラムの deleted_at に日付を入れるだけなので unique で発行される SQL ではダメなわけです。ちなみにこんなSQLが発行されます。

select count(*) as aggregate from "users" where "email" = ?

上記 SQL の結果が 0 の場合 unique バリデーションは通過します。

解決方法

クエリーへWHERE節として追加される条件を追加することも可能です。

<?php
'email' => 'unique:users,email_address,NULL,id,account_id,1'
v4.2:バリデーション

なのでこんな感じで書いて上げればOK.

<?php
Validator::make(['email' => $email], ['email' => 'unique:users,email,NULL,id,deleted_at,NULL']);

こうするとこんなSQLが発行されます。

select count(*) as aggregate from "users" where "email" = ? and "deleted_at" is null

where 節が付加されているのがわかりますね。

*1:なんか抜け毛が増えた気がする