参考にさせて頂いたページ
inimist/cakephp-captcha · GitHub
cakephp-captcha-master.zipをダウンロードして解凍する
解凍したら以下のような構造になっていた
. ├── README.md └── app ├── Controller │ ├── Component │ │ └── CaptchaComponent.php │ └── SignupsController.php ├── Model │ ├── Behavior │ │ └── CaptchaBehavior.php │ └── Signup.php └── View ├── Elements │ └── captchamath.ctp ├── Helper │ └── CaptchaHelper.php └── Signups ├── add.ctp └── demo.ctp
Controllerを配置する
zipの中にある
をそれぞれ開発環境のapp/Controller/にそれぞれ配置する。
Modelを配置する
zipの中にある
をそれぞれ開発環境のapp/Model/にそれぞれ配置する。
Viewを配置する
zipの中にある
- View/Helper/CaptchaHelper.php
を開発環境のView/Helper/に配置して、
- View/Signups/index.ctp
を自分で作成する。
index.ctpの記述内容は以下の通り。
<?php echo($this->Form->create()); ?> <div> <?php echo $this->Form->label('Signup.security_code', 'セキュリティコード: '); echo $this->Captcha->render(); echo $this->Form->error('Signup.security_code'); ?> </div> <?php echo($this->Form->end('送信')); ?> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script> jQuery('.creload').on('click', function() { var mySrc = $(this).prev().attr('src'); var glue = '?'; if(mySrc.indexOf('?')!=-1) { glue = '&'; } $(this).prev().attr('src', mySrc + glue + new Date().getTime()); return false; }); </script>
フォントを配置する
別途ダウンロードした
- Sanchez-Regular.ttf
- monofont.ttf
開発環境のapp/Lib/Fonts/ディレクトリに配置する。
使用するフォントを設定する
app/Controller/Component/CaptchaComponent.phpの
private $__fonts = array('monofont', 'sanchez');
となっている箇所を
private $__fonts = array('monofont', 'Sanchez-Regular');
に変更した。
SignupsController.phpを編集する
さきほど配置したSignupsController.phpを参考ページにならって編集した。
demo,addのアクションを削除したり、他にも色々編集して、以下のようにした。
<?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 */ class SignupsController extends AppController { // Controller名 public $name = 'Signups'; // 使用するコンポーネントとその設定 public $components = array( 'Captcha'=>array( 'model'=>'Signup', 'field'=>'security_code' ) ); // 使用するModel public $uses = array('Signup'); // 使用する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; } // フォームの送信データがModel内で使用できるようにsetする $this->Signup->set($this->request->data); // setCaptchaで画像に表示されている文字列をsetする $this->Signup->setCaptcha( 'security_code', $this->Captcha->getCode('Signup.security_code') ); // バリデーションを実行 if($this->Signup->validates()){ // バリデーションOKのときの処理 $this->Session->setFlash('Signupのバリデーションはtrueです'); $this->render(); return; }else{ // バリデーションNGのときの処理 $this->Session->setFlash('Signupのバリデーションはfalseです'); $this->render(); return; } } }
signups/indexにアクセスしてみる
この段階で、バリデーションが機能するようになった。
ちょっとだけCaptchaHelper.phpを改良する
個人的には、自動的に生成されるlabel, errorMessage, div, required をfalseにして、自分の好きなところに表示させたいので、
echo $this->Form->input( $this->settings['model'].'.'. $this->settings['field'], array('autocomplete'=>'off','label'=> $this->settings['clabel'],'class'=>'clabel'));
となっている箇所を
echo $this->Form->input( $this->settings['model'].'.'. $this->settings['field'], array( 'autocomplete'=>'off', 'label'=> false, 'class'=>'clabel', 'errorMessage' => false, 'div' => false, 'required' => false ) );
とした。
今回追加したファイル
- app/Controller/Component/CaptchaComponent.php
- app/Controller/SignupsController.php
- app/Lib/Fonts/monofont.ttf
- app/Lib/Fonts/Sanchez-Regular.ttf
- app/Model/Behavior/CaptchaBehavior.php
- app/Model/Signup.php
- app/View/Helper/CaptchaHelper.php
- app/View/Signups/index
SignupsController.phpの記述内容について
今回のcaptcha導入にあたって、苦労した部分などについて少し書いておく。
$componentsとCaptchaComponent.phpの125行目の$settingsについて
public $components = array( 'Captcha'=>array( 'model'=>'Signup', 'field'=>'security_code' ) );
上記はCaptchaComponent.phpの125行目にある、$settingsに設定された内容を上書きするもの。
各Controllerでこれらを設定すると、Controllerに記述した設定内容が優先される。
これらはバリデーションなどで使用する情報であると同時に、Viewで描画されるinput要素のname属性にも反映される。
いつも通りModelへのsetは必要
// フォームの送信データがModel内で使用できるようにsetする $this->Signup->set($this->request->data);
上記の記述は、通常のModelやバリデーションと同様にsetする必要がある。
getCodeとsetCaptcha
// setCaptchaで画像に表示されている文字列をsetする $this->Signup->setCaptcha( 'security_code', $this->Captcha->getCode('Signup.security_code') );
上記の記述のうち、getCodeメソッドの引数には$componentsのmodelとfieldに設定した文字列をつなげたものが
'Signup.security_code'
のような感じで入ることになる。
この詳細は、CaptchaComponent.php内のgetCodeメソッドが定義されている箇所を読むとわかるんだけど、sessionに格納された文字列を取得している。
これは、DebugKitのSessionをみながら作業するとよくわかる。
次に、setCaptchaの引数についてですが、その引数は二つ。
第一引数は$componentsのfieldに設定した文字列と同じ'security_code'
を設定する。
第二引数はgetCodeメソッドの戻り値で、getCodeメソッドの戻り値とは、submitしたときに画像に表示されている文字列。
この詳細は、CaptchaBehavior.php内のsetCaptchaメソッドが定義されている箇所を読むとわかる。
実行時の引数はそれぞれ、$field, $captchaとして、setCaptchaメソッド内で使用される。
さらに、CaptchaBehavior.php内のvalidateCaptchaメソッドを読むと
return フォームに入力した文字列 == 画像に表示されていた文字列;
と比較結果をreturnしている事がわかる。
特徴として
gdをインストールしなくても動作する。と参考ページに書いてあった。
おまけ
画像更新リンクの文字列を変更する
CaptchaComponent.phpの125行目の$settingsの
'reload_txt' => 'Can\'t read? Reload',
を編集する。
バリデーションエラーのときに表示する文字列を変更する
Model/Signup.phpの
'error' => 'Incorrect captcha code value'
を編集する。
画像の外側やリンクの外側に要素を追加したい
CaptchaHelper.phpの
echo $this->Html->image($this->Html->url(array('controller'=>$controller, 'action'=>$action, '?'=> $qstring), true), array('vspace'=>2)); echo $this->Html->link( $this->settings['reload_txt'], '#', array('class' => 'creload', 'escape' => false));
の部分に例えばdiv要素を追加して、
echo '<div class="hogehoge">'.$this->Html->image($this->Html->url(array('controller'=>$controller, 'action'=>$action, '?'=> $qstring), true), array('vspace'=>2)).'</div>'; echo '<div class="hogehoge">'.$this->Html->link( $this->settings['reload_txt'], '#', array('class' => 'creload', 'escape' => false)).'</div>';
みたいな感じにする。
ただ、これらを編集したときはjsも少しだけ編集する必要がある。