Doctrineのupdateの仕方が美しくない

Timestamp/Date/DateTime型だとエラーになる

普通に書くとこんな感じになるけど、エラーになる

<?php
Doctrine::getTable('Foo')->createQuery('f')
  ->update()
  ->set('f.bar', date('Y-m-d H:i:s'))
  ->execute();
#=> syntax error

Doctrine::getTable('Foo')->createQuery('f')
  ->update()
  ->set('f.bar', "'".date('Y-m-d H:i:s')."'")
  ->execute();
#=> ok

どうせだったら、日付書式か、DateTimeクラスを認識するようにすればよかったのに

<?php
Doctrine::getTable('Foo')->createQuery('f')
  ->update()
  ->set('f.bar', new DateTime())
  ->execute();

Doctrine::getTable('Foo')->createQuery('f')
  ->update()
  ->set('f.bar', date('Y-m-d H:i:s'))
  ->execute();

NULLが認識されない

<?php
Doctrine::getTable('Foo')->createQuery('f')
  ->update()
  ->set('f.bar', null)
  ->execute();
#=> syntax error

Doctrine::getTable('Foo')->createQuery('f')
  ->update()
  ->set('f.bar', 'NULL')
  ->execute();
#=> ok

これも内部で===を利用してnull判定をして、自動でnullを挿入すべきだと思う
Doctrine_Record#set()との挙動に違いがあるので、初めてupdate()を使うときは必ずエラーになるかも

次のバージョンでは対応されそうだけど、symfonyに取り込まれないと使えないしなぁ

sfJpMobilePluginを0.0.3にUP

0.0.2までやってからPCサイトを構築していたので、全く動かない状態で放置されてました。
下記のような修正を入れて、とりあえず動くようにしました。

  • 動かなかった部分の修正
  • 絵文字の相互変換周りの修正
  • リダイレクトの時にsession_idを維持するようにした
  • link_toやurl_forなどに対して、DoCoMoの時にguid=ONを付けるようにした
    • jpmobile_link_toとjpmobile_url_forは廃止
    • 副作用でURL生成の際に全部付くようになった
  • 初期入力文字種類を入れるヘルパーを追加(istyleとadd_istyle)
    • istyleはそのまま attr="value" を出力するもの
    • add_istyleはlink_toのoption用で、array("attr"=>"value")を加えて返します。

session_idを常に引き回す仕様だったので、そんな感じになってるけど、Cookieを使える場合は引き回さないようにしたいときを考慮しないとなぁ

Doctrine_Pager_Layoutの使い方

Doctrineに付属しているPagerクラス。
Pagerだけでは、ページングのナンバーリンクの自動生成はできない。

そこで、包括的なDoctrine_Pager_Layoutを利用するようにするとPagerもRangeも同時に利用することが可能。

しかし、Pager_Layoutの生成はちょっと煩雑。

<?php
$pager = new Doctrine_Pager(
  $query,
  $currentPage,
  $perPage);
$layout = new Doctrine_Pager_Layout(
  $pager,
  $pager->getRange('Sliding', $options),
  $urlMask
);

こんな感じなので、Actionに書くより、モデル内なりに入れてしまったほうがいい。

よく使うメソッド

メソッド名 返り値 説明
Pager#execute() Doctrine_Collection 現在のページで表示する分のデータを取得する
Pager_Layout#display() null ナンバーリンクを出力する
Pager#haveToPaginate() boolean ページネイトする必要があるか(1ページしかないかどうか)
Pager#getPreviousPage() integer 前のページNo
Pager#getNextPage() integer 次のページNo
Pager#getLastPage() integer 最後のページNo(ページ数)

ベースURLがうまくいかない

urlMaskを設定する。
インスタンス後はaddUrlMask()による追加しかできないので、なるべくインタンスで決める。
どうしてもの時は、インタンス時に固定部分のみ宣言する*1

また、サンプル通りに{%page_number}を指定すると、/foo/barなURLの場合/foo/page_numberとなってしまう。
単純に相対パスで計算されてしまうから起こるものなので、/foo/bar/:page*2のようにして回避するか、generateUrl()などを使って、urlMaskに強引に設定する。

<?php
$url = $this->generateUrl('route_name');
$layout = new Doctrine_Pager_Layout(
  $pager,
  $pager->getRange('Sliding', $options),
  "{$url}/{%page_number}"
);

リンクURLに動的なパラメータが必要

先程のurlMaskに強引に設定する方法でもいける。

他の方法としてdisplay()にパラメータを渡すことで実現できる。
パラメータが適用できる範囲は、urlMaskとsetTemplate()で指定する書式内

urlMaskはsetTemplate()内では{%url}として扱われる。

$layout = new Doctrine_Pager_Layout(
  $pager,
  $pager->getRange('Sliding', $options),
  "{%foo}"
);
$layout->setTemplate('<a href="{%url}/{%bar}/{%page_number}">{%page_number}</a>');

$layout->display(array('foo' => 'hoge', 'bar' => 'fuga'));
#=> <a href="hoge/bar/1">1</a><a href="hoge/bar/2">2</a>...

ナンバーリンク1つ毎に違うパラメータが必要

Rangeを使って、foreachしてやるしかない

*1:全部を動的に生成する場合は空文字

*2::pageにデフォルト値を設定して省略できるようにしてはいけない

PHP5.2.10でのpear&peclの不具合の解決

この前言ってた問題の解決方法。
PHP5.2.10でpearがおかしい - c/feを参考に、というかそのまま実行したら直った。

やり方は/path/to/php/lib/php/.channelsにあるpear.php.net.regとpecl.php.net.regを5.2.9でインストールしたもので上書きするというもの。

PHP5.2.10のバグ?

pearおよびpeclコマンドが利用できない。

"not supported protocal" って出てインストールができない。
PECLは、ソース取ってきてphpize -> make -> make installで入れられた。(XDebug)
なので、拡張自体が未対応だからって理由ではないみたい。

PHP5.3.0を使ってみた

良かった

  • mbstring.http_outputにtext/***以外のMimeに対応
  • クロージャの実装
  • FileInfoのネイティブサポート
  • XDebugは大丈夫だった
  • 設定ファイルがデフォルトでも分かりやすい(-distと-recommendedから-productと-developに変わった)

困った

  • symfony1.2が動かない
  • eAcceleratorが導入できない

多分その他諸々が動かないだろうから、5.3.2ぐらいから使い時なのかなぁ

screenの自動起動(改)

前回から改良

前回はsudo -sでネストはされなくなったものの、ローカルPCのscreen上からsshした際に、自動起動*1されなかったのでちょっと改良。

if [ $TERM != 'screen' ] || ([ $UID != 0 ] && [ $SHLVL = 1 ]);then
  screen -xR
fi

*1:screenからsshすると、$TERM = screen になってるのが原因