digital matter

2011 年 2 月 のアーカイブ

symfonyで行の並び順を指定できるビヘイビアを使ってみた

今回はこちらを参考に、csDoctrineActAsSortablePluginを使ってみました。

$ ./symfony plugin:install csDoctrineActAsSortablePlugin
>> plugin    installing plugin "csDoctrineActAsSortablePlugin"
>> sfPearFrontendPlugin downloading csDoctrineActAsSortablePlugin-1.5.1.tgz ...
>> sfPearFrontendPlugin Starting to download csDoctrineActAsSortablePlugin-1.5.1.tgz
>> sfPearFrontendPlugin (6,795 bytes)
>> sfPearFrontendPlugin .
>> sfPearFrontendPlugin .
>> sfPearFrontendPlugin ...done: 6,795 bytes
>> sfSymfonyPluginManager Installation successful for plugin "csDoctrineActAsSortablePlugin"
>> sfSymfonyPluginManager Installing web data for plugin

使い方はschema.ymlのモデルのActAsにSortableを追加してやればいいだけです。

ModelName:
  actAs:
    Timestampable: ~
    Sortable: ~

これで、自動的にpositionというbigintのカラムが生成されて、ソート順が数字で指定できるようになります。

併せて順序を入れ替えるための便利なメソッドが使えるようになります。

http://www.symfony-project.org/plugins/csDoctrineActAsSortablePlugin/1_5_1?tab=plugin_readme

今回、I18nの下にSortableを置いたら、インデックス名がやたら長くなってしまい、CREATE文でエラーが出るようになってしまいました。

SQLSTATE[42000]: Syntax error or access violation: 1059 Identifier name '******_*********_***_*******_******_*****_translation_position_sortable_idx' is too long.

plugins/csDoctrineActAsSortablePlugin/lib/template/Sortable.php

  protected function getSortableIndexName()
  {
    return sprintf('%s_%s_%s', $this->getTable()->getTableName(), $this->_options['name'], $this->_options['indexName']);
  }

ということなので、nameとindexNameを指定して短くできそうです。

と言ってもposition_sortable分しか短くできないのですけど。

最終的には、schema.ymlの方でtableNameをdatabase_name.table_nameで指定していたのですが、これをtableName: table_nameにするだけで対応できました。

関連する投稿

MySQL Workbenchからschema.ymlを生成する

MySQL Workbenchからsymfony+Doctrine用のschema.ymlを書き出せないかなぁとつぶやいたら@hidenorigotoさんに教えていただいたので試してみました。
http://twitter.com/#!/hidenorigoto/status/38153994970988544

MySQL Workbench schema exporter

MySQL Workbench schema exporterは、MySQL WorkbenchプラグインのMySQL Workbench Doctrine Pluginにインスパイアを受けて開発されたようです。
が、こちらのプラグインはすでにメンテされていないようです。

開発終了した理由がぞろぞろ書いてありますが、要約すると「LUAが…」ってことみたいです。

MySQL Workbench schema exporterはPHPで書かれています。MySQL Workbenchのmwbファイルを読み込んでパース、フォーマッタを指定してそれぞれの形式を書き出すようです。
ちなみにmwbファイルはZIP圧縮されたXMLです。あと、SQLite3のデータが入ってました。

注意点としてPHP 5.3以降でないと実行できません…
いつものdebian環境では5.2を使ってるので、Windows版の5.3をダウンロードしてインストールしました。

まずはexampleディレクトリに移動します。

C:\Users\test\Downloads\johmue-mysql-workbench-schema-exporter-7d08e29\example>php -v
PHP 5.3.5 (cli) (built: Jan  5 2011 20:36:18)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

example/data/にtest.mwbがあり、サンプルではこのファイルを使います。

ちなみにサンプルのEER(Enhanced Entity-Relationship) diagramはこんな感じです。

test.mwb

C:\Users\test\Downloads\johmue-mysql-workbench-schema-exporter-7d08e29\example>php .\doctrine1.yaml.php
<textarea cols="100" rows="50">Bureau:
  tableName: mydb.bureaus
  columns:
    id:
      type: integer(4)
      primary: true
      notnull: true
      autoincrement: true
    room:
      type: string(45)
  indexes:
    testIndex:
      fields: [room]
      type: unique
  options:
    charset: utf8
    type: InnoDB

Email:
  actAs:
    timestampable:
  tableName: mydb.emails
  columns:
    id:
      type: integer(4)
      primary: true
      notnull: true
      autoincrement: true
    email:
      type: string(255)
    users_id:
      type: integer(4)
      primary: true
      notnull: true
  relations:
    User:
      class: User
      local: users_id
      foreign: id
      foreignAlias: Emails
      onDelete: no action
      onUpdate: no action
  indexes:
    fk_Emails_Users:
      fields: [users_id]
  options:
    charset: utf8
    type: InnoDB

User:
  actAs:
    timestampable:
  tableName: mydb.users
  columns:
    id:
      type: integer(4)
      primary: true
      notnull: true
      autoincrement: true
    name:
      type: string(255)
  options:
    charset: utf8
    type: InnoDB

UsersBureaus:
  tableName: mydb.users_bureaus
  columns:
    users_id:
      type: integer(4)
      primary: true
      notnull: true
    bureaus_id:
      type: integer(4)
      primary: true
      notnull: true
  relations:
    User:
      class: User
      local: users_id
      foreign: id
      foreignAlias: UsersBureauss
      onDelete: no action
      onUpdate: no action
    Bureau:
      class: Bureau
      local: bureaus_id
      foreign: id
      foreignAlias: UsersBureauss
      onDelete: no action
      onUpdate: no action
  indexes:
    fk_users_bureaus_bureaus1:
      fields: [bureaus_id]
  options:
    charset: utf8
    type: InnoDB

Testtable:
  tableName: mydb2.testtable
  columns:
    id:
      type: integer(4)
      primary: true
      notnull: true
  options:
    charset: utf8
    type: InnoDB
</textarea><br><br>1 MB used<br>0.055 sec needed

というわけで、リレーションやインデックスなども書きだされるようです。

HTMLのタグはdoctrine1.yaml.phpの中に書いてあるので、CLIから使うときは適当に外してください。

timestampableなどのビヘイビアに関しては、コメント欄に書くことで出力できるようです。

{d:actAs}
  actAs:
    timestampable:
{/d:actAs}

この仕様はちょっと微妙な気が…

created_atとupdated_atがあったらtimestampable付けるとかの方が楽だなぁ、と。

作っちゃった後の全テーブルにコメント指定して回るのはちょっと辛いので。

サーバにPHP 5.3が入っているなら、symfony taskでmwbからschema.ymlの生成と、ActAsの追加をやってしまうのがいいかな、と思いました。

うーん、個人的にはMySQL Workbench上で完結したいから、プラグインの方が便利な気はするんですけどねぇ。LUAとは言わなくてもPythonスクリプティング対応しているようなので、Pythonに書き直すとか…

この後、60テーブルほどのファイルを変換してみましたが、問題なく実行できました。

追記(2011/02/19)

注意点がいくつかあります。

というか、致命的かも。

1.NOT NULLのchar型にDEFAULT値”を入れるとNULLに変換される

これはDoctrineのbuild –sqlがおかしいかな…

column_name:

  type: char(3)

  notnull: true

  default: ”

column_name char(3) DEFAULT NULL NOT NULLとかいう矛盾を持ったクエリが生成されます。

ちなみにvarcharは大丈夫です。

default: ”の行は削除しましょう。

2.DECIMALやFLOATの最大桁数と少数点の値が逆になる

ひどい。

例えばMySQL WorkbenchでDECIMAL(15,4)と指定したカラムがDECIMAL(4,15)と書き出されます。

column_name:

  type: decimal(4,15)

  notnull: true

  default: ’0.0000′

もちろん、ちゃんとMySQL Workbenchからクエリのエクスポートをしたときは15,4になります。

置換で何とか…

うーん、やっぱりMySQL WorkbenchでDBをあらかじめ作成しておいてから→doctrine:build-schema→schema.yml修正が妥当かなぁ。

関連する投稿