Доктрина не сохраняет измененные данные

Итак, я пытаюсь сохранить сущность в Доктрине. Объект, который я хочу сохранить, выглядит так, как будто это извлечено из функции Symfony dump ():

Time {#7751 ▼
  -id: 3
  -timeIn: DateTime {#7749 ▶}
  -timeOut: null
  -rateId: Rate {#7761 ▼
    -id: 1
    -amount: "30.00"
    -name: "Technical"
    -projectId: Project {#7756 ▶}
    -groupId: 1
  }
  -description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
  -userId: 1
  -status: "Unpaid"
  -total: null
  -cost: "60.00"
  -projectId: Project {#7756 ▼
    -id: 1
    -name: "Acme Corp"
    -description: "Metals Company"
    -contactId: 1
    -organizationId: 1
    -groupId: 1
  }
  -groupId: 1
  }

Теперь я, очевидно, не могу настаивать на этом, потому что у меня есть соответствующие объекты в их идентификаторах. Пример: rateId, projectId и т. д. Итак, чтобы компенсировать это, в моей функции clockOut я запускаю проверку, чтобы заменить объекты на их идентификаторы для хранения. См. Функцию clockOut ниже:

public function clockOut($time, $group = null){
    dump($time);
    if (gettype($time) == "object"){
        if (gettype($time->getProjectId())=='object'){
            $time->setProjectId($time->getProjectId()->getId());
        }
        if (gettype($time->getRateId())=='object'){
            $time->setRateId($time->getRateId()->getId());
        }
        $this->persistClockout($time);
    }
    elseif (gettype($time) == "string"){
        if ($group == null){
            return false;
        }else {
            $time = $this->findData($group, $time);
            $this->persistClockout($time);
        }
    }else {
        return false;
    }
}

Существует также соответствующая функция persistClockout, которая обрабатывает фактическое время выхода и расчет часов. Хотя я не думаю, что это действительно имеет какое-либо отношение к проблеме, с которой я столкнулся, я все равно включу ее, потому что она связана.

/**
 * Persist time
 */
private function persistClockout($time, $group = null){
    if ($time->getTimeOut() == null){
        $time->setTimeOut(new DateTime("Now"));
    }
    $this->hours = $this->hoursCalculate($time->getTimeIn(), $time->getTimeOut());
    $time->setTotal($this->hours);
    dump($time);
    die();
    $this->persist($time);
}

/**
 * Get the amount of hours spent in decimal format.
 */
private function hoursCalculate($past, $present){
    $diff = $present->diff($past);
    $hours = round($diff->s / 3600 + $diff->i / 60 + $diff->h + $diff->days * 24, 2);
    return $hours;
}

Теперь, как вы можете видеть, я запускаю функцию dump () прямо перед концом команды, прежде чем она повторится, потому что я сам пытался диагностировать эту проблему. Согласно функции dump () данные выглядят так:

Time {#7751 ▼
  -id: 3
  -timeIn: DateTime {#7749 ▶}
  -timeOut: DateTime {#11571 ▶}
  -rateId: 1
  -description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
  -userId: 1
  -status: "Unpaid"
  -total: 187.83
  -cost: "60.00"
  -projectId: 1
  -groupId: 1
}

Большой! Это ожидаемый результат. Но проблема возникает, когда я начинаю пытаться сохранить данные в базе данных.

An exception occurred while executing 'UPDATE rate SET project_id = ? WHERE id = ? AND group_id = ?' with params [{}, 1, 1]:

Notice: Object of class ProjectBundle\Entity\Project could not be converted to int

Хотя я проверил данные прямо перед тем, как запустить функцию persist, похоже, все еще думает, что projectId все еще является объектом, хотя я убедился, что установил для него фактический Id, а не объект, он меня игнорирует.

Я пошел дальше и заглянул в профилировщик Symfony и нашел ту часть, которую доктрина использует для обновления, и просмотрел детали, вот и вот projectId - это объект? Хотя я не это сделал?

Доктрина не сохраняет измененные данные

Кто-нибудь понятия не имеет, что происходит? Извините за многословный пост, я просто хотел дать вам некоторую информацию о том, с чем вы работаете. Пожалуйста, игнорируйте функции dump () и die () в коде, я использовал их, чтобы попытаться диагностировать это, но я озадачен. Стоит отметить, что я пробовал запускать обычные вещи, такие как php bin / console cache: clear и перезапускать сервер.

Спасибо заранее, переполнение стека!

Обновлено:

Ниже приведен код, указанный для -> persist ()

    public function persist($entity, bool $flush = true)
{
    $this->manager->persist($entity);

    if ($flush) {
        $this->flush();
    }

    return $this;
}

ОБНОВИТЬ

Я пробовал запустить persist, а затем flush отдельно, но это не сработало. Получил то же исключение. Я, честно говоря, растерялся, ребята.

Не могли бы вы опубликовать одну из ваших сущностей с отображением? Мне кажется, что вся работа, которую вы выполняете с сопоставлением объектов с их идентификаторами, неверна. Это именно то, что Doctrine сделает для вас под капотом. Вам не нужно ничего разрешать. Ошибка выглядит так, как будто Doctrine пытается решить, как получить идентификатор из связанного объекта, но поскольку это int, а не объект, это не удастся.

dbrumann 04.09.2018 07:24

Кажется, существует конфликт между вашим запросом UPDATE и структурой объекта. Ваш Time явно хранит идентификаторы (а не ссылки на Project или Rate), но по какой-то причине вы передаете Project вашему запросу. Ты? Можете выложить функцию persist($time)?

Jovan Perovic 04.09.2018 10:13

Добавлена ​​функция сохранения из моего базового менеджера.

Ervin Šabić 04.09.2018 20:47
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
3
167
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, вам нужно было использовать этот код:

$this->flush($time); 

вместо $this->persist($time);

Отредактировал мой пост, чтобы включить функцию сохранения, которая запускается внутри него.

Ervin Šabić 04.09.2018 20:49
Ответ принят как подходящий

Я понял. Оказывается, проблема заключалась в том, как доктрина идентифицирует разные фрагменты данных и что считает одинаковым. Я предполагаю, что это как-то связано с эффективностью или кешированием или чем-то в этом роде.

В любом случае, позвольте мне рассказать вам, как я пришел к такому выводу.

Первый намек, который у меня был, заключался в том, что, хотя rateId изначально был объектом, а затем был преобразован в соответствующий ему идентификатор, он не вызывал ошибку, как ProjectId.

Во-вторых, я более внимательно изучил функцию dump () и кое-что заметил. (Я повторно использую пример из моего исходного сообщения)

Time {#7751 ▼
  -id: 3
  -timeIn: DateTime {#7749 ▶}
  -timeOut: null
  -rateId: Rate {#7761 ▼
    -id: 1
    -amount: "30.00"
    -name: "Technical"
    -projectId: Project {#7756 ▶}  <---- Right Here
    -groupId: 1
  }
  -description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
  -userId: 1
  -status: "Unpaid"
  -total: null
  -cost: "60.00"
  -projectId: Project {#7756 ▼  <---- Right Here
    -id: 1
    -name: "Acme Corp"
    -description: "Metals Company"
    -contactId: 1
    -organizationId: 1
    -groupId: 1
  }
  -groupId: 1
  }

Цифры после объектов проекта были такими же. Итак, я придумал теорию, согласно которой доктрина где-то хранит исходную ссылку на projectId (объект) и использует ее вместо значения, которое я установил позже в качестве соответствующего идентификатора (Int).

Итак, чтобы проверить эту теорию, я написал две функции для «сглаживания» моего объекта, начиная с конца дерева объектов (поскольку на самом деле он должен доходить только до 3 вложенных объектов) до начала. Таким образом, все ссылки совпадают, хотя в конечном итоге они были «удалены».

 /**
 * Undo all object associations and convert them back into their original IDs. 
 * @param object $data
 * @param array $callable
 */
public function flattenObject($data, $callable){
    $sorter = new SortingHelper;
    foreach($callable as $call){
        $getMethod = 'get'.ucfirst($call).'Id';
        $setMethod = 'set'.ucfirst($call).'Id';
        if (method_exists($data, $getMethod)){
            $found = $data->$getMethod();
            if (gettype($found) == 'object'){
                $result = $this->flatten($found, $callable);
                $data->$setMethod($result);
            }
        }
    }
    return $data;
}

/**
 * @param object $data 
 * @param array $callable
 */
private function flatten($data, $callable){
    for($i = 0; $i != count($callable); $i++){
        $getMethod = 'get'.ucfirst($callable[$i]).'Id';
        $setMethod = 'set'.ucfirst($callable[$i]).'Id';
        if (method_exists($data, $getMethod)){
            $result = $data->$getMethod();
            if (gettype($result) == 'object'){
                $data->$setMethod($result->getId());
            }
        }
    }
    return $data->getId();
}

Выполнение функции flattenObject () позволило мне сохранить объект в базе данных, поскольку ссылки на идентификаторы больше не были объектами.

Бам. Решена очень досадная проблема.

Надеюсь, это как-то поможет кому-то в будущем. Спасибо всем, кто внес свой вклад! :)

Другие вопросы по теме