У меня есть таблица
CREATE TABLE `sob_tags_articles` ( `tag_id` int(11) NOT NULL, `article_id` int(11) NOT NULL, `id` int(11) NOT NULL auto_increment, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=112
И triing, чтобы сохранить объект с Доктриной:
$sbTagsArticles = new SobTagsArticles(); $sbTagsArticles->article_id = $pubId; $sbTagsArticles->tag_id = $tagId; $sbTagsArticles->save();
Но если запись существует с той же $ pubId и $ tagId, новая запись будет вставлена с новой PK.
Как сделать INSERT IGNORE в таблицу с symfony?
$sbTagsArticles->isNew();
возвращает 1.
Thnx.
try { $record->save(); } catch(Doctrine_Exception $e) { if($e->getErrorCode() !== $duplicateKeyCode) { /** * if its not the error code for a duplicate key * value then rethrow the exception */ throw $e; } /** * you might want to fetch the real record here instead * so yure working with the persisted copy */ }
Вы должны убедиться, что одна и та же запись не существует на стороне приложения, а не на стороне SQL. Если вы никогда не хотите, чтобы (article_id, tag_id)
статьи / тега существовала, добавьте уникальный индекс в (article_id, tag_id)
. Это должно генерировать ошибку mysql, которая, в свою очередь, генерирует исключение доктрины, которое вы можете поймать. Существует не игнорировать флаг для сохранения … Возможно, вы сможете использовать один из них, работающий на более низком уровне DBAL (Doctrine_Query, Doctrine_Connection и т. Д.), Но не направляемый с уровня ORM.
Doctrine_Record::isNew()
всегда будет возвращать true, если вы создали экземплярную запись, предлагающую вытащить ее из db, иначе она имеет способ узнать, что запись / isnt новая.
Также почему вы используете механизм хранения MyISAM? Я уверен, что на самом деле это приведет к большему количеству накладных расходов при использовании Doctrine, так как тогда ему нужно подражать ограничениям на стороне php. Обычно ваша схема будет выглядеть примерно так:
CREATE TABLE `sob_tags_articles` ( `tag_id` int(11) NOT NULL, `article_id` int(11) NOT NULL, `id` int(11) NOT NULL auto_increment, PRIMARY KEY (`id`), CONSTRAINT `some_unique_constraint_name_1` FOREIGN KEY `article_id` REFERENCES `article` (`id`) ON DELETE CASCADE, CONSTRAINT `some_unique_constraint_name_2` FOREIGN KEY `tag_id` REFERENCES `tag` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=112
Это фактический код, который будет использоваться
try { $record->save(); } catch(Doctrine_Connection_Exception $e) { if($e->getPortableCode() != Doctrine::ERR_ALREADY_EXISTS) { /** * if its not the error code for a duplicate key * value then rethrow the exception */ throw $e; } /** * you might want to fetch the real record here instead * so yure working with the persisted copy */ }
Вы можете расширить объект SobTagsArticles с помощью нового метода сохранения и проверить, существует ли запись:
public function exists() { $q = Doctrine_Query::create() ->from('sobtagsarticles ta') ->where('ta.tag_id = ? and ta.article_id = ?', array($this->getTagId(), $this->getArticleId())); if (!$result = $q->execute()) { parent::save(); } }
Таким образом, объект будет сохранен, только если он не существует.
Вы также можете установить уникальный индекс в таблицу:
UNIQUE INDEX `sb_tags_articles_unique` (`tag_id` ASC, `article_id` ASC)
Ваша схема будет выглядеть так:
CREATE TABLE `sob_tags_articles` ( `tag_id` int(11) NOT NULL, `article_id` int(11) NOT NULL, `id` int(11) NOT NULL auto_increment, PRIMARY KEY (`id`), UNIQUE INDEX `sb_tags_articles_unique` (`tag_id` ASC, `article_id` ASC), CONSTRAINT `some_unique_constraint_name_1` FOREIGN KEY `article_id` REFERENCES `article` (`id`) ON DELETE CASCADE, CONSTRAINT `some_unique_constraint_name_2` FOREIGN KEY `tag_id` REFERENCES `tag` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=112