ラベル Lumen の投稿を表示しています。 すべての投稿を表示
ラベル Lumen の投稿を表示しています。 すべての投稿を表示

2016年3月5日土曜日

Amazon SESを使ったLumen(Laravel)のメール送信

Lumen(5.1)では、Laravelのメール機能が標準では含まれていないので、追加して試してみました。

参考

https://laravel.com/docs/5.1/mail

追加するパッケージ

composer.jsonのrequireに以下のパッケージを追加してcomposer updateします。
 "illuminate/mail": "5.1.*",
 "aws/aws-sdk-php": "~3.0",

設定ファイルの追加

config/mail.phpとconfig/services.phpファイルの作成(デフォルト設定ファイルmail.phpをコピーする)
// configディレクトリが無い場合は作成する
cp vendor/laravel/lumen-framework/config/mail.php config/mail.php

// services.phpは空ファイルを作成して設定値を自分で記述した
touch config/services.php

config/mail.phpの修正

// デフォルト値をsesと書き換える。または環境変数MAIL_DRIVERを設定する
driver' => env('MAIL_DRIVER', 'ses'),

config/services.php

awsで作成した値を設定します。
<?php
return [
    'ses' => [
        'key'    => 'keyの値',
        'secret' => 'secretの値',
        'region' => 'リージョンの値',  // e.g. us-east-1
    ]
];

テンプレートの作成

// テンプレートファイルを作成
touch resource/views/emails/example.blade.php
テンプレートには、通常のviewと同様に変数を渡せます。

HTMLメールの送信

Mail::send('emails.example', ['user' => $user], function ($m) use ($user) {
    $m->from('hello@app.com', 'Your Application');
    $m->to('メールアドレス', '名前')->subject('テストメールの件名');
});

テキストメールの送信

// テンプレートの値を配列にしてキーをtext、値にテンプレートのパスを指定する
Mail::send(['text' => 'emails.example'], ['user' => $user], function ($m) use ($user) {
    $m->from('hello@app.com', 'Your Application');
    $m->to('メールアドレス', '名前')->subject('テストメールの件名');
 });

// 配列でhtmlメールを指定する場合
Mail::send(['html.view', 'text.view'], $data, $callback);

まとめ


Laravelのドキュメントを確認した限りでは、送信オプションもいろいろ網羅されているので細かい調整もできそうです。標準以上の機能が必要なケースはあまりないかもしれませんが、もっとカスタマイズが必要な場合は、コアのソースを確認して調査する必要がありそうです。
あと、Amazon SESはデフォルトで送信制限があるので、テスト用のメールアドレスはあらかじめSES側で設定とverify(メールアドレスの有効性の確認)しておく必要があります。制限解除済みであれば登録不要です。

2016年2月14日日曜日

Laravel, LumenのSELECT文いろいろ

Laravel, LumenでSELECT文に慣れていないのでメモ。

参考

https://laravel.com/docs/5.1/eloquent#retrieving-single-models

SELECTもいろいろある

find

  • プライマリーキーでマッチした1レコードを取得する
  • 戻り値はモデルのインスタンス(stdClass)
  • 0件の場合は、null
$flight = Flight::find(1);

first

  • 条件にマッチした最初の1レコードを取得する
  • 戻り値はモデルのインスタンス(stdClass)
  • 0件の場合は、null
$flight = Flight::where('active', 1)->first();

get

  • 条件にマッチした全てのレコードを取得する
  • 戻り値は、配列(各レコードはstdClassオブジェクトのインスタンス)
  • 0件の場合は、オブジェクトが返る
$flight = Flight::where('active', 1)->get();

all

  • 全てのレコードを取得する
  • 戻り値は、配列(各レコードはstdClassオブジェクトのインスタンス)
  • 0件の場合は、オブジェクトが返る
$flight = Flight::all();

0件の場合の評価の違い

$flight = Flight::find(1);
if (!$flight ) {
  // 通る
}

$flight = Flight::where('id', 1)->first();
if (!$flight ) {
  // 通る
}

$flight = Flight::where('id', 1)->get();
if (!$flight) {
    // 通らない (オブジェクトが戻り値のため)
}
if (!count($flight)) {
    // 通る Countableインターフェース
}

$flight = Flight::where('id', 1)->get()->toArray();
if (!$flight) {
    // 通る (オブジェクトを配列に変換したため)
}
if (!count($flight)) {
    // 通る
}

$flight = Flight::all();
if (!$flight) {
    // 通らない (オブジェクトが戻り値のため)
}
if (!count($flight)) {
    // 通る Countableインターフェース
}

まとめ

  • get(), all()の場合は、0件の場合もオブジェクトが返る。
  • Objectはtrueということと、1件または複数レコード(get()を使うか)を意識して書けばよさそう。
  • Illuminate\Database\Eloquent\Collectionは、継承しているクラスがCountableインターフェースを実装していてcount()でitemsの件数が取れる。
Illuminate\Database\Eloquent\Collection Object
(
    [items:protected] => Array
        (
        )
)


2016年2月4日木曜日

Lumenのタイムゾーン設定

Lumenを検証していたところ、時間がUTCになっていたのでメモ

Lumen5.1で時間を表示させたところUTCとなっていました。
echo date('Y-m-d H:i:s e P'); // 2016-02-04 09:00:23 UTC +00:00
Asia/Tokyoとなってほしいのですが、
アプリ側では何も設定していないので、lumenのソースを確認したところ見つかりました。

lumen-framework/src/Application.php

    public function __construct($basePath = null)
    {
        date_default_timezone_set(env('APP_TIMEZONE', 'UTC'));
        $this->basePath = $basePath;
        $this->bootstrapContainer();
        $this->registerErrorHandling();
    }
この場合、環境変数APP_TIMEZONEは設定していないのでUTCになるわけですが、
デフォルト値をphp.iniの設定にしてほしいのは私だけでしょうか。

Dotenvを使っている場合は、.envに追加
使っていない場合は、bootstrap/app.phpに設定を追加することにしました。

.env

APP_TIMEZONE=Asia/Tokyo

bootstrap/app.php

// Dotenv::load(__DIR__.'/../');
putenv('APP_TIMEZONE=Asia/Tokyo');
軽量フレームワークなので、かゆいところは自分で対応する必要があるわけですが、
これはドキュメントに書いてほしいですね。

2016年1月18日月曜日

LaravelとLumenでベンチマークやり直し

前回の「LaravelとLumenのHello Woldを試す」は実用的な計測ではないので、
もう少し通常の動的サイトに近い処理を追加して計測してみました。

テスト環境

前回の記事を参照

LaravelとLumenで以下のファイルを追加

  • ルーティング設定でHomeコントローラを指定する (app/Http/routes.php)
  • データベース設定を追加する (config/database.php)
  • コントローラーにデータを取得する処理を追加する (app/Http/Controllers/HomeController.php)
  • モデル追加する (app/Page.php)
  • ビュー追加する (resources/views/home/index.php)
  • ビュー上でデータをforeachで20件ほど表示する
  • セッション機能はfileを使用する
  • Lumenは、機能(DotEnv, Facade, Eloquent)を削る毎にHomeControllerを修正する

Lumenは機能の有無で4パターン計測

機能の切り替えは、bootstrap/app.phpを修正する
  • DotEnv, Facade, Eloquentを使用する
  • DotEnv, Facadeを使用する
  • DotEnvを使用する
  • DotEnv, Facade, Eloquentを使用しない

Lumen5.2ではなく5.1も対象している理由

Lumen5.2ではAPI Tokenの利用を前提にしているようでsession機能が削除されました。
独自にsession機能を追加すると別のものになってしまうので、できるだけLumenをLaravelに近づけるため5.1の計測をしてみました。
ちなみに、sessionを利用したい場合は、Laravelがおすすめとのこと。

結果

framework req/sec
Laravel 5.2692.81
Lumen 5.1 (DotEnv, Façade, Eloquent)1,341.92
Lumen 5.1 (DotEnv, Façade)1,523.70
Lumen 5.1 (DotEnv)1,632.32
Lumen 5.2 (DotEnv)1,663.94
Lumen 5.11,769.84

前回の結果ほど差はありませんが、1.9〜2.5倍程度Lumenの処理性能が速い結果となりました。
DotEnv, Facade, Eloquentを使っても約2倍近い性能を得ることができるので、パフォーマンス重視の方は選択肢の1つとなるのではないでしょうか。
ソースの書き方によってはLaravelに近づけることや移植もできると思うので、良い派生プロジェクトではないでしょうか。

2016年1月15日金曜日

LaravelとLumenのHello Woldを試す

バルス待機中に気になったので確認してました。
「The stunningly fast micro-framework by Laravel.」と公言しているLumenですが、
Laravelとどの程度の差があるかHello Worldで計測してみました。

テスト環境

Intel Core i7-4790K
メモリー 16GB
Ubuntu 15.10
PHP 5.6.11
nginx/1.9.3

  • 特別なチューニングはしていません
  • nginxとphp-fpmの設定もインストールした時のデフォルトのままです。
  • LaravelとLumenはcomposerインストールした状態です
  • どちらもroute.phpで文字列"Hello World!"を返すように修正しました。
  • abコマンドで計測しました

結果

Laravel 5.2     928.19 req/sec
Lumen 5.2     5589.13 req/sec
予想以上に差が出てしまいました。約6倍
機能の数が違うので、検討すべきことは多いですが、LumenはAPIサーバとかに向いているかも。オーバーヘッドの少ないWAFですね。
なかなか悩ましい結果となりました。

以上、簡易的なベンチマークでした。


Laravel 5.2

ab -c 100 -n 10000 http://laravel.local/
This is ApacheBench, Version 2.3 <$Revision: 1638069 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking laravel.local (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        nginx/1.9.3
Server Hostname:        laravel.local
Server Port:            80

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      100
Time taken for tests:   10.774 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      2580000 bytes
HTML transferred:       120000 bytes
Requests per second:    928.19 [#/sec] (mean)
Time per request:       107.737 [ms] (mean)
Time per request:       1.077 [ms] (mean, across all concurrent requests)
Transfer rate:          233.86 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       1
Processing:     4  107  10.0    105     130
Waiting:        4  107  10.0    105     130
Total:          5  107  10.0    105     130

Percentage of the requests served within a certain time (ms)
  50%    105
  66%    113
  75%    114
  80%    115
  90%    117
  95%    125
  98%    128
  99%    128
 100%    130 (longest request)

Lumen 5.2

ab -c 100 -n 10000 http://lumen.local/
This is ApacheBench, Version 2.3 <$Revision: 1638069 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking lumen.local (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        nginx/1.9.3
Server Hostname:        lumen.local
Server Port:            80

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      100
Time taken for tests:   1.789 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      2110000 bytes
HTML transferred:       120000 bytes
Requests per second:    5589.13 [#/sec] (mean)
Time per request:       17.892 [ms] (mean)
Time per request:       0.179 [ms] (mean, across all concurrent requests)
Transfer rate:          1151.67 [Kbytes/sec] received

Connection Times (ms)
             min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       2
Processing:     1   18   2.7     17      25
Waiting:        1   18   2.7     17      25
Total:          2   18   2.7     17      25

Percentage of the requests served within a certain time (ms)
 50%     17
 66%     18
 75%     18
 80%     19
 90%     22
 95%     24
 98%     24
 99%     24
100%     25 (longest request)