public function save(Many2ManyAttribute $attribute) { $collectionName = $attribute->getIntermediateCollection(); $firstClassName = $this->extractClassName($attribute->getParentEntity()); $secondClassName = $this->extractClassName($attribute->getEntity()); // Ensure index $indexOrder = [$firstClassName, $secondClassName]; list($indexKey1, $indexKey2) = $this->arr($indexOrder)->sort()->val(); $index = [$indexKey1 => 1, $indexKey2 => 1]; Entity::getInstance()->getDatabase()->ensureIndex($collectionName, $index, ['unique' => 1]); /** * Insert values */ foreach ($attribute->getValue() as $item) { $firstEntityId = $attribute->getParentEntity()->getId()->getValue(); if ($item->getId()->getValue() === null) { $item->save(); } $secondEntityId = $item->getId()->getValue(); $data = [$firstClassName => $firstEntityId, $secondClassName => $secondEntityId]; try { Entity::getInstance()->getDatabase()->insert($collectionName, $this->arr($data)->sortKey()->val()); } catch (\MongoException $e) { continue; } } /** * The value of many2many attribute must be set to 'null' to trigger data reload on next access. * If this is not done, we may not have proper links between the 2 entities and it may seem as if data was missing. */ $attribute->setValue(null); }
public function save(Many2ManyAttribute $attribute) { $collectionName = $attribute->getIntermediateCollection(); $firstClassName = $this->extractClassName($attribute->getParentEntity()); $secondClassName = $this->extractClassName($attribute->getEntity()); // Make sure indexes exist $indexOrder = [$firstClassName, $secondClassName]; list($indexKey1, $indexKey2) = $this->arr($indexOrder)->sort()->val(); $index = new CompoundIndex($collectionName, [$indexKey1 => 1, $indexKey2 => 1], false, true); Entity::getInstance()->getDatabase()->createIndex($collectionName, $index, ['background' => true]); /** * Insert values */ $existingIds = []; $firstEntityId = $attribute->getParentEntity()->id; foreach ($attribute->getValue() as $item) { if ($item instanceof AbstractEntity && !$item->exists()) { $item->save(); } if ($item instanceof AbstractEntity) { $secondEntityId = $item->id; } else { $secondEntityId = $item; } $existingIds[] = $secondEntityId; $data = [$firstClassName => $firstEntityId, $secondClassName => $secondEntityId]; try { Entity::getInstance()->getDatabase()->insertOne($collectionName, $this->arr($data)->sortKey()->val()); } catch (BulkWriteException $e) { // Unique index was hit and an exception is thrown - that's ok, means the values are already inserted continue; } } /** * Remove old links */ $removeQuery = [$firstClassName => $firstEntityId, $secondClassName => ['$nin' => $existingIds]]; Entity::getInstance()->getDatabase()->delete($collectionName, $removeQuery); /** * The value of many2many attribute must be set to 'null' to trigger data reload on next access. * If this is not done, we may not have proper links between the 2 entities and it may seem as if data was missing. */ $attribute->setValue(null); }