Archive for the 'symfony' Category

symfony doctrineでmigrate

Posted by ゆのじ on 7月 16th, 2010

symfony1.4.6、doctrineで、migrateしつつ開発、のテスト中。思いの外はまりどころが多いので個人的メモ。誤解している、使い方がオカシイなどありましたらご指摘ください。ちなみに、正しい使い始めのための手順はこちらが詳しい。

型にtextだとかdatetimeだとか書いておくとはまる
型にtype: textだとか書いておいても、普通に使う分には使えてしまう。ただ、doctrine:migrateすると、syntax errorが出てしまう。どうも、textとだけ書いておくと、hoge: { type: text } をSQLにするとき、hoge text()と構築してしまってエラーになる模様。string(長さ)と指定しておけばOK。
同様に、datetimeもmigrateを使わないかぎり通るのだけど、migrate使うとエラー。timestampとしておく必要がある。

トランザクション使ってないのでエラー出たら面倒
migrateタスクの中でトランザクション処理を行っていない模様(嘘。ちゃんと書いてあった)。そのせいで、上記のようなエラーがでると中途半端にクエリが通った状態になってしまう。運用データがなければ(開発サーバであれば)、doctrine:drop-dbしてdoctrine:create-dbして、doctrine:migrateすればいいが、そうでない場合は結構注意が必要。つうかトランザクションくらい走らせてください>中の人

お気軽に使えそうで思ったよりはまる。ただ、継続的に開発し続ける手合いにはこれがないと困るので、はまらないように使ってみようと思う。

 

追記:
sfDoctrineMigrateTaskとMigrateを読んでみると、beginTransactionがちゃんと書いてあった。クエリログを見てみると確かにトランザクションは掛けている。なんでdry-runするだけで問題が起こったのかちょっとわからず。

100716 20:30:38     2 Connect   shell@localhost on shell
                    2 Query     SET NAMES utf8
                    2 Query     SET NAMES 'UTF8'
                    2 Query     CREATE TABLE migration_version (version INT) ENGINE = INNODB
                    2 Query     SELECT version FROM migration_version
                    2 Query     START TRANSACTION
                    2 Query     SELECT version FROM migration_version
                    2 Query     CREATE TABLE (略
                    2 Query     ALTER TABLE (略
                    2 Query     CREATE INDEX (略
                    2 Query     commit
                    2 Query     SELECT version FROM migration_version
                    2 Query     UPDATE migration_version SET version = 12
                    2 Quit

追記:

おそらく、MySQLのautocommitを殺していないからだと推測していて、接続時にまずautocommitをオフにするクエリを投げる方法を調査中。symfonyそのもののソース書き換えちゃうのが早いのだけどそれはちょっとねぇ。

追記:

もっと根本的な話だった。MySQLはCREATE TABLE的なDDLをrollbackできない。なんだそれ。あほかい。テンポラリテーブルこさえるような実装だったりするとgdgdになるってわけで。

symfony(というかpropel)でのmysql関数処理バグ

Posted by ゆのじ on 5月 22nd, 2008

結構根が深くていやになったのだが、表題の問題。symfonyの(というかPropelの問題なので以降Propelの)Criteriaの記述で、集約関数を書きたくて調べていたのだが、addSelectColumnという関数で下記のように定義してやればいいっぽい。

$c->addSelectColumn('SUM('.TablePeer::TARGET_COLUMN.')');

このとき、これだけなら問題はあるもののひとまずエラーにはならない(後述)。だが、たとえば時刻の差分(秒)の合計をとりたい場合、SUM(UNIX_TIMESTAMP(col1) – UNIX_TIMESTAMP(col2))のようにしたくなる。それを書いてみたのが下記。

$c->addSelectColumn('SUM(UNIX_TIMESTAMP('.TablePeer::FINISHED_AT.')-'.
                          'UNIX_TIMESTAMP('.TablePeer::STARTED_AT.'))');

これが見事に刺さる。

調べてみると、見事にPropelのBUGで、#425 (Bug in BasePeer::createSelectSql) – Propel – TracによればPropel本体としては既にfixedというステータス。これがsymfony側には反映されていなくて刺さるということのようだ。回避策は今のところこのTracに記述されているworkaroundをそのまま実行するしかない。念のため書き写しておくとこうなる。

577 $selectClause[] = $columnName; // the full column name: e.g. MAX(books.price)
578
579 $parenPos = strrpos($columnName, '(');
580 $dotPos = strpos($columnName, '.', ($parenPos !== false) ? $parenPos : 0);

下線部が追加部分。strRposにするのと、その下の行を追加する。これでひとまずエラーはなくなる。

エラーは無くなるのだが、addSelectColumnを使ったクエリ、明示的にクリアしていないにもかかわらず選択カラムがリセットされてしまって、addSelectColumnで追加したカラムのみになってしまうという問題がある。これが仕様なのかはともかく、doSelectしたときにhydrateできなくて刺さったり、いろいろと問題がある。この辺の本当の意味での正しいクエリの投げ方、どうすればいいんだろう?

追記:とりあえずメソッドを眺めていたら、TablePeer::addSelectColumns(Criteria $c)というメソッドを見つけた。とりあえず、addSelectColumnの先頭でaddSelectColumns($c)とかやってやると一通り追加される模様。

symfonyレイアウトの崩れ

Posted by ゆのじ on 5月 4th, 2008

またもやsymfonyネタ。

symfonyのadmin generatorは便利だが、どうもレイアウトの崩れが気になって仕方がない。例えば下記のような崩れが見受けられる。

previous previous2

左はadminのチェックボックスだけ右に3pxほどずれているし、右は項目をまとめるborderがずれている。どうしても気になって仕方がなかったのでCSSを直すことにした。直すためのcssは下記のような感じ。これをmain.cssあたりで読んでやればいい。

* html #sf_admin_container div.form-row
{
  zoom: 100%;
}

#sf_admin_container div.form-row:after
{
  content: " "; clear: both; height: 0; display: block; visibility: hidden;
}

#sf_admin_container div.form-row .content
{
  padding-left: 0px;
  float: left;
}

結果、下記のようになり、きれいに表示されるようになる。

after after2

 やっていることは簡単。どうもきちんとチェックボックスが並ばないのは、label要素の右にdivがあってその中の要素、がどうもずれるらしい。力業だが、label要素の右にくるdivもfloat:leftで積んでしまえばこのズレは正常に処理されるようになる。これがcssの3つめのブロックでの指定。

 だがこれだと、上で項目ごとのborderがずれると指摘した問題、これがさらにひどくなって全部の項目で中身がborderから外れる。これはdivの中身がfloatしかないと、divの範囲の外に中身がはみ出るよ、という問題で割とよく知られている。
 どう対処するかというと、clearfixとか言われている方法をとる。今回やってるのはどうせ内部用でしか使わない部分なので(admin generatorで外部向けアプリはつくらんよね?)、validでないことはあまり気にしない。(cssの1つめのブロックにあるzoomはIE用、後ろのafterはその他ちゃんとcssを解釈するブラウザ用。情報源はこの辺)。これできちんと表示された。

 これだけでも開発のモチベーションがあがるかもしれない。誰も困っていないのか、ウェブ上では同じような情報はすぐには見あたらなかった。もし既知の問題だったり似たようなレポートがあればコメントで教えていただければ幸い。