顧客は必要に応じてアイテムの順序を変更する必要があります。つまり、各アイテムの実際の位置を保存するには、「順序」または「順序」列が必要です。
Doctrine 2を使用してこれを実装するにはどうすればよいですか?
顧客は必要に応じてアイテムの順序を変更する必要があります。つまり、各アイテムの実際の位置を保存するには、「順序」または「順序」列が必要です。
Doctrine 2を使用してこれを実装するにはどうすればよいですか?
GitHub には、Doctrine のさまざまな拡張機能を備えた優れたリポジトリがあり、そのうちの 1 つは単なる Sortable 機能です。
Doctrine のイベント システムを使用して実装します。動作を追加するには、通常、イベント サブスクライバーを作成し、エンティティ クラスによって実装されたインターフェイスを使用してルールを適用します。私がどこかのサービスオブジェクトに保持している実際のロジック(それについてはあなた自身です)。
use Doctrine\Common\EventSubscriber,
Doctrine\ORM\Events,
Doctrine\ORM\Event\LifecycleEventArgs,
Doctrine\ORM\Event\PreUpdateEventArgs;
class SortableBehavior implements EventSubscriber
{
public function getSubscribedEvents()
{
return array(Events::prePersist, Events::preUpdate);
}
public function prePersist(LifeCycleEventsArgs $args)
{
// the entity being persisted
$entity = $args->getEntity();
if ($entity instanceof SortableInterface) {
//perform sorting magic
}
}
public function preUpdate(preUpdateEventsArgs $args)
{
// the entity being updated
$entity = $args->getEntity();
if ($entity instanceof SortableInterface) {
//perform sorting magic
}
}
}
アプリをブートストラップするときは、サブスクライバーを登録することを忘れないでください。
$eventManager = $entityManager->getEventManager();
$eventManager->addEventSubscriber(new SortableBehavior());
EventSubscriber でいくつかのテストを行いましたが、適切に動作させることができなかったので、コードをクラスに直接追加することにしました (q&d)。私は Zend Framework を使用しているため、別の解決策がある場合はエンティティ マネージャーのフェッチを変更してください。
次のように機能します。
エンティティ コードは次のとおりです。
/**
* Searches for the element above and switches them
* with eachother. Performs a EntityManager::flush()
* to save the results after the switch.
*/
public function sortUp() {
try {
$em = \Zend_Registry::get("entitymanager");
$class_name = get_class($this);
$dql = "SELECT ut FROM $class_name ut WHERE ut.inactive IS NULL AND ut.inactive IS NULL AND ut.sort < '" . $this->getSort() . "' ORDER BY ut.sort DESC";
$query = $em->createQuery($dql);
$query->setMaxResults(1);
$ut = $query->getResult();
} catch (Exception $exc) {
throw new Exception("Error when looking for sortable partner: " . $exc->getMessage());
}
if (count($ut)) {
$this->_switchSortAndSave($ut[0]);
}
}
/**
* Searches for the element below and switches them
* with eachother. Performs a EntityManager::flush()
* to save the results after the switch.
*/
public function sortDown() {
try {
$em = \Zend_Registry::get("entitymanager");
$class_name = get_class($this);
$dql = "SELECT ut FROM $class_name ut WHERE ut.inactive IS NULL AND ut.sort > '" . $this->getSort() . "' ORDER BY ut.sort ASC";
$query = $em->createQuery($dql);
$query->setMaxResults(1);
$ut = $query->getResult();
} catch (Exception $exc) {
throw new Exception("Error when looking for sortable partner: " . $exc->getMessage());
}
if (count($ut)) {
$this->_switchSortAndSave($ut[0]);
}
}
private function _switchSortAndSave(\Entities\Usertype $switch_entity) {
$new_sort = $switch_entity->getSort();
$switch_entity->setSort($this->getSort());
$this->setSort($new_sort);
$em = \Zend_Registry::get("entitymanager");
$em->persist($switch_entity);
$em->persist($this);
$em->flush();
}
/**
* Looks for the last entry according to sort order
* and returns that if found.
*
* @return Entity|null
*/
public static function findLast() {
try {
$em = \Zend_Registry::get("entitymanager");
$class_name = get_called_class();
$dql = "SELECT ut FROM $class_name ut ORDER BY ut.sort DESC";
$query = $em->createQuery($dql);
$query->setMaxResults(1);
$ut = $query->getResult();
} catch (Exception $exc) {
throw new Exception("Error when searching for last $class_name: " . $exc->getMessage());
}
if (count($ut))
return $ut[0];
else
return null;
}
私はこの解決策にあまり満足していないので、もし誰かが Doctrine 2 のための素晴らしい Sortable を思いついたら共有してください :)
特定のフィールドで並べ替えられたコレクションを自動的に取得できます。
そうすれば、「sort_order」列を使用して順序を定義できます。次に、パフォーマンス上の理由から DQL Update ステートメントを使用してソート列を正しく更新するいくつかのメソッド、つまり「moveTo($pos, $entity)」を使用し、関連する数の更新を発行する必要があります。
ただし、順序が変更された同じリクエストでコレクションを反復する必要がある場合、これにより問題の半分が解決されます。ただし、これはまれなユースケースであるため、無視されることがよくあります。
別の列を追加します。
ソート順: タイプ: 整数(4) デフォルト: 10
そのエントリを 10 から他のものに変更すると、次のような方法で取得される結果セットに移動します。
$this->result = Doctrine_Core::getTable('CustomerTable') ->createQuery('a')->orderBy("a.sort_order asc, a.id desc")->execute();