Обновление отношений «многие ко многим» в Doctrine - PullRequest
0 голосов
/ 17 мая 2011

У меня есть отношение статьи к категории, и я хотел бы обновить отношение при необходимости. Это означает добавление или удаление нужных категорий из статьи. Я использую установку php (ZF) с Doctrine 1.2. В YAML конфигурация выглядит (упрощенно) так:

Article:
  columns:
    id: bigint(10)

Category:
  columns:
    id: bigint (10)
  relations:
    articles:
      foreignAlias: categories
      class: Article
      refClass: CategoryArticle

CategoryArticle:
  columns:
    category_id: bigint (10)
    article_id: bigint (10)
  relations:
    category:
      class: Category
      foreignAlias: categoryArticle
    article:
      class: Article
      foreignAlias: categoryArticle

У меня есть постоянная статья в $, где доступны все старые категории. С помощью запроса POST я получаю список идентификаторов категорий, которые должны быть новыми. У меня есть это до сих пор:

$oldCategories = array();
foreach ($article->categories as $cat) {
    $oldCategories[] = $cat->id;
}
$newCategories = $form->getValue('categories');

$diffRemove = array_diff($oldCategories, $newCategories);
$diffAdd    = array_diff($newCategories, $oldCategories);
foreach ($diffRemove as $id) {
    // Remove all the categories $id from article [1]
}
foreach ($diffAdd as $id) {
    // Add all the categories $id to article [2]
}

Мой вопрос касается [1] и [2]. Какова лучшая производительность для добавления и удаления связи «многие: многие»?

1 Ответ

4 голосов
/ 15 августа 2011

Удаление

Наиболее эффективный способ массового удаления в SQL - это использование одного оператора SQL с некоторыми заданными условиями, например,

delete from Products where id>3

Используются индексы, разделы и т. Д.

Существует способ достичь этого значения производительности с помощью Doctrine 1.2 - с помощью операторов DQL DELETE . Как показано в документации, следующий запрос преобразуется в приведенный выше SQL:

$q = Doctrine_Query::create()
    ->delete('Products p')
    ->where('p.id > 3');

В вашем случае вы можете оптимизировать удаление с помощью чего-то вроде

$q = Doctrine_Query::create()
    ->delete('CategoryArticle ca')
    ->where('ca.article_id=?', $article_id)
    ->andWhereIn('ca.category_id', $diffRemove);

Этот код должен сгенерировать что-то вроде:

delete from CategoryArticle 
where article_id = $article_id and category_id in ($diffremove)

Вставка

При вставке вы можете использовать CategoryArticle сущность. Наиболее эффективный способ сделать это с помощью Doctrine - создать коллекцию сущностей и сохранить эту коллекцию:

$collection = new Doctrine_Collection('CategoryArticle');
foreach ($diffAdd as $id){
    $ca = new CategoryArticle();
    $ca->category = $id;
    $ca->article = $article_id;
    $collection[] = $ca;
}

$collection->save();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...