Как мне удалить ссылки на объект, если этот объект удален в Doctrine MongoDB? - PullRequest
4 голосов
/ 18 января 2012

На моей странице появляется следующая критическая ошибка

The "WildkatProxy\DocumentsTagProxy" document with identifier "4e90eede17bc2ec68c000001" could not be found.

Я предполагаю, что это связано с тем, что прокси-сервер тегов документов был удален из другого действия, и поэтому ссылка больше не действительна.Теперь я хочу удалить устаревшую ссылку на этот объект, но молча.(Как это может случиться и во многих других ситуациях). Можно ли в любом случае выполнить «обратный каскад» для всех объектов, ссылающихся на удаленный объект при удалении объекта?

Каковы наилучшие методы для достижения этой цели??

Спасибо, Энди

Ответы [ 2 ]

1 голос
/ 26 января 2015

Я предполагаю, что у вас есть две коллекции, ArticleTag и Article, в которых статьи имеют ссылки на теги статьи.Если вы хотите удалить ссылки на теги из статей при удалении тега, вы можете реализовать прослушиватель событий.

Создать класс:

namespace Foo\BarBundle\EventListener;

use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
use Foo\BarBundle\Document\Article;

class ArticleTagRemovalListener
{
    public function preRemove(LifecycleEventArgs $args)
    {
        $document = $args->getDocument();

        if ($document instanceof Article) {
            // Remove tag from all articles
            $args
                ->getDocumentManager()
                ->getRepository('FooBarBundle:Article')
                ->removeTag($document);
        }
    }
}

и зарегистрировать этот класс в своем файле services.yml или xml:

foo_bar.listener.tag_removal:
    class: Foo\BarBundle\EventListener\ArticleTagRemovalListener
    tags:
      - { name: doctrine_mongodb.odm.event_listener, event: preRemove }

Далее в пользовательском классе хранилища вашей статьи добавьте следующий метод:

public function removeTag($tag)
{
    return $this
        ->createQueryBuilder()
        ->update()
        ->field('tags')->pull($tag)
        ->multiple(true)
        ->getQuery()
        ->execute();
}

Это удалит тег из всех доступных статей перед его удалением,Если вы хотите каскадно удалить операцию для всех документов статьи.(Таким образом, при удалении этого тега удаляйте все статьи с определенным тегом, используйте следующий метод репозитория.)

public function purgeByTag($tag)
{
    $result = $this
        ->createQueryBuilder()
        ->remove()
        ->field('tags')->equals($tag)
        ->getQuery()
        ->execute();

    return $result['n'];
}

Обновите ArticleTagRemovalListener, чтобы вызвать этот метод, и готово!

0 голосов
/ 26 января 2012

По умолчанию Doctrine не будет каскадировать никакие операции UnitOfWork для ссылочных документов, поэтому, если вы хотите использовать эту функцию, вы должны явно включить ее

Вы можете включить его в любом поле с помощью «remove» или «detach» в зависимости от желаемого поведения.

@ReferenceOne(targetDocument="Profile", cascade={"detach"})

http://www.doctrine -project.org / Docs / mongodb_odm / 1,0 / о / ссылка / ссылка-mapping.html # каскадной-операция

...