PHPのRuby on Railsクローンのフレームワーク Akelos PHPをいじってみた出来事のメモ。

Akelosをいじってみるメモ帳

Akelos PHP Blogチュートリアル一覧(全18記事)
Akelos PHP ユーザ認証チュートリアル一覧(全19記事)

2008年09月05日

Blog screencast チュートリアルのコメント表示が出来ない問題

Akelos-jaのメーリングリストでも話題に出ていますが、Akelos公式サイトのBlogチュートリアルの動画(Screencast)でコメント表示の所の挙動が確かに謎。

今回私が書いたチュートリアルでは明示的にincludeを書いて先読み動作させていますが、果たしてこれで正しいの?

動画チュートリアルにあるように何も書かないで行けるパターンってあるんですかね?


「Akelos Blogチュートリアル 17.コメント機能を追加する 表示、反映の仕組みなど追加」より

続いて、読み出しの指定を書きます。show()アクションが書いてあるところを探してください。
下記のようになっているはずです。
-------------------------------------------------------
function show()
{
$this->post = $this->Post->find(@$this->params['id']);
}
-------------------------------------------------------
となっているところを

-------------------------------------------------------
function show()
{
$this->post = $this->Post->find(@$this->params['id'],array('include'=>'comment'));
}
-------------------------------------------------------
と書き換えてください。末尾のところがポイントです。何を取り込む(include)するかを指定します。

ラベル:雑記 akelos
posted by AMUAMU at 12:15| Comment(1) | TrackBack(3) | Akelos | このブログの読者になる | 更新情報をチェックする

2008年09月03日

Akelos Blogチュートリアル一覧(全18記事)

Akelos Blogチュートリアル一覧(全18記事)

1.はじめに
http://akelos.seesaa.net/article/100211099.html

2.初期のセットアップ script/setup
http://akelos.seesaa.net/article/100211283.html

3.httpd.confの修正(主にWindowsユーザのみ)
http://akelos.seesaa.net/article/100211451.html

4.いっかい確認
http://akelos.seesaa.net/article/100211960.html

5.DB設定 初期DBを作る
http://akelos.seesaa.net/article/100212219.html

6.設定の続き
http://akelos.seesaa.net/article/100212562.html

7.Blogコントローラ初期作成
http://akelos.seesaa.net/article/100212869.html

8.Postモデルを作る
http://akelos.seesaa.net/article/100213158.html

9.Postモデルのテーブル定義を書く
http://akelos.seesaa.net/article/100213366.html

10.マイグレーション migration
http://akelos.seesaa.net/article/100214297.html

11.色々自動生成 scaffold
http://akelos.seesaa.net/article/100214594.html

12.ルート設定、動作確認
http://akelos.seesaa.net/article/100214873.html

13.テーブル定義の修正 日付入力機能追加
http://akelos.seesaa.net/article/100215332.html

14.入力チェック機能の追加
http://akelos.seesaa.net/article/100215769.html

15.ビューの修正 sintags
http://akelos.seesaa.net/article/100216167.html

16.コメント機能を追加する テーブルの関連付け
http://akelos.seesaa.net/article/100216587.html

17.コメント機能を追加する 表示、反映の仕組みなど追加
http://akelos.seesaa.net/article/100217165.html

18.コメント機能を追加する 動作確認
http://akelos.seesaa.net/article/100217845.html


以下、ユーザ認証チュートリアルへ続く
posted by AMUAMU at 00:03| Comment(1) | TrackBack(0) | チュートリアル目次 | このブログの読者になる | 更新情報をチェックする

Akelos PHP ユーザ認証チュートリアル一覧(全19記事)

Akelos PHP ユーザ認証チュートリアル一覧(全19記事)

1.ユーザ認証機能を作るよ!
http://akelos.seesaa.net/article/105874461.html

2.Userモデルを作る。
http://akelos.seesaa.net/article/105874495.html

3.Userモデルをちゃんとする その1 属性設定
http://akelos.seesaa.net/article/105874534.html

4.Userモデルをちゃんと その2 validation
http://akelos.seesaa.net/article/105875522.html

5.Userモデルをちゃんと その3 beforeCreate/beforeUpdate
http://akelos.seesaa.net/article/105875619.html

6.Userモデルをちゃんと その4 その他関係するメソッド実装
http://akelos.seesaa.net/article/105875692.html

7.Userモデルの確認 完成したUserモデル
http://akelos.seesaa.net/article/105875728.html

8.Accountコントローラを作る 枠組み自動作成
http://akelos.seesaa.net/article/105875783.html

9.Accountコントローラの中身 認証確認 beforeFilter
http://akelos.seesaa.net/article/105895288.html

10.Accountコントローラ アクション実装1
http://akelos.seesaa.net/article/105900567.html

11.Accountコントローラ アクション実装2
http://akelos.seesaa.net/article/105900741.html

12.Accountコントローラ 管理者アクション実装
http://akelos.seesaa.net/article/105918009.html

13.ApplicationControllerの実装 共通処理
http://akelos.seesaa.net/article/105918346.html

14.メール処理の実装 ActionMailer その1 生成とモデル
http://akelos.seesaa.net/article/105918922.html

15.メール処理の実装 ActionMailer その2 コントローラとビュー
http://akelos.seesaa.net/article/105919353.html

16.routes.phpの編集 ルートの編集
http://akelos.seesaa.net/article/105919651.html

17.Viewの編集
http://akelos.seesaa.net/article/105920107.html

18.Account機能の動作テスト
http://akelos.seesaa.net/article/105920597.html

19.Blogチュートリアルにユーザ認証を組み込む
http://akelos.seesaa.net/article/105921873.html

posted by AMUAMU at 00:02| Comment(0) | TrackBack(0) | チュートリアル目次 | このブログの読者になる | 更新情報をチェックする

2008年09月02日

ということで・・・Akelosチュートリアル執筆完了

ということで、書こうと思ったチュートリアルの範囲を
全部書ききったぞーーーーー!!!

途中、仕事が忙しく中断したので2ヶ月強に渡っての執筆になっちゃいましたが、どうだろうなぁ、この内容。

間違ってるところとかありそうだけど、確認するつもりはない(ーー;

せっかくなので、どなたか、間違いなどの突っ込みや、感想をお待ちしております;

これ、ソースコード部分が見にくいんで、
そのうち整形してWikiとかに転記したいなぁと思いつつ
腰が重い、今日この頃
ラベル:雑記 akelos
posted by AMUAMU at 23:56| Comment(0) | TrackBack(0) | どうでもいいこと | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 19.Blogチュートリアルにユーザ認証を組み込む

やっと最終目的を達するための最後の実装です。

Accountコントローラが正常に動作したことを確認しましたら、以前作ったBlogチュートリアルにユーザ認証を組み込みます。
ユーザ認証チュートリアルの最初でこう書きました。確認してみます。

ということで、ユーザ認証を前回までに作ったBlogチュートリアルのサイトに組み込んでみようかと思う。
方向性としては、new Post、Edit、Deleteにユーザ制限を加え、ユーザ登録した人だけがこれらのアクションに触れるようにする。


でわ、これを実装します。

C:\xampp\htdocs\projects\blog\app\controllers\blog_controller.php
を開いて下さい。

Blogコントローラクラスの中に下記を追加します。

function __construct()
{
// beforeFilterで、自動的にApplicationControllerの_authpageメソッドを呼ぶように指定。
//認証済みユーザのみの制限をかけたいアクションを指定している。
$this->beforeFilter(array('_authpage'=>array('only'=>array('add','edit','destroy'))));
}


これで終わりです。

・・
・・・・・
・・・・・・・・・
そうです、これだけで終わりなんです。
とっても簡単。

なんて素晴らしい。
何て楽でしょう。
後の所には手を入れる必要ありません。

実際の動作を http://localhost/blog/ にアクセスして確認してみましょう。

どうですか?認証が掛かっていますか?
ログインしたら表示しますか?

このように一回ユーザー認証用の機能実装を行えば後は非常に簡単に機能を再利用して、簡単に認証ページ(認証の必要なアクションやコントローラ)が追加できます。


これでユーザ認証チュートリアルは終了しますが、いくつか修正すべき点があります。
これらは、ここまでのチュートリアルの内容の延長にあるので自力で試して解決してみるのが良いと思います。

以下に問題点やそのヒントを書きます。

・Account機能一覧ページと、Blogの記事一覧ページとの間の行き来が出来ない。
→view内の各種テンプレートを修正して、相互のリンクを追加しましょう。
・英語表記を日本語表記にしたい
→C:\xampp\htdocs\projects\blog\app\locales\account\ja.php のファイルを編集しましょう。
・アカウント修正したときにメールアドレス修正したらメール送信したらどうだろう?
→notifymailとaccount_controllerの修正で
・メールアドレスの存在確認とか欲しいよね
→存在確認用のテーブルとか必要かなぁー、ここまでの応用と routes.php 当たりの修正でいけますよ。たぶん
・折角アカウント登録しているのに、Blogの記事登録や修正時に認証した人のidが保存されていない。
→これはちょっと難しいかも。

気が向けば、上の何れかはチュートリアル書こうかなぁ

posted by AMUAMU at 23:06| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 18.Account機能の動作テスト

これで一通りのAccount機能が実装されました。
早速ブラウザで http://localhost/blog/account/ のように配置している場所を指定してアクセスしてみましょう。

最初のページはindexアクションで出来た機能一覧のページです。

この機能一覧のページに入った段階ではログインはしていません。
試しに modifyページ等に入ってみましょう。
入れないで、ログインフォームが表示されれば問題ありません。

何かしらエラーが出たら、コードにミスがあります。入力ミスが多いと思いますが、エラーの内容を見て、よく調べて修正しましょう。


でわ、実際の登録を New registページからしてみて、
さらに、ログインや、ログアウト、データ修正やアカウント削除(停止)などをしてみて動作確認しましょう。

ちなみに、Windows環境ではSMTPでのメール送信が出来ないのでメール送信エラーが出ると思います。
http://homepage2.nifty.com/spw/software/radish/
のようなWindowsローカルで動作する簡易SMTPサーバソフトをインストールしてテストをすれば、デバッグも楽です。
このRadishというソフトは、配送を停止したり、キューを確認したり、受信ログを表示出来たりするので、Windows環境でのメール送信に関するデバッグには最適なソフトなので、オススメ。
設定とかはRadishの説明を見て下さい。

最後に、管理者アカウントとしてuser.phpで指定したメールアドレスで登録をして、管理者しかみれないはずのuserlistなどを確認してください。

全てが動作し、エラー表示がされなければAccount機能はめでたく完成です。

posted by AMUAMU at 22:44| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 17.Viewの編集

さぁ、ラストスパートです。
コントローラの各アクションに対応したViewつまり、html生成部分を書きます。
scaffoldでAccountコントローラを作りましたので、listing、show、add、create、edit、destroyの各アクションに対応したViewはある程度、自動生成されています。
逆にそれ以外のアクションに関しては自分で書く必要がありますが、scaffoldが自動生成してくれた上記のアクションのコードを元にしていきながら、書いていきましょう。

Viewは下記のディレクトリに配置されています。
C:\xampp\htdocs\projects\blog\app\views\account\
ここには各アクションに対応したテンプレートがあります。

また、共通のレイアウトファイルとして
C:\xampp\htdocs\projects\blog\app\views\layouts\account.tpl
が作られています。

今回はレイアウトはいじりませんので、各アクションに対応したテンプレートのほうを修正します。


まず、 _form.tpl を開きます。
これはアクション毎のテンプレートから内部呼び出しされる、共通のフォームテンプレートです。

saltに対応した部分が中央にありますが、saltはモデル側で生成されるものなので必要ありません。
消しましょう。
変わりにパスワードの再入力枠を作る必要があります。
また、パスワード入力部分はパスワード型のフォームになおします。

これらを反映させた変更後の内容を、以下に示します。

<%= error_messages_for 'user' %>


<p>
<label for="user_name">_{Name}</label><br />
<%= input 'user', 'name' %>
</p>

<p>
<label for="user_passwd">_{Passwd}</label><br />
<%= password_field 'user', 'passwd' %>
</p>

<p>
<label for="user_passwd_confirmation">_{passwd confirmation}</label><br />
<%= password_field 'user', 'passwd_confirmation' %>
</p>

<p>
<label for="user_email">_{Email}</label><br />
<%= input 'user', 'email' %>
</p>

<p>
<label for="user_is_enable">_{Is enable}</label><br />
<%= input 'user', 'is_enable' %>
</p>

これは管理者用画面で使われますが、これをベースにコピペしていく形になると思います。

これを使うのはadd.tpl等です。add.tpl側は今回は修正ありませんが、呼び出しをしているところは見ておきましょう。

次に修正するのは delete.tpl です。
これは標準では生成してくれていませんので、中身はエラーになっています。
最初に書いてある内容は消して、自動生成してくれたdestroy.tplを参考に、内容を入れます。
下記に内容を示します。

<div id="sidebar">
<h1>_{Tasks}:</h1>
<ul>
<li><%= link_to _('Back to user index'), :action => 'index' %></li>
</ul>
</div>

<div id="content">
<h1>_{Users}</h1>

<p>_{Are you sure you want to delete this User?}</p>
<%= start_form_tag :action => 'delete' %>
<%= confirm_delete %>
</form>
</div>


続いて index.tpl です。
indexでは各機能へのリンクだけを取りあえず表示します。
下記に内容を示します。

<div id="sidebar">
<h1>_{Tasks}:</h1>
<ul>
<li><%= link_to _('Back to user index'), :action => 'index' %></li>
</ul>
</div>

<div id="content">
<h1>_{Account Page Index}</h1>

<p><%= link_to _('Login page'), :action =>'login' %></p>
<p><%= link_to _('New regist page'), :action =>'regist' %></p>
<p><%= link_to _('Remind password page'), :action =>'remind' %></p>
<p><%= link_to _('New regist page'), :action =>'regist' %></p>

<h1>_{Account Page Index}</h1>
<p><%= link_to _('Logout'), :action =>'logout' %></p>
<p><%= link_to _('Modify account profile'), :action =>'modify' %></p>
<p><%= link_to _('Delete account'), :action =>'delete' %></p>

<h1>_{Admin Page Index}</h1>
<p><%= link_to _('Userlist'), :action =>'listing' %></p>


</div>

ここではとりあえず、ログイン後じゃないと扱えないもの、管理者じゃないと扱えないものもリンクしています。
後で表示の制御を入れるか考えます。


続いてログイン用ページ login.tpl を開いてください。
IDとパスワードの入力枠を用意します。
下記に内容を示します。

<div id="sidebar">
<h1>_{Tasks}:</h1>
<ul>
<li><%= link_to _('Back to user index'), :action => 'index' %></li>
</ul>
</div>

<div id="content">
<h1>_{Users}</h1>

<p>_{Account Logout}</p>
<%= start_form_tag :action => 'login' %>
<p>
<label for="user_email">_{Email}</label><br />
<%= input 'user', 'email' %>
</p>
<p>
<label for="user_passwd">_{Passwd}</label><br />
<%= password_field 'user', 'passwd' %>
</p>
</form>
</div>



続いてログアウト用ページ logout.tpl を開いてください。
ここに来るときは既にログアウトしているはずですが、一応リンクを入れておきます。
下記に内容を示します。

<div id="sidebar">
<h1>_{Tasks}:</h1>
<ul>
<li><%= link_to _('Back to user index'), :action => 'index' %></li>
</ul>
</div>

<div id="content">
<h1>_{Users}</h1>

<p><%= link_to _('Logout'), :action =>'logout' %></p>
</form>
</div>


続いて、アカウント情報修正用ページ modify.tpl を開いてください。
下記に内容を示します。

<div id="sidebar">
<h1>_{Tasks}:</h1>
<ul>
<li><%= link_to _('Back to user index'), :action => 'index' %></li>
</ul>
</div>

<div id="content">
<h1>_{Users}</h1>

<%= start_form_tag :action => 'modify' %>

<div class="form">
<h2>_{Editing User}</h2>
<%= render :partial => 'form' %>
</div>

<div id="operations">
<%= save %> <%= cancel %>
</div>

</form>
</div>

ここでは最初に編集した_form.tplを利用しています。
このように定型的に使うフォームなどは再利用し、フォームの内容修正が統一的に行われるようにします。


次は、アカウント登録用ページ regist.tpl を開いてください。
下記に内容を示します。

<div id="sidebar">
<h1>_{Tasks}:</h1>
<ul>
<li><%= link_to _('Back to user index'), :action => 'index' %></li>
</ul>
</div>

<div id="content">
<h1>_{Users}</h1>

<%= start_form_tag :action => 'regist' %>

<div class="form">
<h2>_{User Profile}</h2>
<%= render :partial => 'form' %>
</div>

<div id="operations">
<%= save %> <%= cancel %>
</div>

</form>
</div>

ここも同じように_form.tplを使っています。
先ほど編集したmodify.tplとはメッセージが異なるだけです。
再利用が効いてるわけです。



次は、アカウント登録用ページ remind.tpl を開いてください。
下記に内容を示します。

<div id="sidebar">
<h1>_{Tasks}:</h1>
<ul>
<li><%= link_to _('Back to user index'), :action => 'index' %></li>
</ul>
</div>

<div id="content">
<h1>_{Users}</h1>

<%= start_form_tag :action => 'remind' %>

<div class="form">
<h2>_{User Profile Regist}</h2>
<p>
<label for="user_email">_{Email}</label><br />
<%= input 'user', 'email' %>
</p>
</div>

<div id="operations">
<%= save %> <%= cancel %>
</div>

</form>
</div>



最後に、アカウント登録後に表示するWelcomeページ welcome.tpl を開いてください。
下記に内容を示します。

<div id="sidebar">
<h1>_{Tasks}:</h1>
<ul>
<li><%= link_to _('Back to user index'), :action => 'index' %></li>
</ul>
</div>

<div id="content">
<h1>_{Users}</h1>

<h2>_{Thank you for regist!}</h2>
<p>
<%= link_to _('Back to user index'), :action => 'index' %>
</p>
</form>
</div>
posted by AMUAMU at 22:35| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 16.routes.phpの編集 ルートの編集

あと少しです。テストする前にAccount関係のコントローラが正常に動くようにURLのルートの設定をします。
実際、設定しなくてもある程度は大丈夫なのですが、index処理などが曖昧になるので設定した方が無難ってことで。
実際、複雑なことを今後しようと思ったらroutes.phpの編集は必須ですしね。

ということで、C:\xampp\htdocs\projects\blog\config\routes.php のファイルを開いてください。
以前書いた/blogの設定があると思います。

これを下記のようにしてください。


<?php

// You can find more about routes on /lib/AkRouters.php and /test/test_AkRouter.php

$Map->connect('/account/', array('controller' => 'account', 'action' => 'index'));
$Map->connect('/', array('controller' => 'blog', 'action' => 'listing'));
$Map->connect('/:controller/:action/:id', array('controller' => 'blog', 'action' => 'listing'));
?>

Mapを足しています。 /account/ として来た場合は、accountコントローラのindexアクションを実行しろと足しました。

ちなみにMapは上から順に優先的に評価されますので、上から順に個別の動作を書いていき、だんだん簡単なアドレスの設定を書いていって、最後にマルチエイリアスとして広く動作するもの書く必要があります。
もし、これの書く順序が逆ですと、 /account/ としてリクエストが来た場合、action指定が無いわけですから、'/'の時の設定が優先され、accountコントローラのlistingアクションが実行されてしまうのです。
省略アドレス時は、先に書いてあるもので一致するものを取り出す仕組みなので。

posted by AMUAMU at 22:27| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 15.メール処理の実装 ActionMailer その2 コントローラとビュー

続いて、メール送信の実際の呼び出しをAccountコントローラに追加します。

下記のファイルを開き編集します。
C:\xampp\htdocs\projects\blog\app\controllers\account_controller.php

追記するアクションはregistアクションとremindアクションです。
各アクションでコメントで後で実装としていたメール部分を下記のようにします。

registアクション内

Ak::import_mailer('notifymail');
$m = new Notifymail();
$m->deliver('regist',$this->User);


remindアクション内

Ak::import_mailer('notifymail');
$m = new Notifymail();
$m->deliver('remindpassword',$u);


import_mailerで使うモデルを指定し、deliverメソッドで呼び出しています。
deliverメソッドの最初の引数はアクション名、2つめ引数はテンプレートに展開する配列です。ここではユーザモデルをそのまま投入しています。

これでコントローラ側の実装は終了です。


続いて、実際のメール本文を修正します。
アクション名と同じ名前のtplファイルがviews\notifymail以下のディレクトリにあります。

まずは、regist時のメールを編集します。下記のファイルを開いてください。
C:\xampp\htdocs\projects\blog\app\views\notifymail\regist.tpl
元々入っているメッセージは必要ありませんので削除して、下記のようにします。

{User.name} 様

ご登録ありがとうございました。
以下の内容で登録が完了しましたのでご連絡いたします。

お名前:{User.name}

パスワード:{User.passwd_confirmation}

ご登録メールアドレス: {User.email}

==========================
サンプルサイト
example@sample.com
==========================


同様に、remindpassword時のメールを編集します。下記のファイルを開いて編集してください。
C:\xampp\htdocs\projects\blog\app\views\notifymail\remindpassword.tpl

{User.name} 様

パスワードを再発行しました。

パスワード:{User.passwd_confirmation}


==========================
サンプルサイト
example@sample.com
==========================


{}に囲まれているところはbody変数に入れた配列のうち、展開する変数を指定しています。
{}内が書き換えられて送信されます。
パスワード表記の所が、passwd_confirmationを指定しているのは、passwd自体は暗号化されているためです。passwd_confirmationは入力したときしか設定されていませんので、安全にメール内に入れることが可能になっています。

以上で、メール送信に関する処理、ActionMailer周りの実装は終了です。
posted by AMUAMU at 22:21| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 14.メール処理の実装 ActionMailer その1 生成とモデル

Akelos 0.8のダウンロードパッケージには含まれていませんが、svnの最新パッケージを取得すれば、ActionMailer(AkActionMailer)が使えるようになりました。
これで簡単にメール送信のプログラムが作れます。

ActionMailerのインストール方法ですが
http://trac.akelos.org/browser/trunk/

このページからダウンロードして C:\xampp\htdocs\akelos\lib\ に上書きで展開しましょう。。
ダウンロードは画面の一番下の「Download in other formats:Zip Archive」というところから一括ダウンロードできます。

準備が出来たら、メール送信の雛形を作ります。
コマンドラインで以下を入力して実行してください。

C:\xampp\htdocs\projects\blog>c:\xampp\php\php.exe script\generate mailer Notifymail regist remindpassword --sintags --force


generateスクリプトの指定方法は、mailerと指定している以外は、今までと同じ感じですね。
2番目にMailerの名前を指定。
3番目以降に作りたいアクションを書く感じです。

これで関係するファイルが作られます。

なお、8/12現在のものはバグがあり、View用のテンプレートが間違ったディレクトリに作られます。
もし C:\xampp\htdocs\projects\blog\app\views\notifymail\ のディレクトリ内が空の場合は、C:\xampp\htdocs\projects\blog\app\views\app\views\notifymail\ のディレクトリに作られていますので、後者から前者にファイルを移動してください。


続いて、実際のメール送信の処理を書きます。
下記のファイルを開いてください。
C:\xampp\htdocs\projects\blog\app\models\notifymail.php

デフォルトの内容で、registとremindpasswordのアクション内容が入っています。
これを下記のように書き換えます。


<?php

class Notifymail extends AkActionMailer
{

function regist($User)
{
$this->setCharset('ISO-2022-JP');
$this->setRecipients($User->email);
$this->setSubject("[Notifymail] 登録のご案内");
$this->setFrom('master@example.com');
$this->setBody(array( 'User'=> $User ));
$this->log($this->Message);
}


function remindpassword($User)
{
$this->setCharset('ISO-2022-JP');
$this->setRecipients($User->email);
$this->setSubject("[Notifymail] パスワード再発行のご案内");
$this->setFrom('master@example.com');
$this->setBody(array( 'User'=> $User ));

}

}

?>


非常にシンプルですね。
予め用意されている各種メール用のプロパティに必要な情報を与えていくだけです。

最初のsetCharsetは、日本語メールの場合は必須です。
設定しないと標準のUTF-8とかになりますが、文字化けとかおきますので注意。

setRecipients は送信先アドレス。
setSubjetct はメールの題名(タイトル)
setFrom は送信元アドレス
setBody は本文ですが、ここでは引数で渡されてきたUserクラスをそのまま渡しています。Userクラスの各配列がテンプレート内に展開されるようになっています。
posted by AMUAMU at 22:12| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 13.ApplicationControllerの実装 共通処理

ユーザ認証に関する実際の処理は、色々なコントローラから呼び出される可能性があります。
そこで、どのコントローラから呼び出されても良いように共通のコントローラである「ApplicationController」に実装します。
こうすることで、個別のコントローラは必要な時に必要な処理だけを書けば良いという寸法です。
この便利さは、半端ないのですが、実際には最後のほうで分かると思います。

下記のファイルを開いてください。共通というだけあって、今までのディレクトリより一つ上の階層にありますんで注意。
C:\xampp\htdocs\projects\blog\app\application_controller.php

まず、AccountコントローラのbeforeActionで呼び出す相手となっていた_authpageメソッドを実装しましょう。
以下のコードを加えます。

//各コントローラのbeforeAction登録で呼び出される関数
function _authpage()
{
//セッション情報に有効なデータが入っていれば認証済み
if(!empty($_SESSION['user'])) return true;

//以下ログインしていない場合の処理
$this->flash['notice'] = $this->t('This page needs login.');
//リクエストオブジェクトにあるURIを保存
$_SESSION['return_page'] = $this->Request->env['REQUEST_URI'];
//Userコントローラのログインアクションに移動
$this->redirectTo(array('controller'=>'account','action' => 'login'));
//beforeFilterの処理を進めさせない為、falseを返す
return false;
}

ここでは認証済みかどうかをセッション変数が空かどうかで判断しています。
ログインしていない場合は、今リクエストされた内容をセッションに保存し、Accountコントローラのログインアクションに遷移させています。アプリケーションコントローラは、どのコントローラから呼ばれたか分かりません。よって、redirectToメソッドでは、コントローラも指定していることに注意です。

また、beforeFilterで呼ばれた場合のルールですが、returnでtrue/falseを返す必要があります。
true = そのまま処理を続ける
false = 処理を中断する
これをしないといけません。要注意です。


続いて、同じくAccountコントローラで書かれていたredirectToStoredPageメソッドを足します。
このメソッドは、ログイン完了後、保存してあったアドレスに戻る処理でしたね。
実際、Accountコントローラに記述しても良いのですが、前述の_authpageメソッドで保存先を書いている関係上、同じ並びに書くのが筋です。以下のコードを加えて下さい。

//ログイン後、保存してあったページに戻る関数
function redirectToStoredPage()
{
//念のためログイン済みか確認
if(empty($_SESSION['user'])){
$this->redirectTo(array('controller'=>'account','action' => 'login'));
}else{
if(!empty($_SESSION['return_page'])){
//戻るページの情報を書き戻す
$return_page = $_SESSION['return_page'];
$_SESSION['return_page'] = false;
//保存してあるURIを与えてrecirectToする
$this->redirectTo($return_page);
}else{
//戻るページの指定が無く、単にログインしただけなのでユーザインデックスに戻る
$this->redirectTo(array('controller'=>'account','action'=>'index'));
}
}
}

内容はいたってシンプルです。
細かい処理の流れはコードを見ていただくとして、注目するべきは$this->redirectTo($return_page);でしょうか。redirectToメソッドは結構賢くて、通常は、ここまで出たように配列で飛び先を指定しますが、今回のようにURIアドレスを与えるだけでも解析して飛んでくれます。

最後に、以下のコードを加えます。

//現在のログインユーザの情報(オブジェクト)を返す関数
function currentUser()
{
//View(helper)においてログイン済みかどうかの判断などに使う
return unserialize($_SESSION['user']);
}

コメントにも書いてあるようにこれは、View用の処理です。詳しくはそのうちViewのところの追加説明で使いますので、今はこんなもんってことで。
posted by AMUAMU at 22:00| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 12.Accountコントローラ 管理者アクション実装

続いて管理者向けの各アクションの実装をします。
これはscaffoldが自動で作ってくれたコードがかなり使えますが、重要なのは管理者権限を持っているかの確認です。ApplicationControllerに実際の管理者権限確認は入れるため、こっちではちょっとだけコードを足すだけです。

管理者向けのアクションlisting、show、add、edit、destroyそれぞれのメソッドの最初に以下のコードを加えます。

//ユーザ情報を書き戻す
$u = unserialize($_SESSION['user']);
//管理者か確認
if(!empty($_SESSION['user']) && empty($u->is_admin)){
$this->redirectTo(array('action'=>'login'));
return;
}


合計5回コピー&ペーストすれば終わりですね、簡単すぎる。scaffoldすばらしー。
ちなみに同じコードが複数出るので、個別の内部関数にすべきかもしれませんが、まぁ今回はめんどくさいので、このままで。


以上で、Accountコントローラの実装は終了です。

念のため追記にコードを全部再掲します。
確認したい人はどうぞ確認用に全部のコードを見る
posted by AMUAMU at 21:54| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 11.Accountコントローラ アクション実装2

アクション実装の続きです

ユーザ登録削除 deleteアクション
削除は、実際にはデータを消すわけではなくis_enableフラグをfalseに設定し、無効なユーザとしています。実際のコードを示します。
function delete()
{
//ユーザ情報を書き戻す
$u = unserialize($_SESSION['user']);

if(!empty($u->id) && $this->Request->isPost()){
//is_enableフラグをfalseで上書き
$this->user = $this->User->find($u->id);

if($this->user->updateAttribute('is_enable',false)){
$this->flash['notice'] = $this->t('deleted user account');
$this->redirectTo(array('action' => 'index'));
}
}

}

ここではupdateAttributeメソッドにより上書きを指示しています。
似た名前のものとして、 updateAttributesというのもあるので注意です。
どっちも機能は基本手kに同じですが、updateAttributesは複数を、updateAttributeはひとつだけを修正する場合に利用します。
どちらも、呼び出すと上書きとsaveを自動でしてくれます。(内部的には setAttributeして、そのあとsave()しているだけです)

updateAttributeメソッドは、
updateAttribute( '修正したい属性名', '上書きする値','validateによるチェックをするかどうか')
という呼び出しになります。3つめのvalidateチェックのフラグは省略可能です。標準でtrue。つまり確認します。


ユーザ登録情報修正 modifyアクション
登録情報修正は、editアクションに作られたものが流用出来そうですが、修正をユーザに委ねる関係上、結構異なりますので注意。具体的にはid情報を引き回さなくてもSESSIONから取り出しています。
ですが、書き換えを行う時には一回findで取り出す必要がありますので注意。
以下にコードを示します。
//ユーザ登録情報修正
function modify()
{
//ユーザ情報を書き戻す
$u = unserialize($_SESSION['user']);

if(!empty($u->id) && !empty($this->params['user'])){
$this->user =& $this->User->find($u->id);
}else{
$this->user = $u;
$this->user->set('passwd','');
}
//入力された情報で更新を行う
if(!empty($this->params['user'])){
$this->user->setAttributes($this->params['user']);
if($this->Request->isPost() && $this->user->save() ){
$_SESSION['user'] = serialize($this->user);
$this->flash['notice'] = $this->t('updated user profile');
$this->redirectTo(array('action' => 'modify'));
}
}
}

ここではsetAttributesとsaveを別々に利用しています(updateAttributesではなく)。
$this->params['user']にはWebの画面からPOSTされてきたデータが入っています。
その配列データをそのまま読み込ませています。
細かく xxx = yyyy とか書かなくて良いのは楽ですね。
ただし、データの扱い方に心配な時や、入力チェックをここで追加で行う必要があれば、個別展開も考えましょう。validateのほうできちんと処理を書いていれば心配はないですけどね。

setAttributesメソッドはそのまま引数に配列を入れるだけです。
第二引数をつかってオブジェクト指定のupdateとかも出来ますが、複雑なので通常は使わないほうがいいでしょう。

ちなみに、save時に強制的にvalidateされます。要注意。



パスワード忘れ時のパスワード再発行 remindアクション
//パスワード忘れのパスワード再送
function remind ()
{
//セッションを念のため破棄(ユーザ情報不一致が発生するため)
$_SESSION['user'] = false;
if($this->Request->isPost()) {
//ユーザモデルクラスを新たに作る
$u = new User();
//emailアドレスが一致するユーザの情報を探し、Userクラス$uに入れる
$u = & $u->findFirstBy('email AND is_enable', $this->params['user']['email'],true);

//一致するメールアドレスが見つかったかどうかを判断
if( !empty($u->email) ) {
//ユーザモデルに新しいパスワードの発行と更新を依頼
$new_passwd = $u->new_password();

////ここに後でメール処理を追記予定
////詳細はメール機能のところで

$this->flash['notice'] = $this->t('succeeded in the email send of new password.');
$this->redirectTo(array('action'=>'login'));
}else{
$this->flash['notice'] = $this->t('Error! Sorry,plese retry email remind...');
$this->redirectTo(array('action'=>'remind'));
}


}
}

ちょっと長いですね。forgot_passwordメソッドとか長い名前がついているサンプルも多いですが、ここではremindとしています。
ログイン出来ない状態なので、$uにUserモデルを新しく作り、その上で入力されたアドレスから、登録メールアドレスを探す処理をfindFirstByメソッドで行っています。
パスワードの作成ルールはモデルで定義されているので、$u->new_password()で発行し、新しいパスワードを受け取っています。
その後、メールの送信処理を入れるんですが、ここでは入れず、あとでmailerを作ったときに足します。

以上でユーザ向けコントローラの処理は実装終了です。
posted by AMUAMU at 15:57| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 10.Accountコントローラ アクション実装1

続いてユーザ向けの各アクションの実装をします。

個別のアクション毎に掲出しますが、全てを前述の__constractメソッドの後ろにいれる形になります。

ただし、welcomeだけは中身が必要ありません。
welcomeアクションはbeforeFilterで認証済みユーザのみが入りますが、ここでは各アクションへのリンクを出すだけのページを想定しています。つまりViewだけがあれば良いということですでコントローラはいじりません。
よって、welecomeは追記はありませんので、標準のままです。

その他は色々実装が必要です。アクション別に書いていきます。

機能一覧ページ indexアクション
indexアクションはscaffoldによってlistingへのリダイレクトが書かれています。$this->performAction()または$this->redirectToAction()などが書かれている部分を消します。
そして、セッション情報の書き戻しを加えます。これはユーザ名などをindexページで表示する際に将来必要となるものです。
下記に内容を示します。

function index()
{
// 今回はindexアクションを使うのでリダイレクト無し。よってコメントアウト
// $this->performAction('listing')
$_SESSION['return_page'] ='';

//ユーザ情報を書き戻す
$u = empty($_SESSION['user']) ? false : unserialize($_SESSION['user']);
if(!empty($u)){
$this->user =& $u;
}
}



ユーザ登録 registアクション
ここはscaffoldが作ってくれたaddアクションをコピー&ペーストすると楽です。
addアクションは認証の事を考えていませんし、ユーザ自身が登録するregistアクションの場合、いくつか修正が必要ですので注意してください。以下にコードを示します。

//登録アクション
function regist()
{
//scaffoldが作ったaddアクションからコピー&ペーストで楽に
if(!empty($this->params['user'])){
$this->User->setAttributes($this->params['user']);
if ($this->Request->isPost() && $this->User->save()){
//ここまでは標準状態のaddアクションと同じ。以下、regist用

////ここにはメールの送信処理を後でいれます
///詳細はメール機能のところで

//保存が成功した場合、認証をかける
//さらにセッションにUserモデルクラスをシリアライズして保存
//ログイン状態の維持を行う。

$_SESSION['user'] = serialize($this->User->auth($this->User->email,$this->User->passwd_confirmation));
$this->flash['notice'] = $this->t('account regist success!');
//welcomeメッセージに移動する。

$this->redirectTo(array('action' => 'welcome'));
}else{
//エラーメッセージを足しておきましょう
$this->flash['notice'] = $this->t('Error!! sorry not registed.');
}
}
}

新しいことはありません。ほとんど、ここまでの復習ですね。
細かい流れ、説明はコード中のコメントを参照してください。

少々分かりにくいところは$_SESSIONへの保存ですが、ここではその前に保存したものに対して確認の意味やモデル内のデータをセットしてもらうために、Userモデルのauthを呼んでいます。
authは、成功すればUserモデルのオブジェクト自体を返しますので中身が入ります。失敗すればfalseが入ります。
このように実際の処理はモデルに投げることでコントローラはシンプルになっています。


ユーザログイン loginアクション
ここは全く新しく書きます。以下にコードを示します。

//ログインアクション
function login()
{
if($this->Request->isPost()) {
//ログイン処理を行う。
//認証をかけて、さらにセッションに保存を行う。
$u = $this->User->auth($this->params['user']['email'] , $this->params['user']['passwd']);
if(!empty($u))
{
$_SESSION['user'] = serialize($u);
$this->flash['notice'] = $this->t('login is success');
//保存してあるログイン前の画面に戻るため
//ApplicationControllerのredirectToStoredPage関数に飛ぶ
$this->redirectToStoredPage();
} else {
$_SESSION['user'] = '';
$this->flash['notice'] = $this->t('login failed');
$this->redirectTo(array('action' => 'login'));
}
}
}

ここも同じような処理です。
redirectToStoredPage()メソッドについては、後述のApplicationControllerのところで説明します。


ユーザログアウト logoutアクション
ここも短いですが全く新しいです。コードを示します。

//ログアウトアクション
function logout ()
{
//セッションの情報を破棄
$_SESSION['user'] = false;
$this->flash['notice'] = $this->t('success logout');
//ログイン画面に移動
$this->redirectTo(array('action' => 'login'));
}

シンプルにセッションに保存されているユーザ情報を破棄し、ログイン画面に遷移させています。

続きは次で
posted by AMUAMU at 15:54| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 9.Accountコントローラの中身 認証確認 beforeFilter

まず最初に、ログインな必要なページの場合、認証済みか確認する処理を加えます。
これにはbeforeFilterという機能を使います。

beforeFilterを使う事で、ページが生成される前に特定の処理をさせることが可能です。
ここでは認証の有無確認をするようにします。
さらにアクション毎に認証済みであることが必要かどうかも、一気に設定できちゃいます。

でわ、その中身としてaccount_controller.phpのAccountControllerクラス内に下記を加えます。

function __construct()
{
// beforeFilterで、自動的にApplicationControllerの_authpageメソッドを呼ぶように指定。
//ただし、delete,logout,editのみが呼び出し対象として指定
$this->beforeFilter(array('_authpage'=>array('only'=>array('delete','logout','modify','add','listing','show','edit','destroy'))));
}


まず、Filter類はクラスの実体化時に呼び出す __construct() メソッド内で設定します。
コメントが入っていますが、実体は一行、というか$this-beforeFilter()メソッドを呼んでいるだけですです。
beforeFilterが指定するのは、ユーザが定義したメソッド(関数)です。
$this->beforeFilter('呼び出す関数名');
で指定できます。これがシンプルな形です。
これによりAccountコントローラが動作する際に必ず呼ばれるようになります。

ここではさらに少々複雑にフィルター条件をつけています。
つまり指定した条件で、特定のアクションのみ、Filterを発動しろと設定しているのです。

$this->beforeFilter(
  array('呼び出す関数名' =>
   array('呼び出す条件'=>
    array('アクション名1','アクション名2',....)
   )
   )
 )

という構造になっています。
呼び出す条件は only または except が指定できます。
only = 指定しているアクションでのみ有効有効にする
except = 指定しているアクション以外で有効にする

ということで、コードに戻ってみますと
呼び出す関数名 _authpage
呼び出す条件 only つまり指定したアクションで有効にする
指定しているアクション 'delete','logout',.....

となっているわけです。

今回は _authpage 関数はアカウントコントローラの中に入れませんでした。
後述するApplicationControllerに入れています。
この理由もApplicationControllerの修正時に説明しますので、とりあえずこの状態で、次へ・・・。
posted by AMUAMU at 13:26| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 8.Accountコントローラを作る 枠組み自動作成

ユーザモデル続いて、ユーザ登録やログインなどを行うユーザ向けの機能を司るAccountコントローラを作ります。

コマンドラインで以下を入力して実行してください。
C:\xampp\htdocs\projects\blog>c:\xampp\php\php.exe script\generate scaffold User Account regist login logout modify delete remind welcome --sintags --force


後半にアクション(とビュー)の名前を複数指定しています。
このように、アクションがある程度想定して、まとめて作るとある程度自動的に作ってくれるので楽です。もちろん、後で足すことも出来ますが。

アクション名を並べたのは良いですが、もちろん実体はありません。
ということで、それぞれのアクションを下記のように定義し、実体を作りたいと思います。

index = ユーザ向け機能へのリンクページ ログイン必要無し
regist = ユーザ登録 ログイン必要無し
login = ログイン ログイン必要無し
logout = ログアウト ログイン要必要
modify = ユーザ登録情報修正 ログイン要必要
delete = ユーザ登録削除 ログイン要必要
remind = パスワード忘れ時の再発行 ログイン必要無し
welcome = 登録後に表示する画面 ログイン要必要
add = ユーザ追加 管理者用
listing = ユーザ一覧 管理者用
show = ユーザ確認 管理者用
edit = ユーザ登録情報修正 管理者用
destroy = ユーザ削除 管理者用


まず、下記のファイルを開き各アクションが存在することを確認しましょう
C:\xampp\htdocs\projects\blog\app\controllers\account_controller.php

scaffoldが追加指定したアクション+標準で自動で作ってくれる index,listing,show,add,edit,destroyのアクションがあります。

アクションが多いですが、この中を埋めていきたいと思います。
posted by AMUAMU at 03:59| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 7.Userモデルの確認 完成したUserモデル

ということで、Userモデルが完成しました。念のため、コードの全体を出します。
本当は、ここでテストとかするのかなぁー・・・。まぁ、今回は割愛w


<?php

class User extends ActiveRecord
{
//クラス内の共通暗号化キーです
var $_my_common_salt = 'my_common_pass';

//管理者かどうかのフラグです。
var $is_admin = false;

//管理者として設定する人のメールアドレス
var $_admin_email = array("hoge@sample.com","amuamu@sample.com");

//クラス生成時の処理
function User()
{
// Railsで言うattr_accessorの設定
// DBのテーブルに無い属性を仮想的に作る場合に使います。
// 確認画面などに表示させ、入力させたいフィールドを足すのに必要なものをここでは指定
$this->set('passwd_confirmation');
// Railsで言うattr_protectedの設定
// ユーザが修正出来ないように保護するものを指定
$this->setProtectedAttributes(array('id','salt'));
//親のコンストラクタを呼びます おまじない
parent::__construct(func_get_args());

}

//入力内容のチェック
function validate()
{

//emailはユニークか?
$this->validatesUniquenessOf('email', array('notice'=>$this->t('email address registed!')));

//新しく作るときだけのチェック項目
if($this->isNewRecord()) {

//パスワードと、パスワード確認枠には入力があるか?
$this->validatesPresenceOf(array('passwd','passwd_confirmation'));

//チェックボックスの確認
$this->validatesInclusionOf('is_enable', array('1') ,$this->t('Please check checkbox of confirmation'));
}

//新しく作るとき または 修正時でかつパスワード修正がある場合のみのチェック
if($this->isNewRecord() || !empty($this->passwd))
{
//パスワードの長さチェック
$this->validatesLengthOf('passwd', array('in'=>array(5, 40), 'too_long' => $this->t('password too long.'), 'too_short' => $this->t('password too short')));

//パスワード確認の為の再入力枠とパスワードの内容が一致しているか
$this->validatesConfirmationOf('passwd', $this->t('not confirmation password'));

}

//emailとnameの空入力チェック
$this->validatesPresenceOf(array('email','name'));

//emailアドレスが有効なアドレスか?
$this->validatesFormatOf('email', AK_EMAIL_REGULAR_EXPRESSION, $this->t('error email address.')) ;


}

//データが新規保存される前に呼び出される callback methodです。
//中でパスワードとsaltをセットしています。
function beforeCreate()
{
//パスワードの暗号化関数を呼び出す
$this->encryptPassword();

return true;
}

//データが修正保存される前に呼び出されるcallback methodです。
function beforeUpdate()
{
//パスワードの暗号化関数を呼び出す
$this->_encryptPasswordUnlessEmptyOrUnchanged();
return true;
}

//新しいパスワードを自動生成してセット、保存する関数
//返値には新しいパスワード文(平文)が返される。
function new_password()
{
//新しいパスワードを自動生成(ランダム)8文字の文字列
$new_pass = Ak::randomString(8);

//新しいpassをセット パスワードは平文のまま
$this->set('passwd',$new_pass);

//こっちもセットしないとvalidateで蹴られるんです
$this->set('passwd_confirmation',$new_pass);

//修正した内容で保存。
//なおこの後、beforeUpdateが呼ばれて、平文は暗号化される
if($this->save()) //保存が成功したら新しいパスを返す
return $new_pass;
else
return false;
}

//認証確認用関数
function auth($email,$pass)
{

//emailが一致する行を取り出す、成功すればこのモデルにも反映される
$u =& $this->findFirstBy('is_enable AND email' ,'1',$email);

//見つからなければ$uはfalseが入る。
if(empty($u)) return false;

//見つかった行のパスワードと、入力されたパスワードの一致確認
//保存されているsaltで暗号化してみて、取り出した行と比較
if($this->_myEncrypt($pass,$u->salt) == $u->passwd){

//管理者権限確認と、フラグを立てる
if( array_search($email,$u->_admin_email) !== FALSE ){
$u->is_admin = true;
}else{
$u->is_admin = false;
}

$result = $u;
} else {
$result = false;
}
return $result;
}


//パスワードが修正されている場合だけ暗号化保存をする関数です。
function _encryptPasswordUnlessEmptyOrUnchanged() {
//修正対象のIDの保存されているデータ(つまり旧データ)を呼び出す。
$u =& $this->find($this->id);

//ユーザからのリクエストのpasswdを確認する
switch($this->get('passwd')) {
case '': //空の場合は、保存されてるデータを入れる
$this->set('passwd',$u->passwd);
break;
case $u->passwd: //同じパスワードならばそのまま。
break;
default: //その他の場合はパスワードの修正
$this->encryptPassword();
break;
}

return true;
}


//パスワードを暗号化する関数です。
function encryptPassword()
{
//saltをセットします。
// Akクラスには便利な関数がいくつかあります。
// Ak::randomString() はランダム文字列を得ることが出来ます。
$my_salt = Ak::randomString(8);
$this->set('salt',$my_salt);

//passwdをセットします。
// encryptPassword関数に渡して暗号化してもらいます。
$this->set('passwd', $this->_myEncrypt($this->get('passwd'),$my_salt));
}

//暗号化関数です。
function _myEncrypt($pass,$salt)
{
//sha1で文字列を暗号化しています。
//暗号化文字列は関数引数のsalt+クラス内の固定saltを足しています
return sha1($pass . $this->_my_common_salt . $salt);
}
}
?>

こんな感じで、次号はコントローラへ・・・
posted by AMUAMU at 03:56| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 6.Userモデルをちゃんと その4 その他関係するメソッド実装

本来、モデルには細かい挙動を実装すべきではないですが、ログインするときに認証する方法と、パスワードをユーザが紛失したときに再発行する仕組みは必要となります。

複雑なシステムの場合は、ここらへんの仕組みは別の認証用クラスとかにまとめる場合もありますが、今回は取りあえずUserモデルに入れてしまいます。

モデルでしか基本的に知らないこと、もしくはモデル以外には教えたくない事を書いています。ここでは、パスワードの暗号化に関する部分を秘匿したい(共通化したい)ので入れます。

下記のようなコードをさらに、クラス内に足して下さい。

//新しいパスワードを自動生成してセット、保存する関数
//返値には新しいパスワード文(平文)が返される。
function new_password()
{
//新しいパスワードを自動生成(ランダム)8文字の文字列
$new_pass = Ak::randomString(8);

//新しいpassをセット パスワードは平文のまま
$this->set('passwd',$new_pass);

//こっちもセットしないとvalidateで蹴られるんです
$this->set('passwd_confirmation',$new_pass);

//修正した内容で保存。
//なおこの後、beforeUpdateが呼ばれて、平文は暗号化される
if($this->save()) //保存が成功したら新しいパスを返す
return $new_pass;
else
return false;
}

//認証確認用関数
function auth($email,$pass)
{

//emailが一致する行を取り出す、成功すればこのモデルにも反映される
$u =& $this->findFirstBy('is_enable AND email' ,'1',@$email);

//見つからなければ$uはfalseが入る。
if(empty($u)) return false;

//見つかった行のパスワードと、入力されたパスワードの一致確認
//保存されているsaltで暗号化してみて、取り出した行と比較
if($this->_myEncrypt($pass,$u->salt) == $u->passwd){

//管理者権限確認と、フラグを立てる
if( array_search($email,$u->_admin_email) !== FALSE ){
$u->is_admin = true;
}else{
$u->is_admin = false;
}

$result = $u;
} else {
$result = false;
}
return $result;
}

これらの関数は、モデルを使うコントローラ側から呼び出される事が想定しています。

よく使うもので新しいメソッドはfindFirstBy()でしょうか。
ルールを指定して、データをDBから探してきてくれます。
emailと指定しているものは、$email変数との一致を見るクエリに自動的に代入されます。あわせてANDでis_enable はtrueであるかどうかを確認させています。
ちなみに@$emailという表現は、関数実行のエラー表示抑制をしてくれるものです。おまじないみたいなもんだと思って下さい。あまりこの@演算子は説明が無いようですが・・・

管理者権限は配列をなめて(array_search)、一致する場合のみadminフラグを立てる単純な処理です。
レベル管理するように改変する場合はここら辺が修正しどころですね。
posted by AMUAMU at 03:52| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 5.Userモデルをちゃんと その3 beforeCreate/beforeUpdate

続いてパスワードを保存する時に暗号化する処理です。
いくつかのところで実装する方法があるのですが、今回はbeforeCreate()とbeforeUpdate()を使ってみます。
※Rubyなら演算子の再定義(オーバーロード)が、一番スマートなんだろうけどPHPは出来ないんですよねー

ということで、下記のようなコードをvalidateメソッドの後ろに足します。


//データが新規保存される前に呼び出される callback methodです。
//中でパスワードとsaltをセットしています。
function beforeCreate()
{
//パスワードの暗号化関数を呼び出す
$this->encryptPassword();

return true;
}

//データが修正保存される前に呼び出されるcallback methodです。
function beforeUpdate()
{
//パスワードの暗号化関数を呼び出す
$this->_encryptPasswordUnlessEmptyOrUnchanged();
return true;
}


encryptPassword()関数と、_encryptPasswordUnlessEmptyOrUnchanged()関数は後で説明します。

とりあえず、beforeCreateとbeforeUpdateについて。これらはActiveRecordに組み込まれているコールバックメソッドです。コールバックメソッドとは、特定のタイミング(トリガー)で自動的に呼び出される場所のことを言います。フックとか、イベントとかって表現をしているフレームワークもありますね。まぁ、どれも似たようなもんです。

ここで指定している2つは以下の意味があります。
beforeCreate 新しいレコードを保存する前に呼び出される
beforeUpdate レコードを更新・修正する前に呼び出される
です。

これらの前にvalidateもコールバックメソッドとして呼び出されています。
これらの呼び出し順は、決まっていて、その他にもいくつかメソッドがあるんですが、それぞれの説明は今回は割愛
function beforeCreate()
function beforeValidation()
function beforeValidationOnCreate()
function beforeValidationOnUpdate()
function beforeSave()
function beforeUpdate()
function afterUpdate()
function afterValidation()
function afterValidationOnCreate()
function afterValidationOnUpdate()
function afterCreate()
function afterDestroy()
function beforeDestroy()
function afterSave()
とりあえず、こんな種類があると思って下さい。意味は名前でだいたいわかるかと思います。

ひとつ、これらのコールバックでは return true; で返して下さい。returnを返さない or return false;は処理が中断する場合があります。逆に内容によって処理を中断したい場合もあるでしょうけど。

さて、話は戻って、beforeCreateとbeforeUpdateの中は、それぞれ別のユーザ定義のメソッドを呼んでいるだけです。それぞれのメソッドをさらに書き加える必要があります。

下記のようなコードをさらに、クラス内に足して下さい。


//パスワードが修正されている場合だけ暗号化保存をする関数です。
function _encryptPasswordUnlessEmptyOrUnchanged() {
//修正対象のIDの保存されているデータ(つまり旧データ)を呼び出す。
$u =& $this->find($this->id);

//ユーザからのリクエストのpasswdを確認する
switch($this->get('passwd')) {
case '': //空の場合は、保存されてるデータを入れる
$this->set('passwd',$u->passwd);
break;
case $u->passwd: //同じパスワードならばそのまま。
break;
default: //その他の場合はパスワードの修正
$this->encryptPassword();
break;
}

return true;
}


//パスワードを暗号化する関数です。
function encryptPassword()
{
//saltをセットします。
// Akクラスには便利な関数がいくつかあります。
// Ak::randomString() はランダム文字列を得ることが出来ます。
$my_salt = Ak::randomString(8);
$this->set('salt',$my_salt);

//passwdをセットします。
// encryptPassword関数に渡して暗号化してもらいます。
$this->set('passwd', $this->_myEncrypt($this->get('passwd'),$my_salt));
}

//暗号化関数です。
function _myEncrypt($pass,$salt)
{
//sha1で文字列を暗号化しています。
//暗号化文字列は関数引数のsalt+クラス内の固定saltを足しています
return sha1($pass . $this->_my_common_salt . $salt);
}

それぞれの細かい処理はコード内のコメントを参照してください。

よく使うのは $this->set() や$this->get() あたりぐらいでしょうか。
ここではbeforeCreateとbeforeUpdateの前、つまりDBに保存される前に、データを書き換えたり、加えたりしているわけです。
ここではsaltを作ってsetしたり、passwdを暗号化して書き換えたりしていますね
beforeCreateやbeforeUpdateから呼び出される流れを追って確認すると良いと思います。
posted by AMUAMU at 03:45| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

Akelosユーザ認証チュートリアル 4.Userモデルをちゃんと その2 validation

続いて、モデルに入るデータのルールを決めていきます。
validateの登場です。
validateは、入ってくるデータの内容を確認し、正当性をチェックして、ちゃんとデータが入るようにします。ただしく無いデータが来た場合のエラー処理もまとめてしてくれます。

C:\xampp\htdocs\projects\blog\app\models\user.php
を開いてください。

下記のようなコードを前回のUserメソッドの後ろに足します。
//入力内容のチェック
function validate()
{

//emailはユニークか?
$this->validatesUniquenessOf('email', array('notice'=>$this->t('email address registed!')));

//新しく作るときだけのチェック項目
if($this->isNewRecord()) {

//パスワードと、パスワード確認枠には入力があるか?
$this->validatesPresenceOf(array('passwd','passwd_confirmation'));

//チェックボックスの確認
$this->validatesInclusionOf('is_enable', array('1') ,$this->t('Please check checkbox of confirmation'));
}

//新しく作るとき または 修正時でかつパスワード修正がある場合のみのチェック
if($this->isNewRecord() || !empty($this->passwd))
{
//パスワードの長さチェック
$this->validatesLengthOf('passwd', array('in'=>array(5, 40), 'too_long' => $this->t('password too long.'), 'too_short' => $this->t('password too short')));

//パスワード確認の為の再入力枠とパスワードの内容が一致しているか
$this->validatesConfirmationOf('passwd', $this->t('not confirmation password'));

}

//emailとnameの空入力チェック
$this->validatesPresenceOf(array('email','name'));

//emailアドレスが有効なアドレスか?
$this->validatesFormatOf('email', AK_EMAIL_REGULAR_EXPRESSION, $this->t('error email address.')) ;


}

色々なvalidation用メソッドが登場しています。

コメントを見てある程度使い方がわかると思いますが、共通なのは 最初に調べたいカラム名を指定して、validationがエラーだった場合のメッセージ内容を$this->t('xxx')で指定するところですね。
なぜ、このようにメッセージを設定するかは別途書くとして、今はこういうもんだと思っておけば良いかと思います。ちなみにコード内では、xxxの部分は英語にしておいた方が良いです。日本語化は別なところでしますので、ここでは適当に。

わかりにくいのはvalidatesUniquenessOfとvalidatesConfirmationOfですかね。
validatesUniquenessOfは、いわゆる重複値チェックを一気にしてくれます。
DB内のemailフィールドで同じ値を持つデータが無いかを調べてくれます。便利です。
メールアドレスは個人毎にユニークに持つものなので、ここでチェックさせています。

validatesConfirmationOfは、指定した属性の名前と、その名前の後ろに"_confirmation"を足した名前の属性とで、一致をチェックするものです。
フォームの再入力値チェック用に使います。
ここでは、passwdを指定していますので、自動的に passwd_confirmation と比べる形になります。

posted by AMUAMU at 03:38| Comment(0) | TrackBack(0) | チュートリアル | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。