На данный момент я не уверен, проблема в доктрине или в symfony.
У меня есть объект под названием Field. У него есть свойство dataTable с обычными методами получения и установки. В одном из моих вспомогательных классов я использую метод установки, чтобы изменить dataTable на временное значение. Я никогда не вызываю persist в этом классе или контроллере, который его вызывает. Однако я обнаружил, что база данных обновляется с помощью этого временного значения.
Если нужно, я могу добавить виртуальное свойство и использовать его вместо этого, но я думаю, что код будет чище, если я смогу этого избежать. Как я могу гарантировать, что доктрина сохраняет только то, о чем я прямо говорю?
Отображение объектов:
type: entity
gedmo:
soft_deleteable:
field_name: deletedAt
time_aware: false
id:
id:
type: integer
generator:
strategy: auto
fields:
name:
type: string
sortorder:
type: integer
dataTable:
type: string
type:
type: string
columnAdded:
type: boolean
deletedAt:
type: date
nullable: true
manyToOne:
section:
targetEntity: Domain\Model\Section
inversedBy: fields
oneToMany:
fieldOptions:
targetEntity: FieldOption
mappedBy: field
oneToOne:
zmrList:
targetEntity: Domain\Model\ZmrList
Соответствующий код контроллера: (Persist никогда не вызывается ни для чего в контроллере)
$columns = $this->queryBuilder->getListColumns($list);
$filters = $this->queryBuilder->composeListFilters($list);
$query = $this->queryBuilder->build($columns, $filters, $list->getForm()->getId(), $instanceId);
Соответствующий код в QueryBuilder:
foreach ($details['columns'] as $k=>$layerColumn) {
$this->columns[$layerColumn]->getField()->setDataTable('table_'.$alias);
}
Функция сеттера:
/**
* @param string $dataTable
*/
public function setDataTable(string $dataTable): void
{
$this->dataTable = $dataTable;
}
в чем я уверен, так это в том, что база данных обновляется только в том случае, если вы используете ** flush () **, поэтому отлаживайте свой код и смотрите, не сбрасываете ли вы объект где-то
flush записывает изменения, внесенные в Любые управляемых объектов. «временное» изменение значения управляемого объекта не чисто, это грязно. Я бы действительно использовал временное поле или переоценил бы подход.
@Джакуми, спасибо. Если вы хотите опубликовать это как ответ, я приму это
@AmyAnuszewski Это действительно возможно, я только что добавил ответ.




заявление об отказе от ответственности: верно следующее для политики отслеживания изменений по умолчанию (неявно)
flush по определению записывает любые изменения, внесенные в управляемые объекты, в базу данных.
Сохранение объекта делает его управляемым, и поэтому любые изменения в нем, даже если они должны быть «временными», будут сохраняться в flush (как уже указал А. Марван в комментарии).
Поскольку семантика очень ясна, я бы посоветовал не устанавливать временные значения для управляемых полей (любых сопоставленных полей). Либо добавьте для этого временное свойство, либо переоцените подход - может быть, сервис, оболочку или что-то еще, что лучше подходит для вашего варианта использования.
комментарий для изменения политики отслеживания:
Ответ Rikudou_Sennin предлагает технически правильное решение технической проблемы, когда объекты сохраняются, когда разработчик может этого не захотеть... путем изменения политики отслеживания изменений. ИМХО, это семантически зло, ... ну ладно, назовем это проблематичным.
Как разработчик, я всегда предполагал, что объекты имеют согласованное состояние, даже если оно еще не сброшено в базу данных. Если он имеет состояние, отличное от его сохраненной версии, я хочу предположить, что когда запрос выполнен и все или ничего измененных объектов записываются в базу данных, база данных находится в согласованном состоянии. «Нет» можно считать заданным. Об «всех» достаточно сложно думать.
Однако с другой политикой отслеживания изменений и неявной возможностью того, что «грязный» объект, который никогда не будет доверенным, может крутиться вокруг со значениями, на которые разработчик никоим образом не может полагаться, потому что неясно, будет ли объект сохранен. или нет, или, может быть, было упорно. Это только добавляет больше (ненужных) сомнений. Это также является дополнительным источником трудно поддающихся отладке ошибок.
Резюме вариантов:
*) предполагает в некотором роде чистый и правильно структурированный код с неповрежденной и бескомпромиссной семантикой.
Неправда, вы можете изменить политику отслеживания.
@Rikudou_Sennin хорошо, я исправлен. Однако я бы сказал, что это менее интуитивно понятно и создает другие проблемы и ловушки.
Вы имеете в виду изменение политики отслеживания или использование полей для временных значений? Изменение политики отслеживания на явное на самом деле круто, поскольку Doctrine работает намного быстрее, если вы работаете с большим количеством объектов. Я согласен с тем, что использование отслеживаемых полей для временных значений — не самое чистое решение.
Политика отслеживания @Rikudou_Sennin (явная) менее интуитивна, потому что вы должны явно отслеживать изменения. Не сомневаюсь, что быстрее. Однако (см. редактирование ответа) я бы предпочел неявное явному, если только нет очень веских причин не делать этого. Однако в этих случаях необработанный sql может быть даже лучше ^^
Вы можете сделать это, изменив Change Tracking Policy с Deferred Implicit (по умолчанию) на Deferred Explicit. Изменив его на явный, в базу данных будут сохраняться только объекты, отмеченные persist(), даже обновления (в схеме implicit отслеживаются все обновления). У него есть еще одно преимущество, заключающееся в том, что он намного более удобен для памяти, потому что ему не нужно проходить каждый объект, который находится в хранилище доктрин, он проходит только те, которые вы пометили для сохранения с помощью persist().
Вот как это сделать через yaml:
type: entity
changeTrackingPolicy: DEFERRED_EXPLICIT # can be DEFERRED_IMPLICIT, DEFERRED_EXPLICIT or NOTIFY
# the rest of your config
Я думаю, что ваш ответ был тем, что я изначально искал, однако я думаю, что Джакуми был прав в том, что мне не следует делать то, что я делаю. Я создал виртуальное свойство вместо внесения временных изменений в исходное поле.
можешь дать код карты? Контроллер и код, которые выполняют модификацию связанного объекта?