2016-12-09 2 views
0

У меня две модели с простым соотношением 1-n (категория и элемент с категорией_id). Я хотел бы показать, сколько предметов в этой категории. Я хотел бы, чтобы число кэшировалось, а затем всегда делало счет, поэтому у меня есть дополнительное поле в таблице категорий, называемой total_items_count. Как лучше всего запустить этот счетчик, когда вызвать функцию countUpdate, поскольку отношение может измениться из нескольких мест (backend, api, frontend ...).Как отслеживать изменения отношения между двумя моделями в yii2

Мой первоначальный план состоял в том, чтобы использовать событие AFTER_UPDATE, но «link()» необходимо вызывать после того, как элемент хранится в базе данных (при добавлении нового элемента как минимум), поэтому я не знаю, какая категория является элементом, связанным с , Мне также нужно знать старую категорию, в случае, если элемент переходит из одной категории в другую. В backend-контроллере я использую $ item-> link ('category', $ categoryObj); так как я могу изменить это отношение на n-n когда-нибудь.

Любые советы о том, как иметь полный контроль, если связь между товаром и категорией изменяется, а затем обновлять счет для старой и новой связанной категории? Спасибо

ответ

0

Первым и самым важным, что вам нужно сейчас, является то, что вам необходимо обновить поле count категории с помощью метода ActiveRecord::updateCounters(), чтобы предотвратить неправильное обновление из нескольких мест. Таким образом, вы можете сделать одну из этих вещей:

В категории элемента модели вы можете сделать следующее:

public function save($runValidation = true, $attributeNames = null) 
{ 
    if (parent::save(runValidation, attributeNames)) { 
     $this->category->updateCounters(['total_items_count' => 1]); 
     return true; 
    } 
    return false; 
} 

Или вы можете написать централизованный компонент (скажем, приложение \ Components \ Категория), которые вы будете вызов из всей заявки. Этот компонент будет иметь метод, который сохраняет элемент. Например:

public function saveItem($category, $item) 
{ 
    if ($item->save()) { 
     $item->link('category', $category); 
     $category->updateCounters(['total_items_count' => 1]); 
     return true; 
    } 
    return false; 
} 

Конечно, при удалении элемента, вы вызовете:

$category->updateCounters(['total_items_count' => -1]); 

See the ActiveRecord::updateCounters() API

Из документации Yii2:

Примечание: Если вы используйте yii \ db \ ActiveRecord :: save() для обновления столбца счетчика, вы можете получить неточный результат, потому что, скорее всего, sa me счетчик сохраняется несколькими запросами, которые считывают и записывают одно и то же значение счетчика.

Если вам нужно следить за которой старая категория, просто создать еще один столбец, скажем, «old_category» в таблице категории пункт и при изменении категории пункта поставить старый идентификатор категории там, и идентификатор новой категории в столбец category_id.

Это помогает? Если у вас есть какие либо вопросы, пожалуйста спрашивайте!

+0

Спасибо, я проверил его на этой неделе. Будет ли save() вызываться только при обновлении элемента (или как при обновлении, так и при создании элемента)? – Dakipro

+0

save() вызывается в обоих случаях. Таким образом, вы можете проверить, создаете ли вы или обновляете элемент. Если вы обновляете элемент, вам не понадобится обновлять total_items_count. Вы также можете использовать метод afterSave, который имеет параметр $ insert, который будет «true», если элемент создан. Не забывайте вызывать родительский :: afterSave() после этого! –

+0

спасибо, я сейчас близко.Дело в том, что я не могу определить, изменилась ли категория, потому что мне нужно сохранить модель элемента, а затем «связать ее» следующим образом: '$ model = $ this-> findModel ($ id); if ($ model-> load (Yii :: $ app-> request-> post())) { $ model-> save(); // а затем ссылку на него $ model-> link ('category', $ categoryObj); ' и save() затем вызывается два раза, и в обоих случаях я не знаю, изменяется ли« категория »($ this-> isAttributeChanged ('category') всегда возвращает false) – Dakipro

Смежные вопросы