CakePHPでjQueryを使ってAjaxする方法

「CakePHPのAjaxヘルパーってprototypeかよ・・・」というjQueryラヴァーへ捧げるエントリー。 jQuery+CakePHPでAjaxしちゃう方法ですよ。例題として簡単なタスク管理システムつくるぜ。 ↑ こういうやつ。/tasks/indexの画面す。 タスクをFormからSubmitすると下のリストに画面遷移なく追加されていく、というものです。 以下、作業ログ。 ■ DB設定 こんな感じで。ちょーてきとー。 DROP TABLE IF EXISTS tasks; CREATE TABLE tasks ( id int(11) unsigned NOT NULL auto_increment, title varchar(255), created datetime NOT NULL, modified datetime NOT NULL, PRIMARY KEY (id), KEY created (created), KEY modified (modified) ); あとモデルも適当につくっておいてください。 ■ jQueryから まずはJavaScriptを書いちゃうのがわかりやすいでしょう。いじるのは「views/tasks/index.ctp」です。なお、layoutの方でjQueryを読み込んでおくのを忘れずに。 面倒だから全部貼り付けてみる。 <h2>Tasks</h2> <?php echo $form->create(‘Task’, array(‘default’=>false)); echo $form->input(‘title’); echo $form->submit(‘Add’); echo $form->end(); ?> <ul id="tasks"> <?php foreach($tasks as $task) { ?> <li><?= h($task[‘Task’][‘title’]); ?></li> <?php } ?> </ul> <script language="JavaScript"> $(function() { $("#TaskAddForm").submit(function() { $.post(‘/tasks/ajax_add’, { title: $("#TaskTitle").val() }, function(rs) { $("#tasks").prepend(rs); $("#TaskTitle").val(”).focus(); }); }); }); </script> 注意する点は、formがsubmitされても画面遷移しちゃわないようにform作るときに”default”をfalseにすることぐらいすかね。 ■ コントローラー で、ajaxで呼び出されるajax_addも含め、コントローラーはこんな感じ。わかりやすいようにコメントつけといたよー。「controllers/tasks_controller.php」です。 class TasksController extends AppController { var $name = ‘Tasks’; // ajax呼び出しに必要 …

CakePHPのAuthComponentではまったところ

先日のエントリーの続編。またしても超絶個人的メモ。ごめん。 フォームからusername、passwordにあたるものが送信されると自動的にpasswordはhash化される・・・。はまった。 User情報の更新などで「password欄が空欄だったらそのまま、入力されたら更新」という処理があると思いますが、上記の注意事項があるため気をつけましょう。コード的には以下かな($meには現在のユーザー情報)。 if ($this->data[‘User’][‘password’]==$this->Auth->password(”)) { $this->data[‘User’][‘password’] = $me[‘User’][‘password’]; } $this->Auth->user()にはpasswordが含まれていません。別の言い方をすると$this->Auth->user(‘password’)はNULL。 User情報の更新を$this->User->save()でやっても$this->Auth->user()の情報は更新されません。更新するには再度login、logoutする、とかといった工夫が必要(参考)。 以上ですかね。いやー、勉強になりますな! 追記:Passwordチェックは、フォーム上でPasswordのフィールド名を変更しておく手もあります(Thanks to @msng)。こちらだと入力値のチェックが自由自在でいいかもですね。 $this->data[‘User’][‘password’] = $this->Auth->password($this->data[‘User’][‘password_to_be’]);

CakePHPのAuthComponentに関する覚書

超個人的メモ。すまん。 ■ まずはこちら 参考情報的な。 Authentication :: Core Components :: The Manual :: 1.2 Collection :: The Cookbook 公式マニュアル。人とおり目を通すこと。 【CakePHP】AuthComponentについてのまとめ 【ざっくり基本編】 | ねねとまつの小部屋 こちらで復習。 【CakePHP】AuthComponentについてのまとめ その2【ちょっとしたコツ編】 | ねねとまつの小部屋 さらに読んどくべし。 【CakePHP】AuthComponentについてのまとめ その3【ログイン後のリダイレクト編】 | ねねとまつの小部屋 リダイレクトの処理だけど、最新版ではSessionに戻り先が保存されているっぽいから不要?? CakePHP Note:自動ログインその1 自動ログインまでやりたい場合はこちらで。 ■ 実装までの手順 コードは上記サイトを見てもらうとして概念的なステップ。 全部のモデルで使いたいと思うからAPP/controllers/app_controller.phpに「var $components = array(‘Auth’);」って書いちゃう。 細かい設定は同ファイルのbeforeFilterに書いちゃう。 ただ、$this->Auth->allowだけは各コントローラーに記述。その際は「parent::beforeFilter();」を忘れぬこと。 DB側は基本的にUsersテーブル、username, passwordを設定しておけばOK。ここでusernameじゃなくて、emailにしたい場合もあるだろうから「$this->Auth->fields」をbeforeFilterへ。 自動ログインしたい場合(=Cookie使う場合)は「$this->Auth->autoRedirect = false;」してからlogin()にいろいろ記述。 入力時にパスワードの再確認をしたい場合は比較処理に注意(入力値をHash化してから比較すること)。 ■ 使ってみた感想! 以前のCakePHP修行ではそれぞれのメソッドに_checkLogin()とかかましていましたが、それらが根こそぎ不要に!なんという便利さ!みんな、使ったほうがいいよ! 追記:CakePHPのAuthComponentではまったところ

独習CakePHP ~ 最初の7日間で何をすべきか? ~

第2回CakePHP勉強会に参加しました。 なんちゃってエンジニアなので隅っこの方で話を聞いていようかなぁ、と思っていたのですが、青い人から「ライトニングトークしませんか?」と誘われました。やったことのないものはとりあえずチャレンジ!ということで5分程度しゃべってきました。 以下、資料。CakePHP初心者向けに、最初の7日で何をすべきか+陥りやすい罠などをまとめてみました。まぁ、ネタですがw。 | View | Upload your own ↑ Slideshare、はじめて使うな、そういえば。 僕のパートはまぁ、いいとして、その他の方のお話がやっぱり参考になりました。実際のところ、みんながどうやってコードを書いているのか、とか、どういう開発をしているのかとかが普段の生活からはわからないので勉強になりましたよ・・・とりあえずmemcache使いたい。 今回の勉強会は数時間で満員とのこと・・・第3回目も油断せずに申し込まないとですね。最後になりますが、主催者のみなさま、会場を提供していただいたトライコーンの方々、ありがとうございました! » 第2回CakePHP勉強会::events.php.gr.jp

CakePHPでCSVファイルをダウンロードさせたいときの作法

ひさびさにCakePHPの開発メモ。エンジニアじゃない人はスルーの方向で・・・。 さてアプリをつくっていてCSVファイルをダウンロードさせたい、みたいなときがありますが、その際にCakePHPではこうするといいよ、というお話。なお、このコードに関しては主に青い人に聞きまくりました(笑)。 では早速。 ■ やりたいこと /user/download のURLにてユーザー全部の情報をCSVでダウンロードさせたい。 ■ users_controller.php コントローラーのdownload()を以下のように記述。 function download($id) { $this->autoRender = false; // Viewを使わないように Configure::write(‘debug’, 0); // debugコードを出さないように $csv_file = sprintf(“users_%s.csv”, date(“Ymd-hi”)); // 適当にファイル名を指定 header (“Content-disposition: attachment; filename=” . $csv_file); header (“Content-type: application/octet-stream; name=” . $csv_file); $buf = “”; // ごにょごにょして$bufにUserの内容を追加 // 注意点は二つ。 // 1. 一つにまとめたい文字列は””で囲む。 // 2. 文字列内に”がある場合は””としてエスケープ print($buf); // 出力 return; } これで/users/download/にアクセスすればCSVファイルが出力されるはずです。よろしければどうぞ。 その他のCakePHP関連情報は以下からどうぞ。 » CakePHP修行! アーカイブ | IDEA*IDEA

CakePHPでSNSっぽいものをつくってみる企画で学んだこと(CakePHP修行 最終回)

さてCakePHP修行。今回が最終回です。このエントリーを書くのがすっかり遅くなってしまった(理由は後述)。 初回が6月20日だったので2ヶ月ぐらいかかりました。ただ、期間はかかりましたが、フレームワークによるラピッド開発の威力を思い知りました。やってよかった。 さて最終回はつらつらと今回の企画で学んだことや雑感などをメモ程度にまとめてみたいと思います。 ■ フレームワークについて この企画をやる前はあまりフレームワークに良い印象はありませんでした。なんとなく感じていたのは次のようなものでした。 なんかもっさりしていそう(動作が重そう)。 カスタマイズするのがやりにくそう。 ドキュメントが少なそう。 ゼロから作るのが男だぜ!俺のアイディアはフレームにはまらないぜ! 赤松さんも使ってないしー。 ただ、終わったあとには次のように思いました。 やっぱり開発速度は段違い!コードが短いので見直しも楽! 動作速度は検証していないからわからないけど、CakePHPはなんか軽そう(あくまで主観)。 カスタマイズは十分にできることが判明!(つか、カスタマイズしたいところだけ従来の手法でガシガシ書ける) ただ、ドキュメントはやっぱり少ないかも。参考にできるようなコードもあまりなかったような・・・。 今回SNSっぽいものを作りましたが、だいぶデータの作り方、取り出し方などがわかりました。作りたいものもたくさんあるので、しばらくはCakePHPでアプリ開発してみたいと思います。慣れてくればもっと速く作れそうでwktkです。 ■ CakePHP開発のTips あまりエンジニアっぽくない僕がいうのもなんですが、次のようなことに気をつけると開発しやすいのかなぁ、と。あくまで個人的なメモですよ、メモ。 コーディングはやっぱり毎日やらないと忘れる。毎日ちょっとずつでもやりたい。 CakePHPで一番重要なのはAPIドキュメントっぽい。ある程度仕組みが分かってきたらこのドキュメントばかり見てました。デバッグに必須です。 まずは開発環境をセットアップしてから開発すると良いですね。今回初Tracでしたが、かなり便利でした。自分なりの環境をすぐにセットアップできるWikiをまとめておくと良いですね。 開発は見た目から。当初はデザインはミニマムで、と思っていましたがやっぱり開発のノリはインターフェースに左右されますね。綺麗な画面を作ってからやると良いかと思います。 当たり前ですが、フレームワークはかなり論理的に作られています。はまったら一歩ひいて「フレームワークの開発者だったらこういう命令つくるよなぁ」と考えるとすっきりすることが多かったです。 どの言語にもいえることがですが、同じ処理をするのにやり方は複数あります。どのやり方が正しいとか美しいとかは個々人の判断だと思いますが、あまりどれが正しいとか考えずに「とりあえず動くものを」「あとでリファクタリング」と考えれば変にはまってふて寝とかすることがなくなるかと。 ブログで開発レポートをするのは大変だとわかりました・・・。 ■ 謝辞! 最後になりますが、あいかわらず青い人にはお世話になりました。この場を借りて感謝感激す。ブログ上でのコメントもさることながら、チャットでもいろいろ教えてくれてありがとう! ちなみに青い人は若いのにかなり教え上手だと思うのですが、彼の教え方を見ているといくつか特徴があるっぽいのでちょっとまとめてみます。 「えーと、これは忘れてください」 コーディングの仕方はたいてい複数あると思うのですが、青い人はよく「えーと、このやり方は忘れてください」といいながら教えてくれます。あきらかにバッドノウハウ的なもの、まだ難しすぎるものについてはとりあえず選択肢から外し、わかりやすい少数の選択肢から選ばせてくれることが多いように思います。 なお、少数の選択肢を提示するときはちゃんとそれらのメリット、デメリットを提示した上で、自分で考えて選べるようにしてくれます。 「ん?何がしたいんですか?」 複雑なロジックを追っているときには質問をすること自体が難しくなることがあります。そうしたときには常に「何がしたいか」を確認しながら話を進めてくれます。 当たり前かも知れませんが、お互いに「相手がやりたいのはこういうことなのかなぁ」といった適当な推測にはまる(←よくある)前に話を戻すのがうまいっす。 「はいはい」 質問をすると「はいはい、なんでしょう」と言いながら、ヘッドフォンをはずし、手をキーボードから離し、こちらを向いて話を聴いてくれます。基本的なことですが、これができる人って少なかったりしますよね。 ちなみに彼が忙しくて質問に答えられないときはきっちり最初に断られます。忙しいから適当に話きくよー、という態度をされるよりはきっちり断ってもらったほうがいいですよね。 いやー、お世話になったなぁ・・・タイ土産買っていかなくちゃ(あ、買ってきたけど渡してないw)。 ■ あ、そうだ。 この企画で挫折しなかったらCakePHPに$100寄付するという約束でした。以下が証拠ね。ちなみにこの記事を書くのが遅れたのはPaypalに送金していたため(しかも一回失敗してさらに遅れるという・・・)。 ↑ 微力ではありますが、貢献できるところからしておかねば。お世話になりました(&今後もなります)。 というわけでCakePHP修行は終わります!興味のない人にはまったく興味のない内容だったでしょうが、個人的にはかなり楽しかったです。また衝動的にマニアックな企画をするかもしれませんが、そのときはご容赦ください! ※ CakePHP修業は百式管理人がSNSっぽいものをCakePHPで作ろうとして挫折するまでの日記です。前回までのあらすじはこちらへ。

日記のコメントを残せるようにする(CakePHP修行 #44)

さてCakePHP修行。だいぶ終盤に近づいてきました。今回は日記にコメントを残す機能を作りこんでいきます。 ■ モデルやらをいろいろ作る 日記のコメントは当初予定していなかったのでSQLから作り始めます。 まずはSQL。 CREATE TABLE comments (     id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,     post_id INT UNSIGNED,     user_id INT UNSIGNED,     body TEXT,     created DATETIME DEFAULT NULL,     modified DATETIME DEFAULT NULL,     KEY post_id_created (post_id, created) ); これにあわせてAssociationを設定します。UserとPostに対してhasManyの関係を記述します。またCommentモデル&コントローラーも作成します。 ■ コメントの一覧 コメントはそれぞれの日記に対してつくので、posts_controller.phpのdetail()に記述します。えーと、コードは次の一行足しただけですね・・・フレームワークの威力発揮です。簡単すぎる・・・。 $this->set(‘comments’, $this->Comment->findAll(array(‘Comment.post_id’=>$post[‘Post’][‘id’]),null,’Comment.created DESC’)); ちなみに画面はこんな感じ。 ↑ 日記の内容に対してコメントの一覧。自分のものに関しては削除できます。また新規追加もここから可能。 ■ コメントの追加、削除 コメントの追加、削除に関しても基本的にはこの画面でできるので、CommentのViewは作っていません。作ったのはコントローラーの次の記述だけ。 function add($id) {   $this->_checkLogin();   $me = $this->User->findById_hash($_COOKIE[‘my_id’]);   $this->set(‘me’, $me);   if (!empty($this->data)) {     $this->data[‘Comment’][‘id’] = null;     $this->data[‘Comment’][‘post_id’] = $id;     $this->data[‘Comment’][‘user_id’] = $me[‘User’][‘id’];     $this->Comment->save($this->data);     $this->Session->write(‘sys_msg’, ‘Your comment has been added.’);   }   $this->redirect(‘/posts/detail/’.$id); } function del($id) {   $this->_checkLogin();   $me = $this->User->findById_hash($_COOKIE[‘my_id’]);   $comment = $this->Comment->findById($id);   $post = $this->Post->findById($comment[‘Comment’][‘post_id’]);   $this->set(‘me’, $me);   $this->Comment->del($id);   $this->Session->write(‘sys_msg’, ‘Your comment has been deleted.’);   $this->redirect(‘/posts/detail/’.$post[‘Post’][‘id’]); } 超簡単・・・20分ぐらいだったのでは。 これでコメントの追加、削除ができるようになりました。なお、編集は面倒なので省きました。削除して追加する方向でw。こういう機能の追加がやたら簡単ですね。フレームワーク。なめてました。 さてこんなところですかね。アプリとしてはまだまだ甘いところがありますが(エラー処理とか、権限処理とか)、修行としてはいったんここで終了ということにしましょう。あとは最後に今回学んだことをまとめて終わりにします。 挫折する気まんまんでしたが、無事に終わってしまいそうですな・・・。 ※ CakePHP修業は百式管理人がSNSっぽいものをCakePHPで作ろうとして挫折するまでの日記です。前回までのあらすじはこちらへ。

友達の招待・承認系の続きをつくる(CakePHP修行 #43)

さてさてCakePHP修行。ちょっと間が開きましたがさぼっていたわけではありません。細かいところで苦戦していました。 では作業報告。淡々といきます。 ■ 友達の招待(メール編) 友達を自分の友達にするには二通りあります。メールで直接招待する方法と、友達の友達をみていて「この人とつながりたいな」と思ったときです。 まずはメールでの招待からいってみましょう。画面の流れは前回の「SNSっぽい友達系の処理をつくりはじめてみる(CakePHP修行 #38)」で紹介しました。 ここからメールを受け取った人がとる処理を考えます。 えーと、いきなりコード。簡単そうに見えていろいろ面倒でした。 function invite() {   // check login   $this->_checkLogin();   // sys message   $this->set(‘sys_msg’, $this->Session->read(‘sys_msg’));   $this->Session->delete(‘sys_msg’);   // get "my info"   $me = $this->User->findById_hash($_COOKIE[‘my_id’]);   $this->set(‘me’, $me);   $this->pageTitle = ‘Invite a new friend’;   // from start   $this->set(’email_error’, false);   if (!empty($this->data)) {     // error handling     if (empty($this->data[‘User’][’email’])) {        $this->set(’email_error’, true);        return false;      }     // user exists?     if ($this->User->findCount(aa(‘User.email’,$this->data[‘User’][’email’]))) {       // user exists!       $pal = $this->User->findByEmail($this->data[‘User’][’email’]);       if ($this->Friend->findCount(array(‘Friend.user_id’=>$me[‘User’][‘id’],’Friend.friend_user_id’=>$pal[‘User’][‘id’]))) {          $this->set(’email_error’, true);          return false;       }       $this->data[‘Friend’][‘id’] = null;       $this->data[‘Friend’][‘user_id’] = $me[‘User’][‘id’];       $this->data[‘Friend’][‘friend_user_id’] = $pal[‘User’][‘id’];       $this->data[‘Friend’][‘status’] = 0;       $this->Friend->save($this->data);       $inviteLink = WWW_URL.’friends’.DS.’accept’.DS.$this->Friend->getLastInsertID();       $inviteMail = VIEWS.’mail/friends_accept.php’;     } else {       // new user, add user and update hash       $this->User->id = null;       $this->User->save($this->data[‘User’]);       $new_id = $this->User->getLastInsertID();       $new_user[‘User’][‘id’] = $new_id;       $new_user[‘User’][‘id_hash’] = sha1(SHA1_KEY.$new_id);       $this->User->save($new_user[‘User’]);       // add friend relationship       $this->Friend->id = null;       $this->data[‘Friend’][‘user_id’] = $me[‘User’][‘id’];       $this->data[‘Friend’][‘friend_user_id’] = $new_id;       $this->data[‘Friend’][‘status’] = 0;       $this->Friend->save($this->data[‘Friend’]);       $inviteLink = WWW_URL.’users’.DS.’join’.DS.$this->Friend->getLastInsertID();       $inviteMail = VIEWS.’mail/users_join.php’;     }     // send invites     $inviter = $me[‘User’][‘name’];     $msg = implode (file($inviteMail));     eval ("\$msg = \"$msg\";");     $toName = $this->data[‘User’][’email’];     $subject = "[code*code] Invitation from … ".$me[‘User’][‘name’];     mb_send_mail ($toName, $subject, $msg, "From: ".ADMIN_EMAIL);     // write msg, jump     $this->Session->write(‘sys_msg’, ‘Invitaion mail has been sent.’);     $this->redirect(‘/friends/’);   } } 面倒だったのは、今から招待しようとしている人のメールアドレスがすでに登録されているかどうか、また、すでに招待メールを送ったかどうかなどの判断をして場合分けしていくところ。 最初ぐちゃぐちゃとコードを書いていたのですが、わけがわからなくなったので、コーヒー飲んで気分をすっきりさせたあとにゼロから勢いで書きましたw。 なお、これで次のようなメールが送られます。まずは未登録の場合の招待メール。 Hello, taguchi wants you! click a link below to join in! — http://www.codexcode.com/users/join/6 — 次にすでに登録されている場合の招待メール。 Hello, akiyan wants to join your network. click a link below to accept him! — http://www.codexcode.com/friends/accept/8 IDもろだしでよくないのでは、という意見もありますが、それはそれ。面倒なのでこのままにしちゃいました。まぁ、良しとしましょう。 で、これを受け取った人は次のような画面に飛びます(未登録の場合。登録済みの場合は後述)。 ↑ ここで友達からのメッセージを見て登録します。 ↑ …

友達の日記一覧を作る(CakePHP修行 #42)

さてmixiの中の人が「これが一番重いんですよー」と昔言っていたような気がする「友達の日記一覧」を作ります。ちょっと悩んだ。UserとFriendが紐づいているからそこからPostまで見にいけるか、など試行錯誤しましたが、面倒になったので二段階で処理しました。 これって一段階で処理できるようなものなのかな?アソシエーションと$recursiveとか使えばひょっとしてできる?(>青い人)。 ではコード。 // friends’ posts $my_pals = array(); foreach ($this->Friend->findAll(array(‘Friend.user_id’=>$me[‘User’][‘id’],’Friend.status’=>1),’friend_user_id’) as $pal) {   $my_pals[] = $pal[‘Friend’][‘friend_user_id’]; } $this->set(‘posts’, $this->Post->findAll(aa("Post.user_id", $my_pals),null,’Post.created DESC’)); $my_palsにまずは友達のIDを突っ込み、そのIDに該当する日記を引っ張ってきています。ついでに作成日順に並べ替えてみました。 できあがったのはこちら。 ↑ 無事に友達の日記を引っ張ってこれました。数が多くなってきたときの処理作らなくちゃなー。 さて、こんなところですかね・・・次は何だろ。 友達の招待&承認系の処理か・・・これが鬼門。 ※ CakePHP修業は百式管理人がSNSっぽいものをCakePHPで作ろうとして挫折するまでの日記です。前回までのあらすじはこちらへ。

ヘルパーの使い方がわからなかったよ!(CakePHP修行 #41)

CakePHPにはやたら便利そうなヘルパーというものがあるのですが、マニュアルに載っている数々の便利機能が使えなくて四苦八苦してしまいました。 何が足りなかったかというと、コントローラー内における次の一行・・・。 var $helpers = array("time"); 標準でHTMLヘルパーとか使えるからtimeヘルパーもそのままいけるかと思ったじゃないか!自分が気づかなかっただけだけとこれでかれこれ30分悩んでしまったよ・・・。 ↑ これで$time->timeAgoInWords()が使えるようになった! それにしてもタイまで来て食事も抜いた状態で開発ってどういうことだよ・・・でも今夜は報告会。それまでになんとか形にしたい。まぁ、なんとかなりそうかな。夜ぐらいは出かけようかな。 ※ CakePHP修業は百式管理人がSNSっぽいものをCakePHPで作ろうとして挫折するまでの日記です。前回までのあらすじはこちらへ。