cakePHP2.3 TwitterKit Plugin

https://github.com/elstc/twitter_kit/tree/2.0

database.phpにコンシューマキーなどの設定を書く

twitter_usersテーブルを作成する

コントローラの$componentsに、’TwitterKit.Twitter’を追加する

コントローラーにログイン、ログアウトメソッドをつくる

コントローラーでJsヘルパーと、Twitterヘルパーを読み込む

ビュー(users/login.ctp)をつくる

cakePHP2.3 Schema

参考:CakePHP2.0のコンソールを使ってラクラク自動生成しよう【1/2】

データベースの状態をschemaに保存したり、schemaの内容をもとにテーブルをつくったりできる。

コンソールでapp/Console/cake schemaとやって使う。

schema generate

現在のデータベースの状態をapp/Config/Schema/schema.phpに作成する。
schema.phpが既に存在する場合は、overwirteかsnapshotかやめるかを聞かれる。snapshotはschema_1.phpといった感じで、上書きせずに新規作成する。データベースをいじったら作っておくと便利かもしれん。
–modelとか-mでモデルも指定できる。-m Userとかやると、Userモデルのテーブルだけつくられる。

schema create

schema.phpを基に、データベースにテーブルを作成する。作成するテーブルを選んだりすることはできないようだ。
オプションは下記のようになっているので、もとになるschemaファイルの場所とか名前とかスナップショットナンバーとかを指定できるようだ。

schema dump

schemaファイルをもとにsqlを作成する。
schema dump –write schema.sqlといった感じで使う。–writeオプションがないと、そのままコンソールにsqlが表示される。
上記オプションと似ていて、もとにするschemaファイルを指定できる。

cakePHP Routing

http://book.cakephp.org/2.0/en/development/routing.html

下記のような感じでルーティングができる。:hogeとやると、名前がつけられる。第一引数にURLのパターン、第二引数にアクション先を指定する。第二引数は、controller、action以外に、パラメタも指定できる。第三引数は$this->request->params[‘pass’]を設定できるし、それに:hogeとかでつけた名前も使えるし、その:hogeの条件も正規表現で指定できる。といったなんとなくの理解しかできていないが、便利である。

これは、http://hoge.com/tokyoとか、http://hoge.com/tokyo/とかにアクセスすると、baseコントローラのarea_topアクションに、passとしてtokyoをもってアクセスする。

これは、http://hoge.com/s/tokyo/shop97とかにアクセスすると、shopsコントローラの、viewアクションに、$this->request->params[‘mode’] = ‘s’と、$this->request->params[‘pass’][0] = ’97’をもってアクセスする。

pagineteを使うときに、次のページとかがrouting設定を維持しない場合は、下記のような感じでオプションに設定する。

ちなみに、上記URLの/s/というのはスマホ用URLにつくやつでありまして、スマホ対応をcakePHPだけで対応するつもりで下記をつくってみた。
user_agentチェックはテストしてないし、いい感じかまだ分からない。サイトで調べてcakePHPにしてみた。

cakePHP Androidでセッションが使えない

Androidでセッションがつかえないよー。しくしく。

Cookieはつかえるよー。

http://cakephp.jp/modules/newbb/viewtopic.php?topic_id=2370&forum=3に書いてある、
Configure::write(‘Security.level’, ‘low’);をcore.phpに追加してみたけど解決できない。cakePHPバージョン1だとこれによって色々な設定が自動で変わったらしいが、2系だとあんまり変わらないらしい。と本に書いてあった。

core.phpにセッションクッキー名を登録したらとりあえずできた。

cakePHP こわいRecursive

http://book.cakephp.org/2.0/ja/models/model-attributes.html

recursiveは恐ろしい。怖い人はAppModelに、public $recursive = -1;と書いておけばデフォルトで-1になるようだ。
これをしない場合、デフォルト値は1になる。

  • recursive -1 は、JOINしない。自分だけとってくる。
  • recursive 0 は、自分と自分がbelongsToしているモデルだけとってくる。
  • recursive 1 は、自分とbelongsToとHasManyをとってくる。
  • recursive 2 は、自分とbelongsToとHasManyと、BelongsToとHasMany先が関連しているモデルを一階層分とってくる。

みたいな感じになっているようだ。0は自分だけという意味ではないってことである。それにしても0と1と2はいまいち明確な違いが分からない。

ブログみたいなシステムを考えて、UserがPostを投稿し、PostにCommentがつき、PostにはTagも設定できるようにしてみる。この場合、UserはPostをHasManyしていて、PostはUserにbelongsToしている。PostはCommentをHasManyしていて、CommentはPostにbelongsToしている。また、CommentはUserにもbelongsToしている。また、PostとTagはHABTMになっている(PostはPostsTagをHasManyしている)。

Postをrecursive0でfindすると、PostとUserが得られる。Commentは得られない。なのでやはりbelongsToは得られるが、HasManyは得られないのだ。

Postをrecursive1でfindすると、PostとUserとCommentとTagが得られる。Tagの中にPostsTagが入っている。こういうことを自動的にやってくれているらしい。確かに1の場合はHasManyもとってくるのだ。ただし、HABTMの場合は、中間テーブルを取ってくるのではなく気を利かせてHABTM先のモデルを取ってきてくれるらしい。

recursive2でfindすると、Userの中にPostが入っている。Commentの中にはUserとPostが入っている。なので下手にrecursiveをあげるとすごいことになる。

recursive -1 , 0 までは1クエリで、recursive1で、3クエリ。でもrecursive2で、32クエリ。3で、113クエリ。4で、309クエリ。5で865クエリ。6で2228クエリ。recursive2以上を使う場合は、bindModel()とunbindModel()を使って都度アソシエーションを限定的にする必要がある。

http://d.hatena.ne.jp/takuya15/20071219/1198035692 これは、都度動的にアソシエーションを設定することを簡単にする方法が書いてある。これは結構いいかもと思った。

こうやって動的にunbindModelを使うと、Commentした人の名前だけ4クエリで取得できるからrecursive2以上を使うときはこういうことをしないといけない。

全部モデルにアソシエーションは書いておいて、AppModelでrecursiveのデフォルト値を-1に設定しておいて、基本recursiveを使わないようにしつつ、どうしても必要なときだけ、unbindModelを使うっていう感じでいいかのう。

と思ったらなんかおかしい。commentの件数分、個別にUserをクエリで取得しているようだ。なんだこれは。100件コメントがあったら100クエリするつもりのようだ。CommentにUserをJoinすればいいだけの気がするが。

http://d.hatena.ne.jp/hetima/20070225/1172409266にも同じようなことが書いてある。でもこれは、そもそもrecursive0でよかったのに2にしていただけともいえると思った。
それにしてもやっぱりこわい。HasManyされているやつが、何かにbelongsToしていて、その何かがrecursive2以上に該当する場合は注意が必要だということであります。

まあ要するに効率的にやろうとすると、cakePHPも都度色々コードをしっかり書かないといけないってことかのう。

MySQLのインデックス

参考:
MySQLパフォーマンスチューニングのためのインデックスの基礎知識
大きめのテーブルにカラムやインデックスを追加する際の注意

インデックスの追加
ALTER TABLE phone_book ADD INDEX (last_name)

部分的インデックスの追加
ALTER TABLE phone_book ADD INDEX (last_name(4))

復号インデックス
ALTER TABLE phone_book ADD INDEX (last_name, first_name)

HTML5 File API デスクトップからブラウザにファイルをドロップしてアップロード

デスクトップからブラウザにファイルをドロップできるようにしたい。

参考
Reading files in JavaScript using the File APIs
Drag and DropとFile APIを試す
はまちーのにっき。

File APIと、FormDataというのを使った。ちょっとごちゃごちゃしてるけど、dorpクラスにdorpされたファイルを、順番にupload関数に渡してアップロードしている。cakePHPで受け取ってFileBinderで保存しましたが、FormData使ってファイルを渡すと、$this->request->params[‘form’]に入っていた。dropされたらウインドウの下のに、ボックスが現れて、アップロード中のファイル名が表示されて、アップロード成功したら青くなって、失敗したら赤くなって、完了したらフェードアウトしてる様。$.Deferred()は、終わるまで次の処理を待たせたりできるやつらしいので、使ってみた。全てをしっかり理解していないので、効率的じゃなさそうだけど、とりあえずこれで出来た。

cakePHP Paginator ページ番号が大きすぎる場合のエラーの回避

検索ページでPaginatorを使っていると、3ページ目を表示している状態で、検索条件を変更した結果、3ページ目が存在しなくなり、Not Fountエラーが生じるといったことがありました。これはあんまりよろしくないので、Paginatorを確認しました。

queryではなくnameでパラメタをとっている場合は、下記のような感じにすれば、ページが1に設定されます。
try、catchを使って、エラー発生の場合に下記を実行するとエラーが回避されます。

cakePHP Transitionプラグインのautomate関数の使い方

Transitionプラグインは便利ですね。ソースコードがかなりすっきりします。
セッションをつかって、ページ遷移と、ページ毎に入力された内容を記録してきれるので、ページ遷移チェックと、入力内容の取り扱いが楽になります。

さて、$this->Transition->automate(‘register’,’complete’, null);という関数を使ってエラーが出ていたのでメモします。

この関数は、第一引数に前のページ、第二引数に次のページ、第三引数にバリデーションチェックするモデルを入れます。第四引数にバリデーションメソッド、第五引数にエラーメッセージも入るようです。第三引数がnullというのはカレントモデルを使うという意味です。なのでこの関数はnullと入れてもカレントモデルでチェックします。$this->request->dataの中身をバリデーションチェックします。

register画面で入力してもらい、confirm画面で入力内容を確認してもらい、completeでDBに保存して終了画面を出すという流れのときに、confirmで$this->Transition->automate(‘register’,’complete’, null);を使う場合は、この関数を使う前に、下記のようにやります。

こうすればregister画面で入力された内容が、$this->request->dataに入るので、automate関数で行われるバリデーションチェックがとおるようになります。

これで、confirm画面のviewで、ごちゃごちゃ$this->request->dataにhiddenで入れるような必要がなくなります。

capistrano 使い方メモ cakePHP

もう忘れていたのでメモ。。

まずはプロジェクト用のフォルダ(例:myapp)をつくります。
myappに移動します。
capifyします。
configディレクトリに移動します。
deployディレクトリをつくります。

次に、config/deploy.rbと、config/deploy/development.rbとか、config/deploy/production.rbとかの中身をつくる。

config/deploy.rb

config/deploy/dev.rb

次に、デプロイ先の初期セットアップをする。デプロイ先のサーバに必要なフォルダなどをつくってくれる。

あとは、デプロイしたいときに、デプロイする。

cakePHP アソシエーションの一括save

アソシエーション: モデル同士を繋ぐ参考

PostモデルとTagモデルがhasAndBelongsToManyの関係にあるとき、Postを登録する際に、$this->request->dataが、下記にようになっていれば一括登録できるようだ。

Tagの1というのはtag_idです。
Viewでは、下記のように書けばいいようだ。

コントローラはこれだけで、HABTMのアソシエーションも一括登録してくれる。

削除に関しても、Postを削除するときに、$this->Post->delete()とやるだけで、posts_tagsを一括削除してくれる。
もちろん、これらはModelのアソシエーション設定をしっかりしておくことが前提になる。

追加の一括登録時に、デフォルトではposts_tagsはユニークになるようになっていて、既にデータがある場合は削除してから、新たに追加するようだ。よって、もしposts_tagsなどの中間テーブルに各id以外の情報を登録している場合は、新たに追加する際に削除されてしまう。これを防ぐには、アソシエーション設定のuniqueに、trueではなく、keepExistingという文字列をセットする。これによって関連情報が削除されなくなるようだ。

ちなみに、Tag.idなのに、なんでTag.Tagなんだろうか?このTagは、アソシエーション設定の際のエイリアス名なんだけど、エイリアス名.エイリアス名にするのがルールなのかな??ViewのTagを、Tag.idにすると登録できなかった。TagをTag.Tagにすると登録できた。エイリアス名をTakoにして、TagをTakoにすると登録できて、TagをTako.Tagにすると登録できなかった。これからはおとなしく、viewではエイリアス名のみでいきます。

cakePHP HABTMのテーブルをJOINして検索する

postsとtagsはHABTMであるときに、tag_idの1か2をもつpostのみを抽出する場合、postsにposts_tagsをjoinして、更にtagsをjoinした上で、tag_idを条件に設定してfindする。

left joinとinner joinの違いは、これ。inner joinはjoin元とjoin先が両方共情報があるものだけ抽出される。left joinは左優先。right joinは右優先。

Subversion cakePHPプロジェクトの作業コピーつくったら最初にやることのメモ

cakePHPのプロジェクトのリポジトリをつくって、作業コピーをつくったらignore設定とか色々あるので、メモする。いつもignoreを微妙に忘れるし。

subversionのチェックアウト

作業コピーが終わってからの作業のshをつくってみた。
rmとかignoreはかなり冗長的な感じだけど、これで多分動いたみたい。
作業コピーに移動してから実行する。