Symfony / Doctrine не обновляется в памяти

1

Я подозреваю, что это простая проблема с объектами, не обновляющимися в памяти.

Вот мои функции репозитория:

public function insertTask($information)
{
        ...

        $entityManager = $this->getEntityManager();
        $entityManager->persist($taskObj);
        $entityManager->flush();

        // Update the task defects for this task
        $this->updateTaskDefectTaskIds($taskObj->getId(), $task['defects']);

        return $taskObj;
}


private function updateTaskDefectTaskIds($task, $defects)
{
        $taskDefectIds = array();

        foreach ($defects as $defect)
        {
            $taskDefectIds[] = intval($defect['taskDefectId']);
        }

        // Update the task IDs on the task defects
        $this->getEntityManager()
            ->createQuery('UPDATE Model:TaskDefect td SET td.task = :task WHERE td.id IN (:taskDefectIds)')
            ->setParameter('task', $task)
            ->setParameter('taskDefectIds', $taskDefectIds)
            ->execute();

        $this->getEntityManager()->flush();
}

Кажется, это работает. В основном у меня есть: - Таблица задач - Таблица TaskDefect

TaskDefects в силу того, как приложение написано, вставлять его перед выполнением задачи. Но это означает, что мне нужно, как только задача в конечном итоге будет добавлена, обновите записи TaskDefect, чтобы указать на новый TaskId.

Проблема, с которой я сталкиваюсь, - это где-то в памяти (с фактической стороны базы данных, которую она обновляет правильно), она не поднимает мои изменения. Например, я обновляю некоторые TaskDefects, чтобы указать на новый TaskId, но затем я обращаюсь к объекту Task, и он говорит, что дефектов нет.

Если я перейду на другую страницу и попытаюсь получить доступ к одной и той же задаче, то она говорит, что есть недостатки.

Поэтому я чувствую, что мне не хватает flush() или persist() или что-то, что останавливает сущности в памяти от обновления. Очевидно, перезагрузка страницы заставляет обновить, и тогда она отлично работает.

Вот что я имею в своем контроллере:

$task = $repository->insertTask($content); // i figured maybe at this point it too much to expect the task obj to magically update

$updatedTask = $repository->findOneById($task->getId()); // so I grab it again... but no luck

var_dump($updatedTask->getDefects()); // ... because this returns no defects

Любые идеи приветствуются. Благодарю.

Теги:
doctrine2

1 ответ

2
Лучший ответ

Эта строка в insertTask:

return $taskObj;

Не имеет никакого отношения к тому, что происходит в updateTaskDefectTaskIds, потому что вы вообще не изменяете $ taskObj, вы просто передаете значение id, а затем обновляете объекты дефектов через DQL.

Если вы хотите, чтобы $ taskObj отражал ваши дефектные дополнения из insertTask, вы сделали бы что-то вроде этого:

public function insertTask($information)
{
    ...

    $entityManager = $this->getEntityManager();
    $entityManager->persist($taskObj);
    $entityManager->flush();

    // Update the task defects for this task
    $this->updateTaskDefectTaskIds($taskObj, $task['defects']);

    return $taskObj;
}


private function updateTaskDefectTaskIds($taskObj, $defects)
{
    foreach ($defects as $defect)
    {
        $defect = $this->getEntityManager()->getRepository('YourBundle:Defect')->find(intval($defect['taskDefectId']));

        if ($defect instanceof Defect) {

            $defect->setTaskObj($taskObj);
            $this->getEntityManager()->persist($defect);
            $taskObj->addDefect($defect);
        }
    }

    $this->getEntityManager()->persist($taskObj);
    $this->getEntityManager()->flush();
}

Или, если вы не возражаете против дополнительного вызова db, просто обновите $ taskObj в insertTask следующим образом:

$this->getEntityManager()->refresh($taskObj);
return $taskObj;

Кроме того, доктрина любит кэшировать то, что у вас есть в памяти, поэтому, если у нее нет причин проверять db (в примере кода он не может знать о ваших изменениях), то он просто счастливо будет обслуживать вас по устаревшему объекту когда вы извлекаете объект по id.

  • 0
    Большое спасибо за ваш ответ. Вы были на месте, и $this->getEntityManager()->refresh($taskObj); было все, что нужно, чтобы это исправить. Ура!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню