CyberX:エンジニアブログ -7ページ目

gmailを使ってPHPでメール送信する

こんにちは、エモンと言います。

今回はモバゲーやmixiとかオープンプラットフォームとは無縁の技術について解説します。
Gmailを使ってPHPからメール送信してみます。
尚、cyberXではcakePHPを使ったプロジェクトが多いので、
cakePHPから送信することを考えます。

PHPでメール送信するにはPEARとかその他ライブラリが必要らしいですが、
cakePHPではその点、はじめから全て入っているようです。

準備
コントローラにてEmailコンポーネントを宣言。

var $components = array('Email',);



適当なfunctionにてSMTPオプションを設定する。

$this->Email->smtpOptions = array(
'port'=>'465',
'timeout'=>'30',
'host' => 'tls://smtp.gmail.com',
'username'=>'hogename',
'password'=>'hogepass'
);



※ポートとホストはここらしい。しめしめ。
※usernameとpasswordのところは、自分のgmailアカウントにあわせてください。
あとは送信設定してsendするだけです。


/* 送信のメソッドをセットする */
$this->Email->delivery = 'smtp';
$this->Email->from = 'hogename ';
$this->Email->to = 'hogetoname ';
$this->Email->subject = 'Test';
$this->Email->send('日本語を送ってみます');
/* SMTP エラーを確認する。 */
$this->set('smtp-errors', $this->Email->smtpError);



これでテストしたところ、日本語もうまく送れました。
いや~なんていうか、gmailすげぇ。cakePHPすげぇ。

PHPフレームワーク Ethnaを使おう!

はじめまして,CyberXエンジニアの石川です.

CyberXではアプリ開発は,通常CakePHPを使用しています.
が,今回は,PHPフレームワークの一つEthnaを紹介します.

PHPの代表的フレームワークとしてZend Frameworkや,CakePHPSymphonyなどが有名ですが,EthnaもそういったPHPフレームワークの一つです.
Ethnaは,GREEで開発,利用されています.
かなりカスタマイズされていると思いますが,GREE規模のアプリケーションで利用可能というのは大きな実績を持っていると言えます.

それでは,Ethnaのディレクトリ構造から見ていきましょう.

app (アプリケーションのスクリプト)
┃ ┣ action (アクションスクリプト)
┃ ┣ action_cli (CLI用アクションスクリプト)
┃ ┣ action_xmlrpc (XMLRPC用アクションスクリプト)
┃ ┣ plugin (フィルタスクリプト)
┃ ┣ test (テストスクリプト)
┃ ┗ view (ビュースクリプト)
┣ bin (コマンドラインスクリプト)
┣ etc (設定ファイル等)
┣ lib (アプリケーションのライブラリ)
┣ locale
┃ ┗ ja_jp
┣ log (ログファイル)
┣ schema (DBスキーマ等)
┣ skel (アプリケーション用スケルトンファイル)
template
┃ ┗ ja_jp (テンプレートファイル)
┣ tmp (一時ファイル)
┗ www (ウェブ公開用ファイル)
  ┣ css (CSSファイル)
  ┗ js (JavaScriptファイル)

今回は,良く扱うファイルを実際のコードと合わせてご説明します.

今回作るプログラムは下記の様なものです.
・ログインフォーム.
・user_infというテーブルがある.
 (カラムとしてidとpasswdを持っている.)
・ユーザはIDとパスワードを入力してログイン.


1.ActionClassとActionForm
ファイル:app/action/Login.php

class Sample_Form_Login extends Ethna_ActionForm
{
// フォームの定義
var $form = array(
'id' => array(
'type' => VAR_TYPE_STRING,
'form_type' => FORM_TYPE_TEXT,
'name' => 'ID',
'required' => true,
),
'passwd' => array(
'type' => VAR_TYPE_STRING,
'form_type' => FORM_TYPE_PASSWORD,
'name' => 'ログインパスワード',
'required' => true,
),
);
}
class Sample_Action_Login extends Ethna_ActionClass
{
// 前処理
public function prepare() {
}

// メイン処理
public function perform() {
$result = false;
if ($this->af->validate() == 0) {
$id = $this->af->get('id');
$passwd = $this->af->get('passwd');
$userMng =& $this->backend->getManager("User");
$result = $userMng->auth($id, $passwd);
}
if ($result === false) {
$this->ae->add("loginerror", "ログインエラー");
return "login";
} else {
return "mypage";
}
}
}

Ethnaの特徴の一つがActionFormです.
ActionFormでは,フォームから渡ってくる値を定義できます.
ここではidとpasswdを定義しています.
定義に関して詳しくは,こちらのドキュメントを参考にしてください.

次に,ActionClassでは,実際のアクションを記述します.
ここでは,フォームから受け取ったidとpasswdをUserManagerのauthメソッドで検証しています.
ActionClassについてより詳しい解説は,こちらのドキュメントを参考にしてください.

このプログラムでは,まずvalidateでActionFormに記述した内容に沿ってバリデートされます.
バリデートの結果が,0の時に引数として,idとpasswdをUserManagerのauthメソッドに渡します.
その結果trueであれば,mypageテンプレートを表示し,falseの場合にはもう一度loginテンプレートを表示する様になっています.

2.AppObjectとAppManager
ファイル:app/Sample_UserManager.php

class Sample_UserInf extends Ethna_AppObject
{
}

class Sample_UserManager extends Ethna_AppManager
{
public function auth($id, $passwd) {
$userInf = $this->backend->getObject('UserInf', "id", $id);
$pass = $userInf->get("passwd");
if ($passwd == $pass && $pass != "") {
return true;
}
return false;
}
}
?>

AppObjectは,EthnaのORマッパーです.
ここでは,利用するテーブルに関して,メッソド追加などが行えます.
詳しくは,こちらのドキュメントを参考にしてください.

AppManagerは,いわゆるMVCのModelに該当します.
ここでは,authメソッドがあり,authメソッドでは,idから対象ユーザの情報を取得し,そのpasswdが一致すればtrue,しなければfalseを返す様になっています.
詳しくは,こちらのドキュメントを参考にしてください.

3.テンプレート
template/ja_JP/login.tpl

{foreach from=$errors item=error}
{$error}

{/foreach}

{form ethna_action="login" action="/login.php"}
ID {form_input name="id" size="20"}
パスワード {form_input name="passwd" size="8"}
{form_submit value="ログイン"}
{/form}



最後にテンプレートの解説をします.
基本的にEthnaでは,Smartyを利用します.
本来のSmartyと違う部分としては,{form}タグです.
{form}タグでの記述はformタグとして出力されます.
(※ethna_actionに記述された内容はaction指定がinputのhiddenとして生成されます)
{form_input}では,先に記述したActionFormの定義に沿ってinputタグが生成されます.
{form_submit}では,submitボタンが生成されます.


最後に,今回は時間の都合上,表面上の説明しか出来ませんが,Ethnaには他にも便利な機能が様々備わっています.
PHPフレームワークは多数ありますが,その中でも大変魅力的なフレームワークの1つと言えます.

Ethnaについて少しでも興味を持って頂ければ幸いです.

社内で発表した際の資料はこちら


参考
・Ethna
http://ethna.jp/
・Smarty
http://www.smarty.net/docsv2/ja/

phpスクリプトの速度改善

はじめまして。CyberXのエンジニア青木といいます!




今回はphpスクリプトを見直して処理速度を改善しましょうというお話です。




普段書き慣れたコーディング手法が実はけっこう時間かかっているのでは?

と前々から疑問に思っていたところ、ブログ執筆が良いきっかけとなったので今回の調査に至りました。




まず、下記インクリメントの違いについて調べてみました。




・$a++(後置加算子)
・++$a(前置加算子)
・$a=$a+1
・$a+=1




計測用に下記のスクリプトを作り、インクリメントの部分だけ書き換えてそれぞれ10000万回ループさせてみました。




for($a=0;$a<10000;$a++)
{
// something do
}



結果は下記の通りで一番早かったのは「$a+=1」となりました。

反対に「++$a」は一番時間がかかってるようですね。




・$a++(0.616msec)
・++$a(0.806msec)
・$a=$a+1(0.729msec)
・$a+=1(0.519msec)




次に、下記ループの違いについても調べてみました。


・for
・while
・foreach




インクリメントの計測で下記スクリプトの結果は0.616msecとお伝えしました。




for($a=0;$a<10000;$a++)
{
// something do
}



whileも同様に下記のスクリプトを作って10000万回計測したところ、




while($a<10000)
{
// something do
$a++;
}



計測結果は0.689msecとなりました。


最後にforeachで計測したところ、




foreach($loop_ary as $value)
{
// something do
}



計測結果は0.671となりました。


これといって速度に違いは見られず、違いを期待していただけに残念でした。


そこで、評価式に関数を使った場合についても調べてみました。


これまでと同様に10000万回のループで評価式にphp組み込み関数のcount()を使ったケースです。




for($a=0;$a{
// something do
}



計測結果は2.166msecとなりました。

評価式に関数を使わない場合に比べると、約3.5倍程度の時間がかかっている事がわかりました。


またwhileで配列のキー、値を順次セットで取得する下記のケースも調べてみました。




while(list($key,$value)=each($loop_ary))
{
// something do
}



結果は3.953msecです。評価式に関数を2つ使ってる事もあり、

使わない場合に比べると、なんと5倍以上の時間がかかっている事がわかりました。


配列からキー、値を順次セットで取得する場合はforeachの下記構文でも

取得できますので、こちらも同様に計測してみたところ、




foreach($loop_ary as $key => $value)
{
// something do
}



すると、計測結果は0.868msecとなりました。

先ほどのwhileに比べると1/4以下の処理速度となりました。




ループの処理速度は何をを使っても大差はありませんでした。

しかし、評価式に関数を入れるとループの回数分だけ実行されるため余計なオーバーヘッドがかかります。

よって、変数に退避させて評価式に含めるといった対策を心がけるようにしましょう。




今回は基礎構文のみに限定した計測となりましたが、改善の余地はまだまだありそうです。

実行するマシンスペックよっても処理速度は変わってくると思いますが、皆様も見直されてみてはいかがでしょうか?