Yii

Yii Blog Tutorial コメント入力にキャプチャを表示し、検証を追加する

サイト訪問者からのコメントは、ブログを公開している者にとって嬉しいものだ。しかしコメント欄はスパム攻撃の対象にされやすい。特にプログラムを利用したスパムは、定期的に送られてくるので削除してもキリがない。そこでプログラムによる自動スパムコメントを排除する方法の1つとして、キャプチャ(CAPTCHA)を利用する方法がある。

Yii のブログチュートリアルを見ると、コンタクトページにキャプチャが利用されている。Yii にはキャプチャを利用するための仕組みが既に用意されているようだ。そこで、コメント入力にキャプチャによる入力の検証機能を追加してみた。

キャプチャ画像の表示や検証は、Yii のオブジェクトを組み込めば自分でプログラミングすることは何もないので、次のようにして簡単に組み込むことができた。

組み込み

キャプチャ画像の表示はビューへ、検証はコントローラへ、検証を実行するためのトリガーはモデルへそれぞれ指定する。

先ずはキャプチャ画像に対する入力項目をコメントモデルに追加する。Comment クラスに「public $verifyCode;」をアトリビュートとして追加する。

そして、バリデーションチェックでキャプチャの検証を実行するトリガーになるように、rules メソッドに「’captcha’」を追加する。

class Comment extends CActiveRecord
{
	public $verifyCode;

	public function rules()
	{
		return array(
			array('author, email, content', 'required'),
			array('author, email, url', 'length', 'max'=>128),
			array('email', 'email'),
			array('url', 'url'),
			array('content', 'safe'),
			array('verifyCode', 'captcha', 'allowEmpty'=>!extension_loaded('gd')),
		);
	}

キャプチャ画像生成に PHP の gd を利用するようなので、gd がインストールされていないと画像は表示されないだろう。

検証はコントローラで「captcha」アクションを用意し、「CCaptchaAction」オブジェクトを利用して自動で行なえるようになっている。ところで Yii のコントローラでアクションメソッドを用意する方法として、直接「public function actionIndex()」のようにプログラムを書く以外に、アクション名とそこで実行するオブジェクトのクラスを指定するだけで、モジュールを組み込む方法が用意されている。それを利用するにはコントローラに、「actions」メソッドを追加して必要なパラメータを書き込めばいいようだ。チュートリアルの Site コントローラのまねをして、Post コントローラに以下のメソッドを追加する。

class PostController extends Controller
{
	public function actions()
	{
		return array(
			'captcha'=>array(
				'class'=>'CCaptchaAction',
				'backColor'=>0xffffff,
			),
		);
	}

	public function accessRules()
	{
		return array(
			array('allow',
				'actions'=>array('index', 'view', 'captcha'),
				'users'=>array('*'),
			),
		:

アクションでアクセス制御を行なっているようであれば、上の例のように「captcha」を追加する。そうしないと次のビューでキャプチャ画像を表示するように指定しても、画像が表示されない。

コメント入力欄にキャプチャ画像を表示するための指定を、「CHtml::beginForm」と「CHtml::endForm」の間に挟み込む。

<div class="form">
<?php echo CHtml::beginForm(); ?>
 :
<?php if (extension_loaded('gd')) : ?>
	<div class="row">
		<div>
			<?php $this->widget('CCaptcha'); ?>
			<?php echo CHtml::activeTextField($model, 'verifyCode'); ?>
		</div>
		<div class="hint">表示されている文字を入力してください。<br />大文字小文字どちらでも構いません。</div>
	</div>
<?php endif; ?>

	<div class"row buttons">
		<?php echo CHtml::submitButton($model->isNewRecord ? '投稿' : '保存'); ?>
	</div&gh;
<?php echo CHtml::endForm(); ?>

(yii-1.1.0.r1700)