2012年9月26日水曜日

[CakePHP]$form->create()の第一引数

このドキュメントみても$form->create()の第一引数にnullを入れることで、
そのformは特定のモデルを使用しないようにすることができると書いているが、
 本当のところはfalseを入れなくてはだめみたい。
    <?php
        echo $form->create(false,array(
            'type'=>'post',
            'action'=>'mkHtml'
        ));
        echo $form->input('goodsUrl',array('id'=>'goodsUrl'));
        echo $js->submit("作成",array(
            'url'=>'mkHtml',
            'update'=>'#data'
        ));
        echo $form->end();
        echo $js->writeBuffer(array('inline'=>false));
    ?>
てviewに書くと、出力されるhtmlは以下のようになる。
<input name="data[goodsUrl]" type="text" id="goodsUrl" /> 
もし、$form->create()の第一引数にfalseを設定しなかったら以下のように
モデルが配列の最初のレベルに来る。
<input name="data[theme][goodsUrl]" type="text" id="goodsUrl" />
 現在のコントローラーのデフォルトのモデルは"theme"。

 ※CakePHPのバージョンはcakephp-cakephp-1.3.15-9-gacd25c3.zip

[SVN]無料のSVNサーバ Assembla

いつもはノートPCで開発しているけど、たまにはデスクトップの端末で
開発をしてみたい、と思い、ソースコードをサーバに置こうと考えた。

無料でsvnのレポジトリが作れてしまう、以下のサービスを使ってみた。

https://www.assembla.com

今のところ非常に使いやすい。

やり方は、現在のSVNのサーバを以下のようにコマンドラインでエクスポート

svnadmin dump 【リポジトリロケーション】 > 【バックアップファイル名】
 
 出力された【バックアップファイル名】はzip圧縮する。
 
でassemblaのプロジェクトの管理画面のImport/Exportタブから
zipファイルをアップロードする。
 
何分か待つ。
 
画面がrunninng..的な画面でとまったように見えるけど、
しばらく経つと、数字が上がりはじめる。
 
 
【気になる点】
色んなブログで無料で無期限で使える(容量制限はあるみたい)
と書いてあるけど、本当に無期限なのかな。
assemblaのサイトに説明が見つからなかった。 
 
 【注意点】
移行した後、他の端末でchckoutする場合は元の端末と同じURLとなるように
checkoutする。外部サービスのcallbackURLとして設定しているから。 

2012年9月22日土曜日

[Error記録]Twitter Oauthログイン時のエラー

今朝最初にログインしようとしたとき、こんなエラーが出た。


で、修正も何もせずにすぐに同じようにログインしようとしたら、
正常にログインできた。

なんなんだろ、request_tokenがTwitter側からうまく帰ってくる前に処理が進んじゃってるからかな。


 【2012/10/03追記】
この現象、朝PCを起動して初めてログインしようとすると発生するんだよな。
今日も発生したので、「戻る」を押して、もう一度「許可」を押したら発生した。
その際、
$json = $consumer->get($accessToken->key, $accessToken->secret, 'http://twitter.com/account/verify_credentials.json', array());
で得られる$jsonをログに出力してみたんだけど、その結果が、
 {"error":"Could not authenticate you.","request":"\/account\/verify_credentials.json?oauth_consumer_key=・・・・・

"Could not authenticate you."というメッセージがあった。

これで検索すると、Could not authenticate you
というページでtwitterのリクエスト先のURLにhttpsをつければよい、
といった意見があったので試してみよう。
またユーザ側のクライアントの設定で「常にSSLを使用する」、といった設定をしている 場合に発生するとのこと。 クライアントとはおそらくブラウザのこと。 こちらも試してみよう。

【2012/10/03追記②】

ちなみに、本日の追記の時は、一度失敗したCallbackURLをもう一度
ブラウザでたたいたので、シミュレーションだったのだが、先ほど、
お昼休みにPCを落として、またログインしてみたら発生して、
ログを見たら新たな発見があった。
2012-10-03 16:50:15 Debug: requestToken
2012-10-03 16:50:15 Debug: oauth_token=XXXXXXXXXXXXXXXXXXXXXXXXX&oauth_token_secret=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx
2012-10-03 16:50:15 Debug: accessToken
2012-10-03 16:50:15 Debug: 
2012-10-03 16:50:15 Debug: Notice (8): Trying to get property of non-object in [C:\xampp\htdocs\rakuzon\app\controllers\users_controller.php, line 55]
2012-10-03 16:50:16 Debug: json
2012-10-03 16:50:16 Debug: {"error":"Could not authenticate you.","request":"\/account\/verify_credentials.json?oauth_consumer_key=
requestTokeをセッションから取得することはできているのだが、
accessTokenをTwitter側から取得できていない、ということがわかった。
つまり以下がうまくいっていないようだ。
$accessToken=$consumer->getAccessToken('http://api.twitter.com/oauth/access_token',$requestToken); 
【2012/10/04追記】
上記のURLをhttpからhttpsにしてもダメだった。
なんでだろうなー。

【2012/10/05追記】
何も修正していないのに、なぜか今日エラーが出ずにいけた。

2012年9月21日金曜日

[PHP]boolean のfalseはechoしても何も表示されない。

PHPのTRUEと FALSEについて 値を返すというけれど、なぜ「1」かブランク(何もなし)なのでしょうか?


このサイトによると以下とのことです。
どおりでなんにも表示されないと思った。


-----以下抜粋---------------------------------------------------------------------------
echo false;
とやると、falseがstring型へ自動型変換という手順を踏んでechoの対象になりますが
PHPの場合は falseをstring型へ変換すると ""(空文字列)になります。
(別の言語では"false"という文字列に変換されるものが多いですね)
よって、出力されません。
----ここまで----------------------------------------------------------------------------

[CakePHP]layoutってcontrollerがrenderする前に処理してないか?

※このpostは前半部分間違った推測をしています。
 後で本当の原因がわかったので、最後に追記として書いています。


全てのControllerで共通してdefault.ctpというlayoutを使っている。
そこには、もしAuth認証でログイン済みであれば、ユーザ名と
プロフィール画像を表示するようにしている。

つまり、全ての画面で共通なロジックだからだ。

もちろんlogoutでレンダーされる画面にもそのlayoutが適用
されるんだけど、なぜかlogout画面でもユーザ名と
プロフィール画面が表示されてしまう。
赤で囲った部分はログイン状態でなければ表示されないはずの部分。



仮説だが、
「layout内の処理はControllerのrender処理の前に行われる。」
のではないか。

ちなみに、ログアウト画面表示後、TOP画面等を表示すると、
ちゃんとユーザ情報などは表示しないでくれていた。
なので、logout()の処理自体はどこかで動いていて、セッションから
ログイン情報を消してくれているはず。
そして、layout内の<?php echo $content_for_layout ?>を赤枠の部分より
上に配置してみたが、相変わらず表示された。

つまり、viewの部分がlayoutより上にあったとしても、処理としてはlayoutが先に行われて
いるということではないか。

仕方がないので、layout内でlogout後かどうかを判別する仕組みを入れた。
コントローラー側は以下の3行目にログアウト後であるフラグを入れた。
ちなみに、ここで$this->session->write()を使わず$this->set()を使ったのは、
前者だと、おそらく次以降の遷移後にもフラグが立ちっぱなしになってしまうので。
setは一度のrenderでしか有効でない。
 public function logout(){
  $this->Auth->logout();
  $this->set('logoutFlg',true);
 }


つづいてlayout側。(抜粋)
2行目の&&以降で、フラグに値が入っているかを確認している。
入っていなければ、logout後ではないのでユーザ情報を表示する。
 <?php
  if(!empty($auth['User']['id']) && empty($logoutFlg)){
   echo $this->element('loginInfo');
  }else{
   echo $this->element('loginLink');
  }
 ?>

※本当はせっかくtrueが入るからempty()とか使いたくなかったけど、
logout後以外は絶対に値がはいらないから$logoutFlgみたいにbooleanで
判別しようとすると、エラーになっちゃうんだよね。

こうすれば、ログアウト画面のユーザ情報は消えてくれた。
つまり、まとめると、

「layout内の処理はControllerのrender処理の前に行われる。
ただし、layout内でController側で設定された変数が必要な場合は、
Controllerの処理を待って処理をする。」

あくまで仮説です。
誰か、本当のところを知っている人教えて下さい。


【追記】
すみません。書いた直後に原因が発覚しました。
上で書いたことと全然違ってました。

自分はAppControllerのbeforeFilterで
    function beforeFilter(){
       $this->Auth->allow('*');
       $auth=$this->Auth->user();
       $this->set('auth',$auth);
    }
としていました。
$this->Auth->logout()はsessionにあるユーザ情報は消しますが、
set()された$authは消しません。(auth.phpのソースコード参照)
なので、logoutアクションでrenderされる画面にユーザ情報が表示されて
しまったということです。
そこで、Authのユーザ情報の取り出しはview側(layout)にて行うように
修正したところ、上記で追加したlogoutFlg無しでも正常にlogout画面が
ユーザ情報無しで表示されました。

そもそも、AppControllerにAuthのユーザ情報の取り出し処理を入れていた理由は、
全画面でやるので、全viewのファイルに書くのは嫌だなと思っていたからです。
でも、layoutに書いておけば一箇所でよいので、layoutに移しました。









[CakePHP]viewで繰り返し使う部分を外だしする(elements)

elementsという機能を使えば、viewで度々使う部分を外部ファイルにして
呼び出して使うことができる。

たとえば、どの画面にも出ている「○○さんがログイン中」とか。

以下のサイトがわかりやすい。

CakePHPでビューからエレメントを呼び出す

[CakePHP]AppControllerと普通のControllerのcomponentの設定の関係

AppControllerで設定したcomponentを普通のControllerで重ねて設定すると
うまくマージしてくれないみたい。

以下のようにapp_controller.phpで設定するとする。
var $components = array('Auth','Session');
そして普通のControllerであるusers_controller.phpに以下のように設定するとする。
※まぁ、AppControllerで設定しているものを重ねて設定することはないのだけど、
 消し忘れた場合など。
var $components = array('Auth');
すると、以下のようなエラーが発生
Notice (8): Trying to get property of non-object [APP\controllers\users_controller.php, line 51]

 たぶん、コンポーネントの設定のマージがうまくいっていないんだろうな。
以下で指摘した点と同じ原因かもしれない。

[CakePHP]AppController でコンポーネント設定するとsessionコンポーネントが使えない。

なので、users_controller.phpの方のcomponentsの設定を消したらう動いた。

※CakePHPのバージョンはcakephp-cakephp-1.3.15-9-gacd25c3.zip


※追記:
この後、もう一度、users_controllerの方のcomponentの設定を戻してやっても
動いた。原因は違うところにありそうです。すみません。