自分の過去記事
会員登録フォームの作成と、cakephp-captchaの使い方詳細は以下の過去記事にあるので、今回は端折って書く。
以前はSignupコントローラーだったのを、Signupsコントローラーにして作り直した。
さくらvpsとcakephp2.6.7で開発日記 その0002 会員登録フォームの作成をする - MOTOMICHI WORKS BLOG
さくらvpsとcakephp2.6.7で開発日記 その0003 cakephp-captchaを使ってみる - MOTOMICHI WORKS BLOG
usersテーブルを作成する
さくらvpsとcakephp2.6.7で開発日記 その0002 会員登録フォームの作成をする - MOTOMICHI WORKS BLOGで作成したusersテーブルを使う。
必要なファイルのリスト
- Config/email.php
- Controller/SignupsController.php
- Controller/Component/CaptchaComponent.php
- Model/Capt.php
- Model/User.php
- Model/Behavior/CaptchaBehavior.php
- View/Emails/text/signup.ctp
- View/Signups/activate.ctp
- View/Signups/email_sent.ctp
- View/Signups/index.ctp
- Lib/Fonts/monofont.ttf
- Lib/Fonts/Sanchez-Regular.ttf
Config/email.php
email.php.defaultを複製して、ファイル名だけ変更した。
Controller/SignupsController.phpを作成する
記述内容は以下の通り。
<?php /** * (Sample) Controller for Showing the use of Captcha* * @author Arvind Kumar (arvind.mailto@gmail.com) * @link http://www.devarticles.in/ * @copyright Copyright © 2014 http://www.devarticles.in/ * @version 2.5 Tested OK in Cakephp 2.5.4 */ App::uses('AppController', 'Controller'); App::uses('CakeEmail', 'Network/Email'); App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth'); class SignupsController extends AppController { // Controller名 public $name = 'Signups'; // 使用するコンポーネントとその設定 public $components = array( 'Captcha'=>array( 'model'=>'Capt', 'field'=>'security_code' ) ); // 使用するModel public $uses = array('User','Capt'); // 使用するHelper public $helpers = array('Captcha'); function captcha(){ // 画像更新がクリックされたときの処理 $this->autoRender = false; $this->layout='ajax'; $this->Captcha->create(); } function index(){ // 送信データが無い場合の処理 if(!$this->request->data){ $this->render(); return; } // 送信された値がUserモデルで使用できるようにset $this->User->set($this->request->data); // バリデーションを実行 if(!$this->User->validates(array('fieldList' => array('email')))) { // バリデーションNGのときの処理 $this->render(); return; } // emailフォームに入力された値を$emailに格納 $email = $this->request->data['User']['email']; // $emailと現在時刻を結合してハッシュ化 $signup_code = md5($email.time()); // 下記2つの条件に一致するレコードを1列取得して$userに格納する // - フィールド名emailの値が$email // - フィールド名is_registeredの値が0 // // (仮登録されているデータが既にある場合は取得) $user = $this->User->find('first',array( 'conditions' => array( 'email' => $email, 'is_registered' => 0 ) )); // 仮登録データの有無によって、処理を分ける if($user){ // 仮登録データがDBに既にある場合の処理 // UPDATEする事になるので、saveの第三引数に渡す配列を設定 $fields = array('signup_code'); // DBから取得した値のままだと更新されないので、modifiedをnullにする $user['User']['modified'] = null; }else{ // 仮登録データがDBにまだ無い場合の処理 // INSERTする事になるので、saveの第三引数に渡す配列はnullを設定 $fields = null; // INSERT文実行をすることになるので、create()して、フィールドの初期値でModelを初期化 // UPDATE文を実行するときはcreate()しては駄目なのでいつも注意する! $this->User->create(); // フォームから送信された値を$userに挿入 $user = array('User' => $this->request->data['User']); } // 仮登録状態ということをデータベースに登録するので0 $user['User']['is_registered'] = 0; // signup_codeフィールドに入れる値を格納 $user['User']['signup_code'] = $signup_code; // usersテーブルにUPDATEまたはINSERT(UPDATEの場合は$fieldsで指定したものだけを更新) if(!$this->User->save($user,false,$fields)){ $this->Session->setFlash('システムエラーが発生しました。恐れ入りますが始めからやり直してください。'); $this->render(); return; } // "https://hogehoge.com/"みたいなベースURLを取得 $full_base_url = Router::url( '/', true); // 本登録用のURLを生成して、$urlに格納 $url = $full_base_url.'signups/activate/'.$signup_code; //emailの自動送信処理 $cake_email = new CakeEmail('default');// Config/email.phpの$defaultの設定でインスタンスを生成 $cake_email->from( array('mw.contacts@hoge.com' => 'Sender'));// 送信元を設定 $cake_email->to($email);// 送信相手を設定 $cake_email->subject('仮登録のお知らせ');// 件名を設定 $cake_email->emailFormat('text');// HTML or テキストメール $cake_email->template('signup');// テンプレート // テンプレートへ渡す変数 $cake_email->viewVars(array( 'url'=>$url )); // メールを送信 if($cake_email->send()){ // メール送信成功時の処理 // Signup/email_sent.ctpにリダイレクト $this->redirect('email_sent'); }else{ // メール送信失敗時の処理 $this->Session->setFlash('システムエラーが発生しました。恐れ入りますが始めからやり直してください。'); $this->render(); return; } }// end of action index public function email_sent(){ }// end of action email_sent public function activate($signup_code){ // 下記2つの条件に一致するレコードを1行取得して$userに格納する // - フィールド名signup_codeの値が$signup_code // - フィールド名is_registeredの値が0 $user = $this->User->find( 'first', array( 'conditions' => array( 'signup_code' => $signup_code, 'is_registered' => 0 ) ) ); // 上記の処理で、条件に一致する行がデータベースに無かった場合、仮登録が済んでいないのでリダイレクトする if(!$user){ $this->Session->setFlash('URLが無効です。恐れ入りますがメール送信からやり直してください。'); $this->redirect('index'); } // 仮登録情報更新日時のtimestampを取得 $modified_time = strtotime($user['User']['modified']); // 現在日時のtimestampを取得 $time = time(); // 仮登録から86,400秒よりも経過しているかを判定 if(86400 < $time - $modified_time){ $this->Session->setFlash('URLの有効期限が切れています。恐れ入りますがメール送信からやり直してください。'); $this->redirect('index'); } // 送信データが無い場合、Signup/activate.ctp(本登録ページ)を表示する if(!$this->request->data){ $this->render(); return; } // 送信された値がUserモデルで使用できるようにset $this->User->set($this->request->data); // 送信された値がCaptモデルで使用できるようにset $this->Capt->set($this->request->data); // setCaptchaで画像に表示されている文字列をsetする $this->Capt->setCaptcha( 'security_code', $this->Captcha->getCode('Capt.security_code') ); // バリデーションを実行 $result__user = $this->User->validates(array('fieldList' => array('name','password'))); $result__capt = $this->Capt->validates(); if(!$result__user && !$result__capt){ // バリデーションNGのときの処理 $this->Session->setFlash('UserとCaptのバリデーションはfalseです。'); $this->render(); return; }else if(!$result__user) { // バリデーションNGのときの処理 $this->Session->setFlash('Userのバリデーションはfalseです。'); $this->render(); return; }else if(!$result__capt){ // バリデーションNGのときの処理 $this->Session->setFlash('Captのバリデーションはfalseです。'); $this->render(); return; } // フォームから送信されたパスワードをハッシュ化 $passwordHasher = new BlowfishPasswordHasher(); $user['User']['password'] = $passwordHasher->hash($this->request->data['User']['password']); // $user['User']['password_confirm']はもうModel内で使用しないので、unset unset($user['User']['password_confirm']); // 本登録完了のステータスを保存するので1 $user['User']['is_registered'] = 1; // 送信されたニックネームを保存するので、$user['User']['name']の値を上書き $user['User']['name'] = $this->request->data['User']['name']; // usersテーブルをUPDATE if(!$this->User->save($user,false)){ //save失敗した場合の処理 $this->Session->setFlash('システムエラーが発生しました。もう一度送信をお願いします。'); $this->render(); return; } // save成功したら、ログインページにリダイレクト $this->redirect('/users/login'); }// end of action activate }
Controller/Component/CaptchaComponent.phpの配置と編集
ダウンロードしてきたzipファイルから、開発環境に配置して
private $__fonts = array('monofont', 'Sanchez-Regular');
のような感じでフォントを指定を変更した。
Model/Capt.phpを作成する
記述内容は以下の通り。
<?php /** * (Sample) Model for Showing the use of Captcha* * @author Arvind K. * @link http://www.devarticles.in/ * @copyright Copyright © 2008 www.devarticles.in * @version Tested ok in Cakephp 2.x */ class Capt extends AppModel { var $useTable = false; //i dont have a table right now, just testing captcha public $actsAs = array( 'Captcha' => array( 'field' => array('security_code'), 'error' => '文字が一致しませんでした。' ) ); }
Model/User.phpの作成
記述内容は以下の通り。
<?php App::uses('AppModel', 'Model'); class User extends AppModel { public $name = 'User'; /** * * * @return boolean */ public function isUniqueAndActive($valid_field){ // field名を取得(例えばemail) $fieldname = key($valid_field); // 下記二つの条件に一致する行をjoinしない設定で取得 // - $fieldnameフィールドが、フォームから送信された値である // - is_registeredフィールドが、1である $user = $this->find( 'first', array( 'conditions' => array( $fieldname => $this->data[$this->name][$fieldname], 'is_registered' => 1 ), 'recursive' => -1 ) ); if($user){ // conditionsに該当する行が、既に存在する場合は、false return false; } return true; } /** * * @return boolean */ function checkCompare($valid_field , $suffix){ $fieldname = key($valid_field); if($this->data[$this->name][$fieldname] === $this->data[$this->name][$fieldname.$suffix]){ return true; } return false; } /* * バリデーション対象となるキーと、そのルールを設定 */ public $validate = array( 'email' => array( array( 'rule' => 'notEmpty', 'message' => 'メールアドレスを入力してください。' ), array( 'rule' => array('custom', '/^.+@.+$/'), 'message' => '形式が正しくありません。' ), array( 'rule' => array('checkCompare','_confirm'), 'message' => 'メールアドレスが一致していません。' ), array( 'rule' => 'isUniqueAndActive', 'message' => 'すでに使用されています。' ) ), 'name' => array( array( 'rule' => 'notEmpty', 'message' => '必須項目です。' ) ), 'password' => array( array( 'rule' => 'notEmpty', 'message' => 'パスワードを入力してください。' ), array( 'rule' => array('minLength', '8'), 'message' => '8文字以上入力してください。' ), array( 'rule' => array('custom', '/^[a-zA-Z0-9]+$/'), 'message' => '半角英数字で入力してください。' ), array( 'rule' => array('checkCompare','_confirm'), 'message' => 'パスワードが一致していません。' ) ) ); }
Model/Behavior/CaptchaBehavior.phpを配置する
ダウンロードしてきたzipファイルから、開発環境に配置した。
View/Emails/text/signup.ctp
記述内容は以下の通り
このメールは自動送信しております。 このメールアドレスにお問い合わせをいただくことはできません。 24時間以内に下記のURLから本登録をしてください。 <?php echo ($url); ?> また、このメールにお心当たりの無い場合は、このメールを破棄してください。
View/Signups/activate.ctpの作成
記述内容は以下の通り。
<h1>会員登録</h1> <?php echo($this->Form->create()); ?> <div> <?php echo $this->Form->label('Capt.security_code', 'セキュリティコード: '); echo $this->Captcha->render(); echo $this->Form->error('Capt.security_code'); ?> </div> <div> <?php echo $this->Form->label('User.name', 'ニックネーム: '); echo $this->Form->text( 'User.name', array( 'errorMessage' => false, 'div' => false, 'required' => false ) ); echo $this->Form->error('User.name'); ?> </div> <div> <?php echo $this->Form->label('User.password', 'パスワード: '); echo $this->Form->password( 'User.password', array( 'errorMessage' => false, 'div' => false, 'required' => false ) ); echo $this->Form->error('User.password'); ?> </div> <div> <?php echo $this->Form->label('User.password_confirm', 'パスワード(確認): '); echo $this->Form->password( 'User.password_confirm', array( 'errorMessage' => false, 'div' => false, 'required' => false ) ); ?> </div> <?php echo($this->Form->end('送信')); ?>
View/Signups/email_sent.ctpの作成
記述内容は以下の通り。
<h1>会員登録</h1> <div> ご入力いただいたメールアドレスに、メールを送信しました。<br> メール本文に記載されているURLから本登録を完了してください。 </div>
View/Signups/index.ctpの作成
記述内容は以下の通り。
<h1>会員登録</h1> <?php echo($this->Form->create()); ?> <div> <?php echo $this->Form->label('User.email', 'メールアドレス: '); echo $this->Form->text( 'User.email', array( 'errorMessage' => false, 'div' => false, 'required' => false ) ); echo $this->Form->error('User.email'); ?> </div> <div> <?php echo $this->Form->label('Usr.email_confirm', 'メールアドレス(確認): ') ; echo $this->Form->text( 'User.email_confirm', array( 'errorMessage' => false, 'div' => false, 'required' => false ) ); ?> </div> <?php echo($this->Form->end('送信')); ?>
フォントを配置する
下記二つのファイルをダウンロードして配置した。
- Lib/Fonts/monofont.ttf
- Lib/Fonts/Sanchez-Regular.ttf
まとめ
以前作成した会員登録フォームと、Captchaの導入テスト的なものを結合した。
まとめてみると、必要なファイルは結構たくさんある。
なんか足りないかもだけど、足りなかったら、そのうち気付くかも。
それぞれ作成したときの記事は以下の二つ。
さくらvpsとcakephp2.6.7で開発日記 その0002 会員登録フォームの作成をする - MOTOMICHI WORKS BLOG
さくらvpsとcakephp2.6.7で開発日記 その0003 cakephp-captchaを使ってみる - MOTOMICHI WORKS BLOG
今回はここまで。