2011年02月03日

[CakePHP]reCAPTCHA Plugin を作った。

前回、 reCAPTCHA 入力値の判定を CakePHP の Model 内での Validation 時に行う話を書きました。それならばいっそのこと Plugin 化してしまおう、ということで作りました。reCAPTCHA API 用 PHP ライブラリを CakePHP から簡単に使おうというものです。
tbsmcd/recaptcha_plugin - GitHub
使い方は README にも書いてありますが、

1. reCAPTCHA キーを取得。
こちらからサインインして取得します。PUBLIC と PRIVATE があるので両方ともメモってください。

2. ライブラリファイルを設置
こちらからダウンロード・解凍し、recaptcha_plugin/vendors/recaptchalib.php となるように設置してください。

3. 設定ファイルの記述
1 で取得したキーを recaptcha_plugin/config/key.php に記述します。
	$config = array(
		'Recaptcha' => array(
			'Public'  => 'YOUR_RECAPTCHA_PUBLIC_KEY',
			'Private' => 'YOUR_RECAPTCHA_PRIVATE_KEY',
		),
	);
key.php.default をコピーしてもらえばいいと思います。

4. コントローラへの記述
reCAPTHCA を使用するフォームのコントローラに
	public $components = array('RecaptchaPlugin.Recaptcha');
	public $helpers = array('RecaptchaPlugin.Recaptcha');
のように記述します。

5. ヘルパーへの記述
reCAPTCHA を使用する form 内に
	echo $this->Recaptcha->show();  // reCAPTCHA 本体の出力
	echo $this->Recaptcha->error(); // Validation メッセージ出力
このように記述します。Recaptcha->show() はデフォルトでテーマ 'red' を使用しますが、show('white') のような形でテーマを指定することが出来ます。使用できるテーマは

red
reCAPTCHA_Red.png
white
reCAPTCHA_White.png
blackglass
reCAPTCHA_Black.png
clean
reCAPTCHA_Clean.png
の4種類です。

これは何をしているのか?
→基本的には前回の記事と同じく、 reCAPTCHA 用の Validation を追加しています。
多少変わった点といえば、 ValidationBehavior で
	function beforeValidate(&$model) {
		$model->validate['recaptcha_response_field'] = array(
			'checkRecaptcha' => array(
				'rule' => array('checkRecaptcha', 'recaptcha_challenge_field'),
				'message' => 'You did not enter the words correctly. Please try again.',
			),
		);
	}
という形でフックして Validation を追加している点と RecaptchaComponent で
	function startup(&$controller) {
		$modelClass = $controller->modelClass;
		if (!empty($controller->params['form']['recaptcha_challenge_field']) && !empty($controller->params['form']['recaptcha_response_field'])) {
			$controller->data[$modelClass]['recaptcha_challenge_field'] = $controller->params['form']['recaptcha_challenge_field'];
			$controller->data[$modelClass]['recaptcha_response_field'] = $controller->params['form']['recaptcha_response_field'];
		}

		$controller->$modelClass->Behaviors->attach('RecaptchaPlugin.Validation');

	}
というように Model にフォーム値を渡しつつ先の ValidationBehavior を指定してる点でしょうか。

さほど分量があるものでもないしそもそも簡単に使えるものなのですが、多少気の利いたプラグインとして役立てばいいかな、と思っています。


posted by tbsmcd at 22:41| Comment(1) | TrackBack(0) | 技術 | このブログの読者になる | 更新情報をチェックする

2011年01月31日

CakePHP で ReCAPTCHA を使う際の Validate

MVC という点から見たらおかしな話…あれ?わからん。

ちょっと ReCAPTCHA に触る機会があったので
CakePHPでreCAPTCHAによる画像認証を実装するまで - 情報と音楽

こちらを見たりしながら ReCAPTCHA をいじっていたんですけど、ユーザー側からしたら CAPTCHA も入力値(しかも一番厄介なもの)なので、他の値と一緒に Validate してみてもいいんじゃない?という話。以下、上記サイトを参照。

いきなり例。CakePHP の blog チュートリアル と同じスキーマから bake していくと

app/posts
index.png

app/posts/add
add.png

こんな感じの画面ができます。App/models/post.php に validation を書いておけば

valid_add.png

valid_error.png

こんなエラーメッセージを表示するように出来るのですが、 CAPTCHA だけ別扱いにするのはユーザから見ると少し不便な気がします。
そこで、上記サイトのコードを参考に少しいじっていってみたいと思います。

App/views/posts/add.ctp に
App::import('Vendor', 'recaptchalib');
$publickey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx';
echo recaptcha_get_html($publickey);
echo $this->Form->error('recaptcha_response_field');
このようにエラー出力を追加します。

これで view は出来ました。
add_recaptcha.png

次に Controller ですが、 App/controllers/posts_controller.php の add() に
if (!empty($this->data)) {
	// ここから追加
	// ここで $this->data に入力値を渡す.
	$this->data['Post']['recaptcha_challenge_field'] = $this->params['form']['recaptcha_challenge_field'];
	$this->data['Post']['recaptcha_response_field'] = $this->params['form']['recaptcha_response_field'];
	// ここまで追加
bake したものにこれだけ加えます。

最後に Model ですが、App/models/post.php の $validate に
'recaptcha_response_field' => array(
	'checkReCaptcha' => array(
		'rule' => array('checkReCaptcha', 'recaptcha_challenge_field'),
		'message' => 'あ、なんか間違ったみたいだねー。',
	),
),

を加え、ルールを定義する関数として
function checkReCaptcha($data, $target) {
	App::import('Vendor', 'recaptchalib');
	$privatekey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
	$res = recaptcha_check_answer(
		$privatekey,
		$_SERVER["REMOTE_ADDR"], 
		$this->data[$this->name][$target],
		$data['recaptcha_response_field']);
	return $res->is_valid;
}

という風に書いていけば

recaptcha_input.png

recaptcha_error.png

こんな感じで他の入力値と同じようにチェックできるからいいかもね、という話でした。


まあしかし、ビジネスロジックもデータも扱ってない…いやフォーム値のチェックだからな。 /* 追記 */ プラグイン化しました。記事は今度。

tbsmcd/recaptcha_plugin - GitHub
ラベル:cakephp PHP reCAPTCHA
posted by tbsmcd at 23:20| Comment(1) | TrackBack(0) | 技術 | このブログの読者になる | 更新情報をチェックする

2011年01月19日

Titanium Desktop で データベース を使う(PHP もあるでよ)

前置きなし。
1.とりあえず DB を使ってみる。
まずは 公式ドキュメント を参考に、データベースの作成、テーブルの作成、データの挿入をしてみます。
(Application 名は AppName, id は AppID, アプリ作成に使用するディレクトリを AppDir とします。)

AppDir/Resources/index.html

script タグの中にこんな感じで記述します。これを動かしてみると…
スクショ
と、こんな感じで DB を操作できているのは分かるのですが、一体どこで何が起きているのでしょう?いろいろ見ていくと
~/Library/Application Support/Titanium/appdata/AppID/AppID_0/0000000000000001.db
というファイルが出来ていて(Mac の場合)、中身をターミナルから覗いてみると
sqlite> select * from test;
1|hoge
のようにテーブルの作成→データの挿入までが出来ていることが分かります。

無事に DB を使うことが出来ていますが、初期値を入れた状態でアプリケーションを配布したい場合に不便です。そういった場合には Titanium.Database.openFile() を使います。
下準備として YourApps/Resources/ にターミナルから testdb を作り、
sqlite> create table test (id INT, name TEXT);
をしておきます。
AppDir/Resources/index.html


実行結果
スクショ
どうやらデータの挿入が出来ているようです。それではデータベースのファイルを確認してみましょう。
$ sqlite3 AppDir/Resources/testdb
sqlite> select * from test;
をやってみても何も返ってきません。実際のファイルは
AppDir/dist/osx/AppName/Contents/Resources/testdb にあるので、こちらで
sqlite> select * from test;
2|test
このように中身を確認できます。

2. PHP から SQLite を使ってみる
とりあえず PHP マニュアル通りに書いてみましょうか。
PHP: sqlite_open - Manual
をほぼコピペして

AppDir/Resources/index.php
<?php
if ($db = sqlite_open('testdb2', 0666, $sqliteerror)) {
    sqlite_query($db, 'CREATE TABLE foo (bar varchar(10))');
    sqlite_query($db, "INSERT INTO foo VALUES ('fnord')");
    $result = sqlite_query($db, 'select bar from foo');
    var_dump(sqlite_fetch_array($result));
} else {
    die($sqliteerror);
}

で、実行。
スクショ
「あら奥さん、出来ちゃいました。」ぐらいの勢いですんなり行けました。

じゃあちょっと趣向を替えて、 SQLite3 クラス を使ってみましょう。こちら のコードをコピペして
AppDir/Resources/index.php
<?php
$db = new SQLite3('test3.db');

$db->exec('CREATE TABLE foo (id INTEGER, bar STRING)');
$db->exec("INSERT INTO foo (id, bar) VALUES (1, 'This is a test')");

$stmt = $db->prepare('SELECT bar FROM foo WHERE id=:id');
$stmt->bindValue(':id', 1, SQLITE3_INTEGER);

$result = $stmt->execute();
var_dump($result->fetchArray());

スクショ
余裕じゃないですか。こうなったらもう少し調子にのって…

3. じゃあ PEAR を使ってみよう…と言いたいところですが

前回 の記事で Titanium Desktop で PEAR を使ってみました。実はここ1年ぐらい PEAR に触ってなかったのでちょっと自信ないのですが、PEAR::DB は「新規で使うな」という話なので PEAR::MDB2 を使うことになります。しかし MDB2 の SQLite ドライバが SQLite2 用 らしいんですよね。ということで今回は見送り。MDB2_Driver_sqlite3 を自力で書くという手もありますが、それはそれでまた別のお話ということで。

/* まとめ */
API
・Titanium.Database.open を使うとデフォルトで設定された場所に DB ファイルが作成される。
・Titanium.Database.openFile を使うと自分で決めた DB ファイルを使用出来るので、あらかじめデータを挿入しておくことも可能。

PHP
・SQLite 関数を使用して API を介さずに DB を操作できる。
・同様にSQLite3 クラスも使用可能。

といったところでしょうか。
続きを読む
ラベル:titanium PHP sqlite
posted by tbsmcd at 00:00| Comment(1) | TrackBack(0) | 技術 | このブログの読者になる | 更新情報をチェックする

2011年01月13日

Titanium + PHP + PEAR

前回「関西アンカンファレンスに参加してきましたよっ!」という記事を書きました。「PHP 光源氏計画」などというふざけたネーミングでしたが、こちらの
 松江市は2011年1月8日、市内の中学生を対象にしたRuby教室を開催した。ゲーム用拡張ライブラリのDXRubyを使い、自分で作ったキャラクタによるシューティングゲームを作成した。
松江市が中学生Ruby教室開催、DXRubyでゲーム作成 - ニュース:ITpro
こういった取り組みには、言語を問わず学ぶべきだと思うんですよね。松江市出身の自分が PHP 光源氏計画を始動したら故郷から謗りを受けそうですけど。

とまあ、いきなり閑話から入りましたごめんなさい。ここから本文です。

当日のまとめ Togetter - 「第2回関西アンカンファレンス」 を見ていたら
スクリーンショット(2011-01-13 1.21.38).png
Twitter / @オコノミ
という Tweet があって、これは是非やっておかないといけないな…と。

そこで
PHPでTwitter APIのOAuthを使う方法まとめ - 頭ん中
この msng さんの記事を参考に、簡単な Twitter アプリ(未満)を Titanium + PHP + PEAR で作ってみました。元記事にあるように、 Net_URL2, HTTP_Request2, HTTP_OAuth の各最新版を入れるのですが、まずプロジェクトを作らないとインストールするディレクトリも存在しません。
で、作成…
スクリーンショット(2011-01-12 21.40.48).png
プロジェクトのディレクトリ(以下便宜上 AppDir と表記します)の中で AppDir/Resources/PEAR というディレクトリを作り、その中にライブラリを入れていくとします。(理由は後述)
こんな感じ
スクリーンショット(2011-01-13 1.40.07).png

で、アプリを組んでみます。

AppDir/Resources/func.php
<?php
ini_set ('include_path', ini_get('include_path') . '/PEAR');   // 注1
require 'HTTP/OAuth/Consumer.php';

function omikuji () {
	$consumer_key = 'YOUR_CONSUMER_KEY';     //注2
	$consumer_secret = 'YOUR_CONSUMER_SECRET';
	$oauth_token = 'YOUR_OAUTH_TOKEN';
	$oauth_token_secret = 'YOUR_OAUTH_TOKEN_SECRET';

	$consumer = new HTTP_OAuth_Consumer($consumer_key, $consumer_secret);
	$consumer->setToken($oauth_token);
	$consumer->setTokenSecret($oauth_token_secret);
	
	$omikuji_array = array('大吉', '吉', '凶', '大凶', '処置なし');
	
	shuffle($omikuji_array);
	$status = 'test::' . $omikuji_array[0] . ' [' . date('Y-m-d H:i:s') . ']';
	$response = $consumer->sendRequest("http://twitter.com/statuses/update.json", array('status' => $status), "POST");
	$body = json_decode($response->getBody(), true);
	
	return $body['text'];
}
注1: ini_get('include_path') をすると AppDir/Resources となってます。デフォルトではこう指定されてるけど、ややこしくなりそうなので AppDir/Resources/PEAR と変更します。
注2: $oauth_token, $oauth_token_secret の取得は面倒なので省きます。アプリ登録時にデスクトップ用と指定して取得するなりして下さい。

で、 AppDir/Resources/index.html に
スクリーンショット(2011-01-13 10.55.21).png
こんな感じのコードを書きます。

例外処理とかエラー処理とか全然やってないし、公開するんだったら色々変えないといけない部分があるけど、一応これで
スクリーンショット(2011-01-13 1.00.14).png



スクリーンショット(2011-01-13 1.00.20).png

というものが出来ました。(YourApp/tiapp.xml に適切な画面サイズを記述してください。)

勿論 Twitter にも
tbsmcd / Tsubasa Mochida
test::処置なし [2011-01-13 01:00:17] at 01/13 01:00
こんな感じで投稿されてます。

ということで、
・PEAR のようなライブラリは依存関係や Path さえ通れば使えるみたい。
・ini_get('include_path') は AppDir/Resources
@ryo_ryoo_ryooo さんのせいでおみくじアプリなんて作ってしまった

という結論でどうでしょう?



/* 追記 */

実験に使ったアプリ名なんですが、以前遊んだもの を流用しただけです。なんかいま Favstar みたら結構 Fav られてたんで。
ラベル:PHP PEAR titanium
posted by tbsmcd at 02:06| Comment(1) | TrackBack(0) | 技術 | このブログの読者になる | 更新情報をチェックする

2011年01月10日

関西アンカンファレンスに参加してきましたよっ!

1/8(土)に開催された「第2回 関西アンカンファレンス」に参加してきました。

概要は…
第2回関西アンカンファレンスを2011年1月8日に開催します - 頭ん中
第2回関西アンカンファレンスを2011/01/08に開催します - Shin x blog


会場は兵庫県立大学神戸キャンパス(神戸ハーバーランドセンタービル23階)。

IMG_1487.jpg
大講義室より。ハーバーランドを一望!

眺望だけでもテンションが2段飛ばしぐらいで駆け上がる感じだったのですが、JR神戸駅から地下でつながってるのも素晴らしい。このような会場をご好意で提供して下さった兵庫県立大学様に感謝。

アンカンファレンスなので事前に発表枠を埋めるということは一切無く、ホワイトボードに付箋紙をペタペタ貼っていく形で埋めていきます。牽制の結果、当然のように一発目の発表枠が空いていたので躊躇なく大講義室の一発目の枠の発表を表明したのですが……

大講義室
1-1 「PHPがこの先生きのこるために何か」PHP光源氏計画 @tbsmcd

中講義室
1-1 やさしいjQueryの使い方 @kamiyam

第2回関西アンカンファレンス セッション一覧 - backyard of 伊勢的新常識 より。


なんか最近モテモテの @kamiyamさん × JQuery とかぶっちゃった ( @kamiyam さんの発表聞きたかったんだよなー )のですが、こちらも「もっと PHP (が|で)モテる話」をしてきました。


こちらからも見れます。

トップバッターだった(言い訳)からか、「時間を大幅に余らしてあと雑談」という事故レベルの発表でしたが、
tbsmcd / Tsubasa Mochida
ノーミス。 #kansaiun at 01/08 11:12

言い張ったもんの勝ちですね!

という感じで初っ端に荷物を下ろして後は存分に聞きました。個人的に面白かったのは @mzsm_j さんの「新感覚のURL短縮サービスを作ってみた」(つい短.jp) でした。調子にのって
tbsmcd / Tsubasa Mochida
http://懇親会も.参加します.jp #kansaiun at 01/08 14:43

tbsmcd / Tsubasa Mochida
http://あるばーたすまき.します.jp #kansaiun at 01/08 14:49

tbsmcd / Tsubasa Mochida
http://【関西アンカンファレンス】発表した資料を公開.します.jp #kansaiun at 01/08 15:30


はしゃぎすぎました。技術的な話もさることながら、「この発想はなかった!」みたいな話が聞けるのもこういうイベントの醍醐味ですね。

終了後の懇親会では色々と、ここで書けないようなことも沢山話しました。大満足。その中から名言をひとつ

「モテるから『おれはモテる』と言うんじゃない。『おれはモテる』というからモテるんだ。」


そう、言ったもん勝ちなんですよね、何でも。だからこのようなイベントに参加したことがない方、二の足を踏んでる方がいらっしゃったら是非足を運んで、そして発表してください。

「あなたの常識はぼくの非常識、あなたの当然はぼくの発見。」なのだから。続きを読む
ラベル:PHP titanium 技術
posted by tbsmcd at 01:28| Comment(0) | TrackBack(2) | 技術 | このブログの読者になる | 更新情報をチェックする
×

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