diff --git a/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php b/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php
index 743e63a9748..41729bd5c0a 100644
--- a/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php
+++ b/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php
@@ -119,7 +119,9 @@ public function precision($p)
*/
public function insertable($flag = true)
{
- $this->mapping['insertable'] = (bool) $flag;
+ if (! (bool) $flag) {
+ $this->mapping['notInsertable'] = true;
+ }
return $this;
}
@@ -133,7 +135,9 @@ public function insertable($flag = true)
*/
public function updateable($flag = true)
{
- $this->mapping['updateable'] = (bool) $flag;
+ if (! (bool) $flag) {
+ $this->mapping['notUpdateable'] = true;
+ }
return $this;
}
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
index f7819a3a4c8..bb6daf25be7 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
@@ -413,11 +413,11 @@ class ClassMetadataInfo implements ClassMetadata
* - nullable (boolean, optional)
* Whether the column is nullable. Defaults to FALSE.
*
- * - 'insertable' (boolean, optional)
- * Whether the column is insertable. Defaults to TRUE.
+ * - 'notInsertable' (boolean, optional)
+ * Whether the column is not insertable. Optional. Is only set if value is TRUE.
*
- * - 'updateable' (boolean, optional)
- * Whether the column is updateable. Defaults to TRUE.
+ * - 'notUpdateable' (boolean, optional)
+ * Whether the column is updateable. Optional. Is only set if value is TRUE.
*
* - columnDefinition (string, optional, schema-only)
* The SQL fragment that is used when generating the DDL for the column.
@@ -439,8 +439,8 @@ class ClassMetadataInfo implements ClassMetadata
* length?: int,
* id?: bool,
* nullable?: bool,
- * insertable?: bool,
- * updateable?: bool,
+ * notInsertable?: bool,
+ * notUpdateable?: bool,
* columnDefinition?: string,
* precision?: int,
* scale?: int,
@@ -1268,13 +1268,13 @@ public function isNullable($fieldName)
*
* @param string $fieldName The field name.
*
- * @return bool TRUE if the field is not null, FALSE otherwise.
+ * @return bool TRUE if the field is insertable, FALSE otherwise.
*/
public function isInsertable($fieldName)
{
$mapping = $this->getFieldMapping($fieldName);
- return $mapping !== false && isset($mapping['insertable']) && $mapping['insertable'];
+ return ! isset($mapping['notInsertable']);
}
/**
@@ -1282,13 +1282,13 @@ public function isInsertable($fieldName)
*
* @param string $fieldName The field name.
*
- * @return bool TRUE if the field is not null, FALSE otherwise.
+ * @return bool TRUE if the field is updateable, FALSE otherwise.
*/
public function isUpdateable($fieldName)
{
$mapping = $this->getFieldMapping($fieldName);
- return $mapping !== false && isset($mapping['updateable']) && $mapping['updateable'];
+ return ! isset($mapping['notUpdateable']);
}
/**
@@ -1318,8 +1318,8 @@ public function getColumnName($fieldName)
* columnName?: string,
* inherited?: class-string,
* nullable?: bool,
- * insertable?: bool,
- * updateable?: bool,
+ * notInsertable?: bool,
+ * notUpdateable?: bool,
* originalClass?: class-string,
* originalField?: string,
* scale?: int,
diff --git a/lib/Doctrine/ORM/Mapping/Column.php b/lib/Doctrine/ORM/Mapping/Column.php
index 172bc0d2c6b..208f04b5358 100644
--- a/lib/Doctrine/ORM/Mapping/Column.php
+++ b/lib/Doctrine/ORM/Mapping/Column.php
@@ -67,8 +67,8 @@ public function __construct(
?int $scale = null,
bool $unique = false,
bool $nullable = false,
- ?bool $insertable = true,
- ?bool $updateable = true,
+ bool $insertable = true,
+ bool $updateable = true,
array $options = [],
?string $columnDefinition = null
) {
diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
index 8ef72f92fff..0166b0df3dc 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
@@ -720,8 +720,8 @@ private function joinColumnToArray(Mapping\JoinColumn $joinColumn): array
* unique: bool,
* nullable: bool,
* precision: int,
- * insertable?: bool,
- * updateble?: bool,
+ * notInsertable?: bool,
+ * notUpdateble?: bool,
* options?: mixed[],
* columnName?: string,
* columnDefinition?: string
@@ -739,12 +739,12 @@ private function columnToArray(string $fieldName, Mapping\Column $column): array
'precision' => $column->precision,
];
- if ($column->insertable) {
- $mapping['insertable'] = $column->insertable;
+ if (! $column->insertable) {
+ $mapping['notInsertable'] = true;
}
- if ($column->updateable) {
- $mapping['updateable'] = $column->updateable;
+ if (! $column->updateable) {
+ $mapping['notUpdateable'] = true;
}
if ($column->options) {
diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
index 262e88eaca8..d89dad0de3f 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
@@ -800,8 +800,8 @@ private function joinColumnToArray(SimpleXMLElement $joinColumnElement): array
* scale?: int,
* unique?: bool,
* nullable?: bool,
- * insertable?: bool,
- * updateable?: bool,
+ * notInsertable?: bool,
+ * notUpdateable?: bool,
* version?: bool,
* columnDefinition?: string,
* options?: array
@@ -841,12 +841,12 @@ private function columnToArray(SimpleXMLElement $fieldMapping): array
$mapping['nullable'] = $this->evaluateBoolean($fieldMapping['nullable']);
}
- if (isset($fieldMapping['insertable'])) {
- $mapping['insertable'] = $this->evaluateBoolean($fieldMapping['insertable']);
+ if (isset($fieldMapping['insertable']) && ! $this->evaluateBoolean($fieldMapping['insertable'])) {
+ $mapping['notInsertable'] = true;
}
- if (isset($fieldMapping['updateable'])) {
- $mapping['updateable'] = $this->evaluateBoolean($fieldMapping['updateable']);
+ if (isset($fieldMapping['updateable']) && ! $this->evaluateBoolean($fieldMapping['updateable'])) {
+ $mapping['notUpdateable'] = true;
}
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
index 166e19816aa..aecd071e43e 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
@@ -803,8 +803,8 @@ private function joinColumnToArray(array $joinColumnElement): array
* unique?: bool,
* options?: mixed,
* nullable?: mixed,
- * insertable?: mixed,
- * updateable?: mixed,
+ * notInsertable?: mixed,
+ * notUpdateable?: mixed,
* version?: mixed,
* columnDefinition?: mixed
* }
@@ -852,12 +852,12 @@ private function columnToArray(string $fieldName, ?array $column): array
$mapping['nullable'] = $column['nullable'];
}
- if (isset($column['insertable'])) {
- $mapping['insertable'] = $column['insertable'];
+ if (isset($column['insertable']) && ! (bool) $column['insertable']) {
+ $mapping['notInsertable'] = true;
}
- if (isset($column['updateable'])) {
- $mapping['updateable'] = $column['updateable'];
+ if (isset($column['updateable']) && ! (bool) $column['updateable']) {
+ $mapping['notUpdateable'] = true;
}
if (isset($column['version']) && $column['version']) {
diff --git a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
index a46c97a439a..9af968e956c 100644
--- a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
+++ b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
@@ -597,12 +597,13 @@ public function delete($entity)
* )
*
*
- * @param object $entity The entity for which to prepare the data.
+ * @param object $entity The entity for which to prepare the data.
+ * @param bool $isInsert Whether the data to be prepared refers to an insert statement.
*
* @return mixed[][] The prepared data.
* @psalm-return array>
*/
- protected function prepareUpdateData($entity)
+ protected function prepareUpdateData($entity, $isInsert = false)
{
$versionField = null;
$result = [];
@@ -628,8 +629,7 @@ protected function prepareUpdateData($entity)
$fieldMapping = $this->class->fieldMappings[$field];
$columnName = $fieldMapping['columnName'];
- $isInsert = ! empty($this->queuedInserts[spl_object_id($entity)]);
- if (! $isInsert && ! $this->class->isUpdateable($field)) {
+ if (! $isInsert && isset($fieldMapping['notUpdateable'])) {
if ($change[0] !== $change[1]) {
throw NonUpdateableField::byName($field);
}
@@ -637,7 +637,7 @@ protected function prepareUpdateData($entity)
continue;
}
- if ($isInsert && ! $this->class->isInsertable($field)) {
+ if ($isInsert && isset($fieldMapping['notInsertable'])) {
continue;
}
@@ -708,7 +708,7 @@ protected function prepareUpdateData($entity)
*/
protected function prepareInsertData($entity)
{
- return $this->prepareUpdateData($entity);
+ return $this->prepareUpdateData($entity, true);
}
/**
diff --git a/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php b/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
index 783d9a5a5fc..4b75d71784c 100644
--- a/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
+++ b/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
@@ -219,12 +219,12 @@ public function exportClassMetadata(ClassMetadataInfo $metadata)
$fieldXml->addAttribute('nullable', $field['nullable'] ? 'true' : 'false');
}
- if (isset($field['insertable'])) {
- $fieldXml->addAttribute('insertable', $field['insertable'] ? 'true' : 'false');
+ if (isset($field['notInsertable'])) {
+ $fieldXml->addAttribute('insertable', 'false');
}
- if (isset($field['updateable'])) {
- $fieldXml->addAttribute('updateable', $field['updateable'] ? 'true' : 'false');
+ if (isset($field['notUpdateable'])) {
+ $fieldXml->addAttribute('updateable', 'false');
}
}
}
diff --git a/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterUpsertableTest.php b/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterUpsertableTest.php
index bd673eac360..dd10b7053c6 100644
--- a/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterUpsertableTest.php
+++ b/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterUpsertableTest.php
@@ -29,8 +29,8 @@ protected function setUp(): void
public function testInsertSQLUsesInsertableColumns(): void
{
- $persister = new BasicEntityPersister($this->entityManager, $this->entityManager->getClassMetadata(Insertable::class));
- $method = new ReflectionMethod($persister, 'getInsertSQL');
+ $persister = new BasicEntityPersister($this->entityManager, $this->entityManager->getClassMetadata(Insertable::class));
+ $method = new ReflectionMethod($persister, 'getInsertSQL');
$method->setAccessible(true);
self::assertEquals('INSERT INTO insertable_column (insertableContent, insertableContentDefault) VALUES (?, ?)', $method->invoke($persister));
@@ -38,13 +38,13 @@ public function testInsertSQLUsesInsertableColumns(): void
public function testUpdateSQLUsesUpdateableColumns(): void
{
- $persister = new BasicEntityPersister($this->entityManager, $this->entityManager->getClassMetadata(Updateable::class));
+ $persister = new BasicEntityPersister($this->entityManager, $this->entityManager->getClassMetadata(Updateable::class));
- $entity = new Updateable();
- $entity->id = 1;
- $entity->nonUpdateableContent = 'non-persistable';
- $entity->updateableContent = 'persistable';
- $entity->updateableContentDefault = 'persistable';
+ $entity = new Updateable();
+ $entity->id = 1;
+ $entity->nonUpdateableContent = 'non-persistable';
+ $entity->updateableContent = 'persistable';
+ $entity->updateableContentDefault = 'persistable';
$this->entityManager->getUnitOfWork()->registerManaged($entity, ['id' => 1], ['nonUpdateableContent' => 'default', 'updateableContent' => 'default', 'updateableContentDefault' => 'default']);
@@ -63,12 +63,12 @@ public function testExceptionIsThrownWhenTryingToChangeNonUpdateableColumn(): vo
{
$this->expectException(NonUpdateableField::class);
- $persister = new BasicEntityPersister($this->entityManager, $this->entityManager->getClassMetadata(Updateable::class));
+ $persister = new BasicEntityPersister($this->entityManager, $this->entityManager->getClassMetadata(Updateable::class));
- $entity = new Updateable();
- $entity->nonUpdateableContent = 'non-persistable';
- $entity->updateableContent = 'persistable';
- $entity->updateableContentDefault = 'persistable';
+ $entity = new Updateable();
+ $entity->nonUpdateableContent = 'non-persistable';
+ $entity->updateableContent = 'persistable';
+ $entity->updateableContentDefault = 'persistable';
$this->entityManager->getUnitOfWork()->registerManaged($entity, ['id' => 1], ['nonUpdateableContent' => 'default', 'updateableContent' => 'default', 'updateableContentDefault' => 'default']);