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 ファイルをダウンロードします。
- @HiroKwsさんの作成したインストーラー日本語版をダウンロードします
- ターミナルで以下のコマンドを実行します。
$ php laravelja.phar new -l ja -s cake-to-laravel
- すると
cake-to-laravel
というディレクトリの下に Laravel がインストールされます。 - phar ファイルでのインストールは Composer のそれと比べて早いのと日本語化されたメッセージファイルがインストールされるのでおすすめ。
インストールされた Laravel は最新版ではない(4.2.1)ので composer update します。$ composer updateこれで 4.2.7 にバージョンアップされます (2014/08/02 現在)- 川瀬さんが対応してくれました!ブログ書いててよかった!
環境を設定する
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つのパッケージをインストールします。
- Laravel4 Generators
- Laravel IDE Helper Generator
- IDE を使っていない人は必要ありません
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.php
の providers
の配列に以下を追加します。
<?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
にアクセスしてみてください。
上記画面が、ブラウザに表示されれば正常に処理されています。
続く!
Laravel の unique ルールとソフトデリート
先月中旬から東京に出張行ってるんですが、通勤のストレス*1から部屋(くっそ狭いマンスリーマンション)で勉強する気力が沸かなかったのですが、1ヶ月弱経ちまして少しは回復したのでまずはブログでリハビリ。
フォーラムに投稿された質問
メールアドレスを他の人と被らないよう、バリデーションを「users,mail_address」としました。
[解決済み] バリデーションで「unique」を指定した際のソフトデリートとの連携について - laravel.jp
usersテーブル自体はソフトデリートを有効にしています。 この場合、削除したユーザのメールアドレスと、新しく登録するユーザのメールアドレスが同じ場合、 バリデーションに引っ掛かって登録することができません。
どうにかソフトデリートとユニークなメールアドレスを両立させる方法はないでしょうか。
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:なんか抜け毛が増えた気がする
Laravel で簡易APIサーバーを作ってみた
風邪をひいて一日中臥せっていた。が、さすがにずっと眠れるわけもないので意味もなく blog を更新してみる試み。
Sinatraで簡易APIサーバーを作ってみた | Developers.IO の Laravel 版。
動作確認
では、実際に動かしてみよう。ターミナル(あるいはコマンド・プロンプト)で Laravel のプロジェクトにカレントディレクトリを移動させて以下のコマンドを実行する。
$ php artisan serve
こうするだけで PHP の Built-in web server が起動する。あとはブラウザから http://localhost:8000/show
にアクセスしてみよう。
{"id":1,"title":"today's dialy","content":"It's a sunny day."}
こんな感じで出力されていると思う。余談だが、return Response::json($article);
の部分を return json_encode($article);
しても同じ結果に見えるが Response::json
を使用すると Content-Type
を application/json
にしてくれる。json_encode
使うと text/html
になるので実際おすすめできない。
次は POST リクエスト。元エントリと同じく curl
を使用してリクエストを投げる。まずは body を未指定で POST する。
curl -X POST -I http://localhost:8000/edit
結果はこんな感じ
HTTP/1.0 400 Bad Request (以下略)
return App::abort(400);
がちゃんと機能しているのがわかる。
次は body を指定して POST する。
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"title":"MyFavorite","content":"Color is Black."}' http://localhost:8000/edit -w "\n%{http_code}\n"
結果は
略 {"title":"MyFavorite","content":"Color is Black."} 200
リクエストされたものがそのまま返却された。
言いたいこと
Laravel は簡単なことはちゃんと簡単に書ける。僕らは難しいことに頭をひねろう。
Typetalk Hack Fukuoka に行ってきたよ
ブログを書くまでが勉強会です。
Typetalk Hack Fukuoka on Zusaar
API を見ると、とりあえず叩いてみる習性があるので行ってきました。
感想としては、90 分でなにか作るのは結構厳しいなぁ…とか思ってたんですが発表を聞いている限りみんなすごかったので、こりゃあ頑張らなきゃなあとおもいました(小並感)。
発表で印象に残っているのは @kiwanami さんのS式をポストすると結果を返す変態botと cakephper さんのtwilio API とマッシュアップさせてtypetalk にボイスメッセージを届くようにする仕組み。
僕はなぜか、backlog-api-php のテスト書いてました。typetalk-api-php もリポジトリだけは作ったので近いうちにリリースしたい。
その後の懇親会は(いや、全体的に)@hayashi_77無双でした。とても愉快な方です。
楽しかったのでまたやって欲しいなぁ。
Laravel で View を文字列で取得する
簡単。
<?php $viewStr = View::make('home')->render();
でOK.セクション毎にも取れる。
<?php $viewStr = View::make('home')->renderSections()['content'];
Laravel 4.2 Beta をインストールする
これが一番簡単だと思います。
$ git clone -b develop https://github.com/laravel/laravel.git laravel-beta $ cd laravel-beta $ composer install
変更点等は @HiroKws のツイートをチェックするべし。
注意点ですが、trait を使用しているため PHP5.4 以上になっているのでそこだけ気をつけてください。
追記
今現在開発しているアプリケーションを 4.2 にあげたい人は composer.json
を修正しましょう。
{ "require": { "laravel/framework": "4.2.*" }, "minimum-stability": "dev" }
この2箇所を修正すればOKです。
Laravel で Controller から Controller を呼ぶ
@syossan27 やりたいことがピンときませんが、処理が終わったらもう一つのアクションにリダイレクトしてみてはいかがでしょうか?
— MATSUO Masaru (@localdisk) 2014, 5月 12
たまーに、こんなことしたいことがありますね。で、まぁリダイレクトすればいいよ、みたいな回答したんですが、よく考えたら普通にできるよなーと。
まず、呼び出される CalledController
.
<?php class CalledController extends \BaseController { protected $user; public function __construct(User $user) { $this->user = $user; } public function getUser() { return $this->user; } }
この getUser
を呼び出したいとします。
で、呼び出す側。CallController
はこんな実装になります。
<?php class CallController extends \BaseController { public function getIndex() { $called = app()->make('CalledController'); $user = $called->getUser(); var_dump($user); } }
app()->make('CalledController')
でコンテナ経由で CalledController
のインスタンスを取得しています。なので CalledController
に定義されているコンストラクタインジェクションが機能しててちゃんとインジェクションされた User
クラスが取得できるわけです。
もちろんコンストラクタで CalledController
をインジェクションすることもできます。
<?php class CallController extends \BaseController { protected $called; public function __construct(CalledController $called) { $this->called = $called; } public function getIndex() { $user = $this->called->getUser(); var_dump($user); } }
まぁ、Controller から別の Controller のメソッドを呼びたいというシチュエーションが発生した場合、リファクタリングのチャンスと思ってリファクタリングしたほうがいいんじゃないかなーと思います。色々あってそうも行かない時等にこのエントリを思い出していただければ幸い。
Typetalk Hack Fukuoka で Services_Backlog を作り直します
むかーし、Services_BacklogというBacklog の API の PHP Wrapper を作った*1んだけど、PEAR も時代遅れだし、対応しているAPIが少ないとか、なんか動かなくて困ってる人とかいて、心の中で謝罪を繰り返していたんですが、ちょうど上記のイベントが開催されるようなのでちゃんと作りなおそうと思います。余裕があれば typetalk の PHP API Wrapper も作りたいところ。
もう大体できてる。
手抜き部分*2やテスト書いたらリリースします。もちろん Composer 対応です。今回は PSR-4 使ってみた。
(2014/05/14 追記)
こっそりリリース localdisk/backlog-api-php - Packagist
あと、明日は Fukuoka.jvm #1 に行ってきます。ここのところ、Java で頭使う仕事全然してなくて*3 Java 力が落ちる一方なのでここらへんで喝を入れたい。