symfony DoctrineのTIPS その2
- カテゴリ :
- バックエンド(プログラミング)
- タグ :
- Tech
- Doctrine
こんばんは。牧野です。
最近、会社で使っているPCも自分用のノートPCもハードディスク容量が少ないせいか、重く感じるようになっていました。
そんな時に発表されたsonyの新しいVAIO Z。シミュレータで出てきた価格にびっくりしつつも、心ひかれています。。。
さて、今日はsymfonyと使うDoctrineのTIPSその2です。ここのところ、またsymfonyを触る機会が増えていました。
1.生SQLを使う
schema.ymlをちゃんと書けばDQLでたいていのことはできるのですが、そのままSQLを実行してデータを取りたい時にどうぞ。
Doctrine_Connectionオブジェクトがあれば、とりあえず何でもできます。
2.データ更新時の注意
Doctrineは関連するデータを簡単に引っ張ってこられるところが便利なのですが、データ更新をする際には気をつけたいことがあります。
あるモデルオブジェクトのデータ変更内容を確定させる前に、同じモデルオブジェクトを取得するようなことをすると、確定前のデータ変更内容はリセットされます。
具体例な例を見てみましょう。
config/schema.yml
DBの中身
lib/model/doctrine/DvdPackage.class.php
テスト用のアクションクラス
関連するdvd_packageデータの発売日も1ヶ月遅らせようとしています。
結果をみると、、
肝心のidが1のdvd_packageデータが2010-03-03のままで、更新できていません。
これは、changeAllSeriesReleaseDateメソッドのforeachの部分が原因です。
$dvdとして自分自身を取得した際に、保存前のrelease_dateが消えてしまったのです。
保存前、というのが問題なので、
$this->release_date = $date_string;
の後に
$this->save();
を入れれば大丈夫です。
今まで2回ほどこのようなケースに出会ったことがありましたので、どこかで役立つことがあるかもしれません。
最近、会社で使っているPCも自分用のノートPCもハードディスク容量が少ないせいか、重く感じるようになっていました。
そんな時に発表されたsonyの新しいVAIO Z。シミュレータで出てきた価格にびっくりしつつも、心ひかれています。。。
さて、今日はsymfonyと使うDoctrineのTIPSその2です。ここのところ、またsymfonyを触る機会が増えていました。
1.生SQLを使う
schema.ymlをちゃんと書けばDQLでたいていのことはできるのですが、そのままSQLを実行してデータを取りたい時にどうぞ。
Doctrine_Connectionオブジェクトがあれば、とりあえず何でもできます。
- $con
= Doctrine::getTable(適当なテーブル)->getConnection(); - $con
= Doctrine_Manager::getInstance()->getConnection(コネクション名); - $sql
= "select * from hogehgoe"; - $results
= $con->fetchAll($sql);
2.データ更新時の注意
Doctrineは関連するデータを簡単に引っ張ってこられるところが便利なのですが、データ更新をする際には気をつけたいことがあります。
あるモデルオブジェクトのデータ変更内容を確定させる前に、同じモデルオブジェクトを取得するようなことをすると、確定前のデータ変更内容はリセットされます。
具体例な例を見てみましょう。
config/schema.yml
- DvdSeries:
tableName: dvd_series columns: id: type: integer(4) primary: true autoincrement: true series_title: type: string(255) notnull: true - DvdPackage:
tableName: dvd_package columns: id: type: integer(4) primary: true autoincrement: true dvd_series_id: type: integer(4) number: type: integer(4) package_title: type: string(255) price: type: integer(11) release_date: type: date relations: DvdSeries: local: dvd_series_id foreign: id class: DvdSeries foreignAlias: DvdPackages
DBの中身
- mysql>
select * from dvd_series; - +----+-----------------+
- |
id | series_title | - +----+-----------------+
- |
1 | シーズン1 | - +----+-----------------+
- 1
row in set (0.00 sec) - mysql>
select * from dvd_package\G - ***************************
1. row *************************** id: 1 - dvd_series_id:
1 number: 1 - package_title:
テストタイトルその1 price: 3000 release_date: 2010-03-01 - ***************************
2. row *************************** id: 2 - dvd_series_id:
1 number: 2 - package_title:
テストタイトルその2 price: 4000 release_date: 2010-04-02 - ***************************
3. row *************************** id: 3 - dvd_series_id:
1 number: 3 - package_title:
テストタイトルその3 price: 4000 release_date: 2010-05-03 - ***************************
4. row *************************** id: 4 - dvd_series_id:
NULL number: NULL - package_title:
テストタイトル price: 3000 release_date: 2010-06-04 - 4
rows in set (0.00 sec)
lib/model/doctrine/DvdPackage.class.php
- class
DvdPackage extends BaseDvdPackage - {
/** * 同一シリーズのDVD発売日をまとめてずらす。 * */ public function changeAllSeriesReleaseDate($date_string) { $old_timestamp = strtotime($this->release_date); $new_timestamp = strtotime($date_string); $today_timestamp = strtotime(date('Y-m-d')); $this->release_date = $date_string; //変更前、または変更後の発売日が以前の場合は、他のDVDの発売日は変更しない。 if ($today_timestamp > $old_timestamp || $today_timestamp > $new_timestamp) { return $this->save(); } $change_timestamp = $new_timestamp - $old_timestamp; if ($this->DvdSeries) { foreach ($this->DvdSeries->DvdPackages as $key => $dvd) { if ($dvd->id == $this->id) { continue; } $this->DvdSeries->DvdPackages[$key]->release_date = date('Y-m-d', strtotime($dvd->release_date) + $change_timestamp); } } return $this->save(); } - }
テスト用のアクションクラス
- class
testActions extends sfActions{ public function executeIndex(sfWebRequest $request) { echo "<pre>"; $con = Doctrine::getTable('DvdPackage')->getConnection(); //dvd_seriesをもつデータ $test_dvd = Doctrine::getTable('DvdPackage')->find(1); var_dump($test_dvd->toArray()); $test_dvd->changeAllSeriesReleaseDate('2010-04-01'); var_dump($test_dvd->toArray()); echo "</pre>"; exit; } - }
関連するdvd_packageデータの発売日も1ヶ月遅らせようとしています。
結果をみると、、
肝心のidが1のdvd_packageデータが2010-03-03のままで、更新できていません。
これは、changeAllSeriesReleaseDateメソッドのforeachの部分が原因です。
$dvdとして自分自身を取得した際に、保存前のrelease_dateが消えてしまったのです。
保存前、というのが問題なので、
$this->release_date = $date_string;
の後に
$this->save();
を入れれば大丈夫です。
今まで2回ほどこのようなケースに出会ったことがありましたので、どこかで役立つことがあるかもしれません。
