Laravel4で「HelloWorld」を表示させるまで
最近、ようやく、注目が集まってきたPHPのWebアプリケーションフレームワークLaravelのLaravel4 Beta4が
リリースされたので、HelloWorldを出力するまでの流れを簡単に書いていこうと思います。
【Laravel4のインストール】
- Laravel4はLaravel3とは違ったインスール方法が採用されている。
- ComposerというPHPのパッケージ管理システムを使ったインスールになる。
- Composerとは何か?
- 公式サイト http://getcomposer.org/
- まず、Composerをインストールしなければならない。
- ComposerのインストールとPATHの設定を確認した後
{ "require": { "laravel/framework": "4.0.*" }, "autoload": { "classmap": [ "app/commands", "app/controllers", "app/models", "app/database/migrations", "app/database/seeds", "app/tests/TestCase.php" ] }, "minimum-stability": "dev" }
- requireの項目に、"laravel/framework": "4.0.*" という記述が。
- どういうことか?
- https://packagist.org/packages/からrequireで指定されたパッケージのバージョンがダウロード&インストールされる。
- https://packagist.org/packages/laravel/framework/へブラウザでアクセスすると、Laravelのパッケージ一覧が閲覧できる。
- requireの項目に "laravel/framework": "4.0.*@dev"を指定すると最新版が、"laravel/framework": "v4.0.0-BETA3"を指定すると、BETA3がインストールされる。
- requireでバージョンが指定されていない場合minimum-stabilityの値が"dev"となっているので、最新版が自動的にインストールされる形になる。
- どういうことか?
- どうやってインストールする?
<?php // autoload_classmap.php generated by Composer $vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( 'BaseController' => $baseDir . '/app/controllers/BaseController.php', 'DatabaseSeeder' => $baseDir . '/app/database/seeds/DatabaseSeeder.php', 'HomeController' => $baseDir . '/app/controllers/HomeController.php', /* 中略 */ 'User' => $baseDir . '/app/models/User.php', );
<?php // autoload_namespaces.php generated by Composer $vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( 'Symfony\\Component\\Translation\\' => $vendorDir . '/symfony/translation/', 'Symfony\\Component\\Routing\\' => $vendorDir . '/symfony/routing/', 'Symfony\\Component\\Process\\' => $vendorDir . '/symfony/process/', /* 中略 */ 'Illuminate' => $vendorDir . '/laravel/framework/src/', );
- で、ようやく、Laravel4の初期設定。
- php artisan key:generate を実行しておく。すると、app/config/app.php のkeyに値がセットされる。
- .htaccessを編集。
- RewriteBase /project_root/public/ 任意のディレクトリを指定
- 127.0.0.1/project_root/public/へアクセスする
- 「Hello World!」が出力されていればとりあえずは成功。
- app/routes.php にルーティングが定義されていおり、デフォルトではトップページのルーティングが定義されているだけ。詳しくは、別のエントリーで。
- ちなみに、このViewファイルはapp/views/hello.php。
- 127.0.0.1/project_root/public/へアクセスする
- RewriteBase /project_root/public/ 任意のディレクトリを指定
とりあえずは、今回は、こんな具合で終わり。
次は、新しいコントローラーの作成とルーティングの定義やモデルファイルの作成を書いていこうと思います。
- Laravel4のドキュメント
- http://four.laravel.com/docs/eloquent
- Hirohisa Kawaseさんによる 日本語ドキュメント https://leanpub.com/laravel4plus
LaravelのORM Eloquentで括弧を使ったクエリーのグループ化する方法
- 商品テーブルから削除フラグが0で公開ステータスが1の商品で、更に入力されたキーワードに該当する商品を取得したい
<?php // キーワード $keyword=Input::get("keyword"); // 検索 $itemList=Item::where("del_flg", "=", 0) ->where("item_public_status", "=", 1) ->where(function($query) use($keyword) { $query->where("item_name", "LIKE", "%$keyword%"); $query->or_where("item_meta_keywords", "LIKE", "%$keyword%"); $query->or_where("item_meta_description", "LIKE", "%$keyword%"); }) ->get();
- ポイントは無名関数を使うときに、useを使うこと。
- 無名関数内では、$keywordにアクセスできないためuse構文を使用する。
- useには複数指定できるので、引き継ぎたい変数をどんどんぶっこめばいいだけ。
- こうして実行されるSQL
SELECT * FROM `item` WHERE `del_flg` = '0' AND `item_public_status` = '1' AND (`item_name` LIKE '%チョコ%' OR `item_long_description` LIKE '%チョコ%' OR `item_meta_keywords` LIKE '%チョコ%' OR `item_meta_description` LIKE '%チョコ%')
LaravelのキャッシュでRedisを使う
PHPフレームワークのLaravelでキャッシュエンジンをRedisにしてみた。以外と、すんなり言ったので、記事を残しておく。
- Redisの概要
- Redisのインストール
- Laravelでの設定。
- application/config/database.php にRedisに関する項目を探す
<?php // application/config/database.php /* 中略 */ 'redis' => array( 'default' => array( 'host' => '127.0.0.1', 'port' => 6379, 'database' => 0 ), ),
-
- キャッシュの設定
- ドライバーにRedisを指定する
- application/config/cache.php にRedisに関する項目を探す
- キャッシュの設定
<?php // application/config/cache.php 'driver' => 'redis'
基本これだけでOK。あとは通常通り、キャッシュを使えばいいだけ
<?php // 保存 // 3番目の引数は分数 Cache::put('key', 'value', 10); // 取得 $value= Cache::get('key'); // 削除 Cache::forget('key');
LaravelのORM機能 Eloquent の EagerLoading
LaravelのORM Eloquentには、Eager Loadingという機能がある。
モデル内に定義されたメソッドを元に自身以外の他テーブルからデータを引っ張りだしてくれる便利な機能。
例えば、以下の様なECサイトのテーブル構成でイメージしてみる。
商品テーブルにはimage_idというサムネイル用のIDが定義されており、画像テーブルのimage_idにリンクされている。
やりたいこととしては、商品情報と画像の情報を一度に取得するというもの。
モデルの定義は割と簡単で以下のように設定する。
<?php // models/item.php class Item extends Eloquent{ public static $table = "item"; public static $key = "item_id"; public static $timestamps = false; // サムネイル function thumb(){ return $this->belongs_to("Image","image_id"); } } // models/image.php class Image extends Eloquent{ public static $table = "image"; public static $key = "image_id"; public static $timestamps = false; }
で、問題はコントローラー側でどういう呼び出し方をするのか?
Eloquentでは、必ず、staticなwithメソッドからスタートさせなければならないルールがある。
<?php /* コントローラー側の処理 */ // すべての商品をサムネイルと一緒に取得 $itemList=Item::with("thumb")->get(); // 条件を付与 $itemList=Item::with("thumb") ->where("price",">",500) ->where("del_flg","=",0) ->get(); // 情報の呼び出し方 foreach($itemList as $value){ echo $value->item_name." ".$value->price."円 :"; echo $value->thumb->file_name; } // 出力 // 銅の剣 500円:thumb_ken.jpg ?>
といった具合な事を書く。ちなみに、以下が実行されるSQL。
SELECT * FROM `item`; SELECT * FROM `image` WHERE `item_image_id` IN (1,2,3); SELECT * FROM `item` WHERE `price` > 500 AND `del_flg`=0; SELECT * FROM `image` WHERE `item_image_id` IN (1,3);
見ての通り、JOINなどでテーブル結合しているわけではなく、一度、商品テーブルからデータを取得した後、
image_idをIN句でくくって、取得するという方法が取られている。
これに関しては、まぁ、色々と議論の余地はあるんでしょうが、チャチャっと作りたい人には便利な機能かもしれません。
LaravelでSQLの実行結果が簡単にわかるプロファイラー機能
Laravel3.1になり、Bandle(プラグイン)として提供されていたSQLプロファイラーのAnbuが標準で組み込まれることになり、LaravelでもCakePHPのようなSQL実行結果が簡単にわかるようになったようです。このプロファイラーはCake同様、ページの下部に固定される形に表示されるわけですが、標準ではオフになっているので、有効にするには、以下のように設定する必要があります。
- application/config/application.phpを開く
- Profilerの項目をfalseからtrueに変更して保存
<?php /* 中略 */ /* |-------------------------------------------------------------------------- | Profiler Toolbar |-------------------------------------------------------------------------- | | Laravel includes a beautiful profiler toolbar that gives you a heads | up display of the queries and logs performed by your application. | This is wonderful for development, but, of course, you should | disable the toolbar for production applications.. | */ 'profiler' => true,
DBに接続しているページを表示してみれば、下のような具合で、SQLの実行結果が確認できます。
LaravelのELOQUENTの便利なSETTERとGETTER
LaravelのORMには特定のフィールドに対して、ちょっとした処理を加えて、データを保存できたりする便利な
メソッドがあります。わかりやすいのは、パスワードを暗号化して保存したい場合。
$user->password="password" としてやるだけで、文字列が暗号化されてデータがセットされるみたいな。
方法は非上に簡単で、set_{フィールド名}でメソッドを作ってあげればいいだけ。あとは、そのメソッド内で暗号化なりなんなり好きにすればいいだけです。下のサンプルでは、LaravelのCrypterを使って暗号化するサンプルです。
<?php // models/user.php use Laravel\Crypter; use Laravel\Database\Eloquent\Model; class User extends Eloquent { public static $table = "user"; public static $key = "user_id"; public static $timestamps = false; public function set_password($password){ $this->set_attribute("password", Crypter::encrypt($password)); } } // コントローラー // controllers/user.php class User_Controller extends Base_Controller { public function action_add(){ $user=new User; $user->name="nohohonx"; $user->password="hogehoge"; $user->save(); } } ?>
phpMyAdminなどで、userテーブルを見ると、暗号化されたU326DItRyQYN8Pb3Eu82iNshUMqwngf+Oh5o93hEみたいな文字列で埋まってるはずです。素晴らしい。また、逆にget_{フィールド名}のメソッドを定義することも可能で、テーブル上に存在しないフィールド名を使用しても問題ありません。下のサンプルは、日本語の日付フォーマットに整形されたデータを取得するサンプル。
<?php public function get_format_registed_date(){ $datetime = date_create($this->get_attribute("registed_date")); return date_format($datetime, "Y年m月d日"); } // 整形されたデータが表示されます。 echo $user->format_registed_date;
他にも苗字と名前を一緒に取得するためのメソッドを定義するなんてことも。
<?php class User extends Eloquent { public static $table = "user"; public static $key = "user_id"; public static $timestamps = false; public function get_full_name(){ return $this->get_attribute("last_name")." ".$this->get_attribute("first_name"); } } // Yamada Tarou が出力される $user=User::find(1); echo $user->full_name;
他のフレームワークにも似たような機能はあるんでしょうが、実に素晴らしいです。
Laravelのバリデーションの日本語化など。
Webアプリでは欠かせない重要な機能。入力値の検証いわゆるバリデーション。もちろん、Laravelにも、バリデーション機能があるわけで。
一応、備忘録として、日本語化の方法なども含めて、簡単に残しておこうと思う。
- 下準備
- 以下、入力検証アクションのサンプル
<?php // 入力検証アクション public function action_validate(){ // 入力値 // すべての入力値が連想配列で取得できる。 $input = Input::all(); // バリデーションルール $rules = array( "name" => "required|min:5|max:60", "email" => "required|email", ); // 検証 $validation = Validator::make($input, $rules); // 検証結果 if ($validation->fails()){ // エラーの場合 Session::flash("action_message","入力値に問題があります。"); Session::flash("action_errors",$validation->errors->all()); return Redirect::back()->with_input(); }else{ echo "Success!!"; } } ?>
-
- 上のコードは何をやっているか?
- $input = Input::all(); で入力値を連想配列で取得。
- $rules = array(); で検証ルールを設定
- 検証ルールの指定方法はこの辺を参考に
- http://laravel.com/docs/validation
- CodeIgniterとかやってた人にはとっつきやすいかも。
- 検証ルールの指定方法はこの辺を参考に
- Validator::make($input, $rules);でオブジェクトを作成。
- $validation->fails()で失敗かどうか判定
- 入力値に問題がある場合は呼び出し元へリダイレクト
- return Redirect::back()->with_input(); はとても幸せになれる魔法のコードだと思ってる。
- リダイレクトすると共に、入力値を引き継げるメソッドだから。
- View内でInput::old("name")って呼び出すと、保持された入力値が表示できる。ただし、リロードすると消える。
- return Redirect::back()->with_input(); はとても幸せになれる魔法のコードだと思ってる。
- 上のコードは何をやっているか?
- 肝心の日本語化は?
- 下準備の時点でコピーしたapplication/language/ja/validation.phpを見ればなんとなくわかるはず!
<?php return array( "accepted" => "The :attribute must be accepted.", "active_url" => "The :attribute is not a valid URL.", "after" => "The :attribute must be a date after :date.", "alpha" => "The :attribute may only contain letters.", "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.", ); ?>
-
- お好みの日本語でどうぞ
- :attribute には HTMLフォームで指定した name 属性が勝手に入ることになる。
- これも日本語にしたいって?
- ご心配なく、同ファイル内に↓これを書けばいい。
- これも日本語にしたいって?
<?php "attributes" => array( "name"=>"お名前", "email"=>"メールアドレス", "address"=>"住所", ) ?>
-
- 簡単でしょ?
とりあえず、今日はこれまで。