symfony1.0で作っておくと良いユーティリティ
僕みたいにORM嫌いが、ORM大好きなひとのコードをリファクタリングしているときに、よくやるのがORの影響で膨大になったクエリを減らす作業です。
symfony1.0 (Propel)だと
PropelでフォルトのJOINをつかっていると気づくとレコード数×外部キーのクエリが発効され、本来10以下で済むはずのクエリが50を超えてたりします。
そんなときJOINをつかったり、WHERE〜INをつかってクエリを減らしますが、WHERE〜INを作ったり、クエリ結果をハッシュで持てるようにするときに似たようなfor分を書きまくります。
という訳でこんなのがあれば便利です。
<?php class PropelUtil { public static function arrayToPrimaryKeyMap($objects_array) { $r = array(); if (is_array($objects_array)) foreach ($objects_array as $v) { if ($v instanceof Persistent) $r[$v->getPrimaryKey()] = $v; } return $r; } public static function getListInPrimaryKeys($objects_array) { $r = array(); if (is_array($objects_array)) foreach ($objects_array as $v) { if ($v instanceof Persistent) { $val = $v->getPrimaryKey(); if (!in_array($val, $r))$r[] = $val; } } return $r; } public static function getListInPosition($objects_array, $pos) { $r = array(); if (is_array($objects_array)) foreach ($objects_array as $v) { if ($v instanceof Persistent) { $val = $v->getByPosition($pos); if (!in_array($val, $r))$r[] = $val; } } return $r; } public static function getListInName($objects_array, $name, $type = BasePeer::TYPE_PHPNAME) { $r = array(); if (is_array($objects_array)) foreach ($objects_array as $v) { if ($v instanceof Persistent) { $val = $v->getByName($name, $type); if (!in_array($val, $r))$r[] = $val; } } return $r; } }
1レコードずつクエリを実行されるのを防ぐためにはこうします。
ワンライナーで書きたい人はメソッド名を短くすると良いと思います
<?php $records = Hoge::doSelect($c); if ($records == null || count($records) == 0) return array(); $relation_tbls = PropelUtil::arrayToPrimaryKeyMap( FugaPeer::retrieveByPKs(PropelUtil::getListInName( $records, self::FKEY, BasePeer::TYPE_COLNAME))); foreach ($records as $k => $record) { if (array_key_exists($record->getFkey(),$relation_tbls )) $record->setRelationTable($relation_tbls[$record->getFkey()]); $records[$k] = $record; } return $records;