Compare commits

...

32 Commits

Author SHA1 Message Date
Grégoire Paris
7b24275346 Merge pull request #9218 from Florian-Varrin/patch-1
Fix typo assumptio--> assumption
2021-12-03 13:27:05 +01:00
Florian Varrin
ed1a576305 Fix typo assumptio--> assumption 2021-12-03 11:39:59 +01:00
Alexander M. Turek
15ec77fa79 Suppress Psalm's ReservedWord errors (#9212) 2021-11-30 20:20:27 +01:00
Alexander M. Turek
cac2acae07 Psalm 4.13.1, PHPStan 1.2.0 (#9204) 2021-11-28 00:50:56 +01:00
Grégoire Paris
146b465ec1 Merge pull request #9198 from laryjulien/fix-fieldmapping-definition
Add a psalm type for field mapping
2021-11-23 21:10:18 +01:00
Julien LARY
5aba762a33 Add a psalm type for field mapping
Field mapping have different definitions
in property definition and method return.
As suggested in issue and to avoid further desynchronization,
a psalm type has been created.
Fixes #9193
2021-11-23 18:05:47 +01:00
Simon Podlipsky
a663dda869 Use equal to instead of equal of in assertSqlGeneration() (#9195) 2021-11-20 21:27:46 +01:00
Thomas Landauer
db14f0fa89 Adding Attributes code block (#9161)
Just that there is some real-world example somewhere ;-) see https://github.com/doctrine/orm/issues/9020#issuecomment-955582801
2021-11-20 18:14:49 +01:00
Vincent Langlet
9a74ae6280 Fix discriminatorColumn phpdoc (#9168) 2021-11-11 23:01:34 +01:00
Grégoire Paris
32eb38ebd9 Merge pull request #9181 from greg0ire/fix-broken-build
Remove similar assertions for other platforms
2021-11-11 16:20:53 +01:00
Thomas Landauer
176fbedc69 Fine-tuning codeblock (#9176)
* Deleting "Not needed for XML and YAML mapping" - this was stupid of me, since *all* annotations are obviously not needed in XML&YAML ;-)
* Shortening the @Column annotation, for consistency with the following event handlers
* Removing some blank lines from XML, for consistency with YAML
* Adding PHP Attributes
2021-11-10 22:43:09 +01:00
Grégoire Paris
1b15af44b6 Remove similar assertions for other platforms
Testing with several platforms should not increase code coverage here,
since the DBAL is responsible for providing the concat expression for
each platform.

Moreover, whenever that concat expression changes for one of the tested
platforms, this test will break.

In doctrine/dbal 3.2, that is the case for SQLServer2012Platform, which
means this test no longer passes.
2021-11-08 21:21:41 +01:00
Grégoire Paris
8336420a26 Merge pull request #9153 from armenio/2.10.x
Infer type from field instead of column
2021-11-08 07:45:07 +01:00
Thomas Landauer
a6b7569d7a Fixing more links (#9154)
* Fixing more links

The first two I missed in https://github.com/doctrine/orm/pull/9151
The third is probably older.
Shouldn't the chapter name be displayed as link text by default?? Are you sure that everything is set up correctly with the parser?

* Update architecture.rst

* Update getting-started.rst

* Update events.rst
2021-11-06 20:49:54 +01:00
Rafael Armenio
9e37c788ef Infer type from field instead of column
getTypeOfColumn() relies on getTypeOfField(), and does not suffer from
mismatching issues caused by quoting, because you cannot quote a field.
Since a field can be composite, that method returns an array, hence why we
need to select the first element.
2021-11-05 13:58:53 -03:00
Grégoire Paris
ca0a6bbf71 Merge pull request #9167 from derrabus/bump/phpstan
PHPStan 1.0.1
2021-11-03 21:15:19 +01:00
Grégoire Paris
a3da3d78d4 Merge pull request #9159 from ThomasLandauer/patch-10
Merging Lifecycle Callbacks code samples for PHP + XML + YAML
2021-11-03 21:13:53 +01:00
Alexander M. Turek
e1c2d2e65d PHPStan 1.0.1
Signed-off-by: Alexander M. Turek <me@derrabus.de>
2021-11-02 20:41:48 +01:00
Alexander Schranz
6f194eeabf Remove reverted bc break (#9166) 2021-11-01 13:56:12 +01:00
Grégoire Paris
16cbc16998 Document BC break (#9143)
Closes #9141
2021-10-30 19:10:25 +02:00
Thomas Landauer
5e6608b48e Update events.rst 2021-10-30 13:48:03 +02:00
Grégoire Paris
94bc137526 Merge pull request #9123 from phansys/quotes_in_column_names
Add XSD "orm:columntoken" type in order to support reserved words in column names
2021-10-29 18:19:35 +02:00
Thomas Landauer
276a0f55ee Removing paragraph on consts (#9158)
IMO, this is better shown by example, so I added it there.
2021-10-29 14:21:37 +02:00
Thomas Landauer
dbaf99f3d9 Update events.rst 2021-10-29 01:17:32 +02:00
Thomas Landauer
97411f5567 Merging Lifecycle Callbacks code samples for PHP + XML + YAML
IMO, the text I deleted just repeated things that are obvious in the example anyway.
2021-10-29 01:12:02 +02:00
Chase Noel
641330baa6 Add doctrine/dbal to project composer.json (#9152)
As discussed in https://github.com/doctrine/orm/issues/9078 when entities utilize data mappings which are provided by the dbal lib it is expected behavior that users will explicitly define their dependency on the package.

Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2021-10-28 23:42:05 +02:00
Thomas Landauer
35e680cd3f Fixing links in overview table (#9151)
I got them wrong in https://github.com/doctrine/orm/pull/9131 ;-)
2021-10-28 21:29:47 +02:00
Javier Spagnoletti
705d88eaba Add XSD "orm:columntoken" type in order to support reserved words in column names 2021-10-28 14:00:39 -03:00
Paul Waring
3271d8f6e2 Fix markup for variable names (#9150)
Three references to `$isDevMode` were marked up with a single backtick, however two backticks are required in order for the variable name to be highlighted correctly (c.f. `ArrayCache`).
2021-10-26 10:59:31 +00:00
Thomas Landauer
3622381f8c Overview table for events: Jump links (#9131)
* Overview table for events: Jump links

* Update events.rst
2021-10-25 22:34:36 +02:00
wickedOne
f2729b0610 Return 0 when there's no metadata to process (#9147) 2021-10-23 09:43:40 +00:00
chapterjason
cd44547573 Remove old use statements (#9146) 2021-10-23 11:32:44 +02:00
34 changed files with 904 additions and 420 deletions

View File

@@ -1,5 +1,12 @@
# Upgrade to 2.10
## BC Break: `UnitOfWork` now relies on SPL object IDs, not hashes
When calling the following methods, you are now supposed to use the result of
`spl_object_id()`, and not `spl_object_hash()`:
- `UnitOfWork::clearEntityChangeSet()`
- `UnitOfWork::setOriginalEntityProperty()`
## BC Break: Removed `TABLE` id generator strategy
The implementation was unfinished for 14 years.
@@ -9,10 +16,6 @@ It is now deprecated to rely on:
- `Doctrine\ORM\Mapping\ClassMetadata::$tableGeneratorDefinition`;
- or `Doctrine\ORM\Mapping\ClassMetadata::isIdGeneratorTable()`.
## BC Break: Removed possibility to extend the doctrine mapping xml schema with anything
If you want to extend it now you have to provide your own validation schema.
## New method `Doctrine\ORM\EntityManagerInterface#wrapInTransaction($func)`
Works the same as `Doctrine\ORM\EntityManagerInterface#transactional()` but returns any value returned from `$func` closure rather than just _non-empty value returned from the closure or true_.

View File

@@ -39,12 +39,12 @@
"doctrine/annotations": "^1.13",
"doctrine/coding-standard": "^9.0",
"phpbench/phpbench": "^0.16.10 || ^1.0",
"phpstan/phpstan": "0.12.99",
"phpstan/phpstan": "1.2.0",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.4",
"squizlabs/php_codesniffer": "3.6.1",
"symfony/cache": "^4.4 || ^5.2",
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"vimeo/psalm": "4.10.0"
"vimeo/psalm": "4.13.1"
},
"conflict": {
"doctrine/annotations": "<1.13 || >= 2.0"

View File

@@ -184,6 +184,8 @@ in well defined units of work. Work with your objects and modify
them as usual and when you're done call ``EntityManager#flush()``
to make your changes persistent.
.. _unit-of-work:
The Unit of Work
~~~~~~~~~~~~~~~~

View File

@@ -85,9 +85,9 @@ Or if you prefer YAML:
Inside the ``Setup`` methods several assumptions are made:
- If `$isDevMode` is true caching is done in memory with the ``ArrayCache``. Proxy objects are recreated on every request.
- If `$isDevMode` is false, check for Caches in the order APC, Xcache, Memcache (127.0.0.1:11211), Redis (127.0.0.1:6379) unless `$cache` is passed as fourth argument.
- If `$isDevMode` is false, set then proxy classes have to be explicitly created through the command line.
- If ``$isDevMode`` is true caching is done in memory with the ``ArrayCache``. Proxy objects are recreated on every request.
- If ``$isDevMode`` is false, check for Caches in the order APC, Xcache, Memcache (127.0.0.1:11211), Redis (127.0.0.1:6379) unless `$cache` is passed as fourth argument.
- If ``$isDevMode`` is false, set then proxy classes have to be explicitly created through the command line.
- If third argument `$proxyDir` is not set, use the systems temporary directory.
If you want to configure Doctrine in more detail, take a look at the :doc:`Advanced Configuration <reference/advanced-configuration>` section.

View File

@@ -127,45 +127,46 @@ Registering Events
There are two ways to register an event:
* *All events* can be registered by calling ``$eventManager->addEventListener()``
or ``eventManager->addEventSubscriber()``, see :ref:`listening-and-subscribing-to-lifecycle-events`
or ``eventManager->addEventSubscriber()``, see
:ref:`Listening and subscribing to Lifecycle Events<listening-and-subscribing-to-lifecycle-events>`
* *Lifecycle Callbacks* can also be registered in the entity mapping (annotation, attribute, etc.),
see :ref:`lifecycle-callbacks`
see :ref:`Lifecycle Callbacks<lifecycle-callbacks>`
Events Overview
---------------
+-----------------------------+-----------------------+-----------+
| Event | Dispatched by | Lifecycle |
| | | Callback |
+=============================+=======================+===========+
| ``preRemove`` | ``$em->remove()`` | Yes |
+-----------------------------+-----------------------+-----------+
| ``postRemove`` | ``$em->flush()`` | Yes |
+-----------------------------+-----------------------+-----------+
| ``prePersist`` | ``$em->persist()`` | Yes |
| | on *initial* persist | |
+-----------------------------+-----------------------+-----------+
| ``postPersist`` | ``$em->flush()`` | Yes |
+-----------------------------+-----------------------+-----------+
| ``preUpdate`` | ``$em->flush()`` | Yes |
+-----------------------------+-----------------------+-----------+
| ``postUpdate`` | ``$em->flush()`` | Yes |
+-----------------------------+-----------------------+-----------+
| ``postLoad`` | Loading from database | Yes |
+-----------------------------+-----------------------+-----------+
| ``loadClassMetadata`` | Loading of mapping | No |
| | metadata | |
+-----------------------------+-----------------------+-----------+
| ``onClassMetadataNotFound`` | ``MappingException`` | No |
+-----------------------------+-----------------------+-----------+
| ``preFlush`` | ``$em->flush()`` | Yes |
+-----------------------------+-----------------------+-----------+
| ``onFlush`` | ``$em->flush()`` | No |
+-----------------------------+-----------------------+-----------+
| ``postFlush`` | ``$em->flush()`` | No |
+-----------------------------+-----------------------+-----------+
| ``onClear`` | ``$em->clear()`` | No |
+-----------------------------+-----------------------+-----------+
+-----------------------------------------------------------------+-----------------------+-----------+
| Event | Dispatched by | Lifecycle |
| | | Callback |
+=================================================================+=======================+===========+
| :ref:`preRemove<reference-events-pre-remove>` | ``$em->remove()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postRemove<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`prePersist<reference-events-pre-persist>` | ``$em->persist()`` | Yes |
| | on *initial* persist | |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postPersist<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`preUpdate<reference-events-pre-update>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postUpdate<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postLoad<reference-events-post-load>` | Loading from database | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`loadClassMetadata<reference-events-load-class-metadata>` | Loading of mapping | No |
| | metadata | |
+-----------------------------------------------------------------+-----------------------+-----------+
| ``onClassMetadataNotFound`` | ``MappingException`` | No |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`preFlush<reference-events-pre-flush>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`onFlush<reference-events-on-flush>` | ``$em->flush()`` | No |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postFlush<reference-events-post-flush>` | ``$em->flush()`` | No |
+-----------------------------------------------------------------+-----------------------+-----------+
| ``onClear`` | ``$em->clear()`` | No |
+-----------------------------------------------------------------+-----------------------+-----------+
Naming convention
~~~~~~~~~~~~~~~~~
@@ -254,15 +255,6 @@ events during the life-time of their registered entities.
cascade remove relations. In this case, you should load yourself the proxy in
the associated pre event.
You can access the Event constants from the ``Events`` class in the
ORM package.
.. code-block:: php
<?php
use Doctrine\ORM\Events;
echo Events::preUpdate;
These can be hooked into by two different types of event
listeners:
@@ -297,135 +289,104 @@ specific to a particular entity class's lifecycle.
.. note::
Note that Licecycle Callbacks are not supported for Embeddables.
Lifecycle Callbacks are not supported for :doc:`Embeddables </tutorials/embeddables>`.
.. code-block:: php
.. configuration-block::
<?php
.. code-block:: attribute
/** @Entity @HasLifecycleCallbacks */
class User
{
// ...
<?php
/**
* @Column(type="string", length=255)
* #[Entity]
* #[HasLifecycleCallbacks]
*/
public $value;
/** @Column(name="created_at", type="string", length=255) */
private $createdAt;
/** @PrePersist */
public function doStuffOnPrePersist()
{
$this->createdAt = date('Y-m-d H:i:s');
}
/** @PrePersist */
public function doOtherStuffOnPrePersist()
{
$this->value = 'changed from prePersist callback!';
}
/** @PostPersist */
public function doStuffOnPostPersist()
{
$this->value = 'changed from postPersist callback!';
}
/** @PostLoad */
public function doStuffOnPostLoad()
{
$this->value = 'changed from postLoad callback!';
}
/** @PreUpdate */
public function doStuffOnPreUpdate()
{
$this->value = 'changed from preUpdate callback!';
}
}
Note that the methods set as lifecycle callbacks need to be public and,
when using these annotations, you have to apply the
``@HasLifecycleCallbacks`` marker annotation on the entity class.
If you want to register lifecycle callbacks from YAML or XML you
can do it with the following.
.. code-block:: yaml
User:
type: entity
fields:
# ...
name:
type: string(50)
lifecycleCallbacks:
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ]
postPersist: [ doStuffOnPostPersist ]
In YAML the ``key`` of the lifecycleCallbacks entry is the event that you
are triggering on and the value is the method (or methods) to call. The allowed
event types are the ones listed in the previous Lifecycle Events section.
XML would look something like this:
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="User">
<lifecycle-callbacks>
<lifecycle-callback type="prePersist" method="doStuffOnPrePersist"/>
<lifecycle-callback type="postPersist" method="doStuffOnPostPersist"/>
</lifecycle-callbacks>
</entity>
</doctrine-mapping>
In XML the ``type`` of the lifecycle-callback entry is the event that you
are triggering on and the ``method`` is the method to call. The allowed event
types are the ones listed in the previous Lifecycle Events section.
When using YAML or XML you need to remember to create public methods to match the
callback names you defined. E.g. in these examples ``doStuffOnPrePersist()``,
``doOtherStuffOnPrePersist()`` and ``doStuffOnPostPersist()`` methods need to be
defined on your ``User`` model.
.. code-block:: php
<?php
// ...
class User
{
// ...
public function doStuffOnPrePersist()
class User
{
// ...
}
public function doOtherStuffOnPrePersist()
#[Column(type: 'string', length: 255)]
public $value;
#[PrePersist]
public function doStuffOnPrePersist()
{
$this->createdAt = date('Y-m-d H:i:s');
}
#[PrePersist]
public function doOtherStuffOnPrePersist()
{
$this->value = 'changed from prePersist callback!';
}
#[PostLoad]
public function doStuffOnPostLoad()
{
$this->value = 'changed from postLoad callback!';
}
}
.. code-block:: annotation
<?php
/**
* @Entity
* @HasLifecycleCallbacks
*/
class User
{
// ...
}
public function doStuffOnPostPersist()
{
// ...
}
}
/** @Column(type="string", length=255) */
public $value;
/** @PrePersist */
public function doStuffOnPrePersist()
{
$this->createdAt = date('Y-m-d H:i:s');
}
/** @PrePersist */
public function doOtherStuffOnPrePersist()
{
$this->value = 'changed from prePersist callback!';
}
/** @PostLoad */
public function doStuffOnPostLoad()
{
$this->value = 'changed from postLoad callback!';
}
}
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="User">
<!-- ... -->
<lifecycle-callbacks>
<lifecycle-callback type="prePersist" method="doStuffOnPrePersist"/>
<lifecycle-callback type="prePersist" method="doOtherStuffOnPrePersist"/>
<lifecycle-callback type="postLoad" method="doStuffOnPostLoad"/>
</lifecycle-callbacks>
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
fields:
# ...
value:
type: string(255)
lifecycleCallbacks:
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ]
postLoad: [ doStuffOnPostLoad ]
Lifecycle Callbacks Event Argument
----------------------------------
@@ -462,7 +423,7 @@ behaviors across different entity classes.
Note that they require much more detailed knowledge about the inner
workings of the ``EntityManager`` and ``UnitOfWork`` classes. Please
read the :ref:`reference-events-implementing-listeners` section
read the :ref:`Implementing Event Listeners<reference-events-implementing-listeners>` section
carefully if you are trying to write your own listener.
For event subscribers, there are no surprises. They declare the
@@ -531,8 +492,10 @@ EventManager that is passed to the EntityManager factory:
.. code-block:: php
<?php
use Doctrine\ORM\Events;
$eventManager = new EventManager();
$eventManager->addEventListener(array(Events::preUpdate), new MyEventListener());
$eventManager->addEventListener([Events::preUpdate], new MyEventListener());
$eventManager->addEventSubscriber(new MyEventSubscriber());
$entityManager = EntityManager::create($dbOpts, $config, $eventManager);
@@ -543,7 +506,9 @@ EntityManager was created:
.. code-block:: php
<?php
$entityManager->getEventManager()->addEventListener(array(Events::preUpdate), new MyEventListener());
use Doctrine\ORM\Events;
$entityManager->getEventManager()->addEventListener([Events::preUpdate], new MyEventListener());
$entityManager->getEventManager()->addEventSubscriber(new MyEventSubscriber());
.. _reference-events-implementing-listeners:
@@ -563,6 +528,8 @@ the restrictions apply as well, with the additional restriction
that (prior to version 2.4) you do not have access to the
``EntityManager`` or ``UnitOfWork`` APIs inside these events.
.. _reference-events-pre-persist:
prePersist
~~~~~~~~~~
@@ -588,6 +555,8 @@ The following restrictions apply to ``prePersist``:
- Doctrine will not recognize changes made to relations in a prePersist
event. This includes modifications to
collections such as additions, removals or replacement.
.. _reference-events-pre-remove:
preRemove
~~~~~~~~~
@@ -600,6 +569,8 @@ There are no restrictions to what methods can be called inside the
``preRemove`` event, except when the remove method itself was
called during a flush operation.
.. _reference-events-pre-flush:
preFlush
~~~~~~~~
@@ -622,6 +593,8 @@ result in infinite loop.
}
}
.. _reference-events-on-flush:
onFlush
~~~~~~~
@@ -685,6 +658,8 @@ The following restrictions apply to the onFlush event:
affected entity. This can be done by calling
``$unitOfWork->recomputeSingleEntityChangeSet($classMetadata, $entity)``.
.. _reference-events-post-flush:
postFlush
~~~~~~~~~
@@ -705,6 +680,8 @@ postFlush
}
}
.. _reference-events-pre-update:
preUpdate
~~~~~~~~~
@@ -789,6 +766,8 @@ Restrictions for this event:
API are strongly discouraged and don't work as expected outside the
flush operation.
.. _reference-events-post-update-remove-persist:
postUpdate, postRemove, postPersist
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -798,6 +777,8 @@ database, but you can use these events to alter non-persistable items,
like non-mapped fields, logging or even associated classes that are
not directly mapped by Doctrine.
.. _reference-events-post-load:
postLoad
~~~~~~~~
@@ -814,7 +795,19 @@ An entity listener is a lifecycle listener class used for an entity.
.. configuration-block::
.. code-block:: php
.. code-block:: attribute
<?php
namespace MyProject\Entity;
use App\EventListener\UserListener;
#[Entity]
#[EntityListeners([UserListener::class])]
class User
{
// ....
}
.. code-block:: annotation
<?php
namespace MyProject\Entity;
@@ -1010,6 +1003,8 @@ Implementing your own resolver :
$configurations->setEntityListenerResolver(new MyEntityListenerResolver);
EntityManager::create(.., $configurations, ..);
.. _reference-events-load-class-metadata:
Load ClassMetadata Event
------------------------

View File

@@ -40,7 +40,7 @@ easily using a combination of ``count`` and ``slice``.
``removeElement`` directly issued DELETE queries to the database from
version 2.4.0 to 2.7.0. This circumvents the flush operation and might run
outside a transactional boundary if you don't create one yourself. We
consider this a critical bug in the assumptio of how the ORM works and
consider this a critical bug in the assumption of how the ORM works and
reverted ``removeElement`` EXTRA_LAZY behavior in 2.7.1.

View File

@@ -81,7 +81,8 @@ that directory with the following contents:
{
"require": {
"doctrine/orm": "^2.6.2",
"doctrine/orm": "^2.10.2",
"doctrine/dbal": "^3.1.1",
"symfony/yaml": "2.*",
"symfony/cache": "^5.3"
},
@@ -112,6 +113,14 @@ Add the following directories:
.. note::
The YAML driver is deprecated and will be removed in version 3.0.
It is strongly recommended to switch to one of the other mappings.
.. note::
It is strongly recommended that you require ``doctrine/dbal`` in your
``composer.json`` as well, because using the ORM means mapping objects
and their fields to database tables and their columns, and that
requires mentioning so-called types that are defined in ``doctrine/dbal``
in your application. Having an explicit requirement means you control
when the upgrade to the next major version happens, so that you can
do the necessary changes in your application beforehand.
Obtaining the EntityManager
---------------------------
@@ -642,7 +651,7 @@ Let's continue by creating a script to display the name of a product based on it
echo sprintf("-%s\n", $product->getName());
Next we'll update a product's name, given its id. This simple example will
help demonstrate Doctrine's implementation of the UnitOfWork pattern. Doctrine
help demonstrate Doctrine's implementation of the :ref:`UnitOfWork pattern <unit-of-work>`. Doctrine
keeps track of all the entities that were retrieved from the Entity Manager,
and can detect when any of those entities' properties have been modified.
As a result, rather than needing to call ``persist($entity)`` for each individual
@@ -1334,7 +1343,7 @@ call this script as follows:
php create_bug.php 1 1 1
See how simple it is to relate a Bug, Reporter, Engineer and Products?
Also recall that thanks to the UnitOfWork pattern, Doctrine will detect
Also recall that thanks to the :ref:`UnitOfWork pattern <unit-of-work>`, Doctrine will detect
these relations and update all of the modified entities in the database
automatically when ``flush()`` is called.

View File

@@ -295,7 +295,7 @@
</xs:choice>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" default="string" />
<xs:attribute name="column" type="xs:NMTOKEN" />
<xs:attribute name="column" type="orm:columntoken" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="unique" type="xs:boolean" default="false" />
<xs:attribute name="nullable" type="xs:boolean" default="false" />
@@ -402,7 +402,7 @@
</xs:choice>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" />
<xs:attribute name="column" type="xs:NMTOKEN" />
<xs:attribute name="column" type="orm:columntoken" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="association-key" type="xs:boolean" default="false" />
<xs:attribute name="column-definition" type="xs:string" />
@@ -497,6 +497,12 @@
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="columntoken" id="columntoken">
<xs:restriction base="xs:token">
<xs:pattern value="[-._:A-Za-z0-9`]+" id="columntoken.pattern"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="many-to-many">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="cache" type="orm:cache" minOccurs="0" maxOccurs="1"/>
@@ -612,7 +618,7 @@
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="type" type="xs:NMTOKEN" default="string" />
<xs:attribute name="column" type="xs:NMTOKEN" />
<xs:attribute name="column" type="orm:columntoken" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:attribute name="unique" type="xs:boolean" default="false" />
<xs:attribute name="nullable" type="xs:boolean" default="false" />

View File

@@ -1253,7 +1253,8 @@ abstract class AbstractQuery
* Will return the configured id if it exists otherwise a hash will be
* automatically generated for you.
*
* @return array<string, string> ($key, $hash)
* @return string[] ($key, $hash)
* @psalm-return array{string, string} ($key, $hash)
*/
protected function getHydrationCacheId()
{

View File

@@ -5,9 +5,7 @@ declare(strict_types=1);
namespace Doctrine\ORM\Cache\Persister\Entity;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\Cache\CacheException;
use Doctrine\ORM\Cache\Exception\CannotUpdateReadOnlyEntity;
use Doctrine\ORM\Utility\StaticClassNameConverter;
/**
* Specific read-only region entity persister

View File

@@ -330,11 +330,9 @@ interface EntityManagerInterface extends ObjectManager
* {@inheritDoc}
*
* @psalm-param string|class-string<T> $className
* @phpstan-param string $className
*
* @return Mapping\ClassMetadata
* @psalm-return Mapping\ClassMetadata<T>
* @phpstan-return Mapping\ClassMetadata<object>
*
* @psalm-template T of object
*/

View File

@@ -79,7 +79,8 @@ class SimpleObjectHydrator extends AbstractHydrator
// We need to find the correct entity class name if we have inheritance in resultset
if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
$discrColumnName = $this->getSQLResultCasing($this->_platform, $this->class->discriminatorColumn['name']);
$discrColumn = $this->class->getDiscriminatorColumn();
$discrColumnName = $this->getSQLResultCasing($this->_platform, $discrColumn['name']);
// Find mapped discriminator column from the result set.
$metaMappingDiscrColumnName = array_search($discrColumnName, $this->resultSetMapping()->metaMappings, true);

View File

@@ -20,6 +20,7 @@ use Doctrine\ORM\Id\AbstractIdGenerator;
use Doctrine\Persistence\Mapping\ClassMetadata;
use Doctrine\Persistence\Mapping\ReflectionService;
use InvalidArgumentException;
use LogicException;
use ReflectionClass;
use ReflectionNamedType;
use ReflectionProperty;
@@ -69,6 +70,26 @@ use const PHP_VERSION_ID;
*
* @template-covariant T of object
* @template-implements ClassMetadata<T>
* @psalm-type FieldMapping = array{
* type: string,
* fieldName: string,
* columnName?: string,
* length?: int,
* id?: bool,
* nullable?: bool,
* columnDefinition?: string,
* precision?: int,
* scale?: int,
* unique?: string,
* inherited?: class-string,
* originalClass?: class-string,
* originalField?: string,
* quoted?: bool,
* requireSQLConversion?: bool,
* declared?: class-string,
* declaredField?: string,
* options?: array<string, mixed>
* }
*/
class ClassMetadataInfo implements ClassMetadata
{
@@ -426,25 +447,7 @@ class ClassMetadataInfo implements ClassMetadata
* Whether a unique constraint should be generated for the column.
*
* @var mixed[]
* @psalm-var array<string, array{
* type: string,
* fieldName: string,
* columnName?: string,
* length?: int,
* id?: bool,
* nullable?: bool,
* columnDefinition?: string,
* precision?: int,
* scale?: int,
* unique?: string,
* inherited?: class-string,
* originalClass?: class-string,
* originalField?: string,
* quoted?: bool,
* requireSQLConversion?: bool,
* declaredField?: string,
* options: array<mixed>
* }>
* @psalm-var array<string, FieldMapping>
*/
public $fieldMappings = [];
@@ -495,7 +498,7 @@ class ClassMetadataInfo implements ClassMetadata
* READ-ONLY: The definition of the discriminator column used in JOINED and SINGLE_TABLE
* inheritance mappings.
*
* @psalm-var array<string, mixed>
* @psalm-var array<string, mixed>|null
*/
public $discriminatorColumn;
@@ -509,7 +512,14 @@ class ClassMetadataInfo implements ClassMetadata
* uniqueConstraints => array
*
* @var mixed[]
* @psalm-var array{name: string, schema: string, indexes: array, uniqueConstraints: array}
* @psalm-var array{
* name: string,
* schema: string,
* indexes: array,
* uniqueConstraints: array,
* options: array<string, mixed>,
* quoted?: bool
* }
*/
public $table;
@@ -665,7 +675,7 @@ class ClassMetadataInfo implements ClassMetadata
/**
* The ReflectionClass instance of the mapped class.
*
* @var ReflectionClass
* @var ReflectionClass|null
*/
public $reflClass;
@@ -1276,18 +1286,7 @@ class ClassMetadataInfo implements ClassMetadata
* @param string $fieldName The field name.
*
* @return mixed[] The field mapping.
* @psalm-return array{
* type: string,
* fieldName: string,
* columnName?: string,
* inherited?: class-string,
* nullable?: bool,
* originalClass?: class-string,
* originalField?: string,
* scale?: int,
* precision?: int,
* length?: int
* }
* @psalm-return FieldMapping
*
* @throws MappingException
*/
@@ -3090,6 +3089,18 @@ class ClassMetadataInfo implements ClassMetadata
}
}
/**
* @return array<string, mixed>
*/
final public function getDiscriminatorColumn(): array
{
if ($this->discriminatorColumn === null) {
throw new LogicException('The discriminator column was not set.');
}
return $this->discriminatorColumn;
}
/**
* Sets the discriminator values used by this class.
* Used for JOINED and SINGLE_TABLE inheritance mapping strategies.

View File

@@ -15,26 +15,26 @@ use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
#[Attribute(Attribute::TARGET_PROPERTY)]
final class Column implements Annotation
{
/** @var string */
/** @var string|null */
public $name;
/** @var mixed */
public $type;
/** @var int */
/** @var int|null */
public $length;
/**
* The precision for a decimal (exact numeric) column (Applies only for decimal column).
*
* @var int
* @var int|null
*/
public $precision = 0;
/**
* The scale for a decimal (exact numeric) column (Applies only for decimal column).
*
* @var int
* @var int|null
*/
public $scale = 0;
@@ -47,7 +47,7 @@ final class Column implements Annotation
/** @var array<string,mixed> */
public $options = [];
/** @var string */
/** @var string|null */
public $columnDefinition;
/**

View File

@@ -249,7 +249,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
$field = $this->quoteStrategy->getColumnName($name, $targetClass, $this->platform);
$whereClauses[] = sprintf('te.%s %s ?', $field, $operator);
$params[] = $value;
$paramTypes[] = PersisterHelper::getTypeOfColumn($field, $targetClass, $this->em);
$paramTypes[] = PersisterHelper::getTypeOfField($name, $targetClass, $this->em)[0];
}
$tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform);

View File

@@ -24,7 +24,7 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
$data = parent::prepareInsertData($entity);
// Populate the discriminator column
$discColumn = $this->class->discriminatorColumn;
$discColumn = $this->class->getDiscriminatorColumn();
$this->columnTypes[$discColumn['name']] = $discColumn['type'];
$data[$this->getDiscriminatorColumnTableName()][$discColumn['name']] = $this->class->discriminatorValue;

View File

@@ -13,7 +13,6 @@ use Doctrine\ORM\Utility\PersisterHelper;
use function array_combine;
use function implode;
use function is_array;
/**
* The joined subclass persister maps a single entity instance to several tables in the
@@ -412,14 +411,15 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
$columnList = [];
$discrColumn = $this->class->discriminatorColumn['name'];
$discrColumnType = $this->class->discriminatorColumn['type'];
$discrColumn = $this->class->getDiscriminatorColumn();
$discrColumnName = $discrColumn['name'];
$discrColumnType = $discrColumn['type'];
$baseTableAlias = $this->getSQLTableAlias($this->class->name);
$resultColumnName = $this->getSQLResultCasing($this->platform, $discrColumn);
$resultColumnName = $this->getSQLResultCasing($this->platform, $discrColumnName);
$this->currentPersisterContext->rsm->addEntityResult($this->class->name, 'r');
$this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName);
$this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumn, false, $discrColumnType);
$this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumnName, false, $discrColumnType);
// Add regular columns
foreach ($this->class->fieldMappings as $fieldName => $mapping) {
@@ -457,7 +457,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
? $baseTableAlias
: $this->getSQLTableAlias($this->class->rootEntityName);
$columnList[] = $tableAlias . '.' . $discrColumn;
$columnList[] = $tableAlias . '.' . $discrColumnName;
// sub tables
foreach ($this->class->subClasses as $subClassName) {
@@ -540,7 +540,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Add discriminator column if it is the topmost class.
if ($this->class->name === $this->class->rootEntityName) {
$columns[] = $this->class->discriminatorColumn['name'];
$columns[] = $this->class->getDiscriminatorColumn()['name'];
}
return $columns;

View File

@@ -44,16 +44,17 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
$rootClass = $this->em->getClassMetadata($this->class->rootEntityName);
$tableAlias = $this->getSQLTableAlias($rootClass->name);
// Append discriminator column
$discrColumn = $this->class->discriminatorColumn['name'];
$discrColumnType = $this->class->discriminatorColumn['type'];
// Append discriminator column
$discrColumn = $this->class->getDiscriminatorColumn();
$discrColumnName = $discrColumn['name'];
$discrColumnType = $discrColumn['type'];
$columnList[] = $tableAlias . '.' . $discrColumn;
$columnList[] = $tableAlias . '.' . $discrColumnName;
$resultColumnName = $this->getSQLResultCasing($this->platform, $discrColumn);
$resultColumnName = $this->getSQLResultCasing($this->platform, $discrColumnName);
$this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName);
$this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumn, false, $discrColumnType);
$this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumnName, false, $discrColumnType);
// Append subclass columns
foreach ($this->class->subClasses as $subClassName) {
@@ -100,7 +101,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
$columns = parent::getInsertColumnList();
// Add discriminator column to the INSERT SQL
$columns[] = $this->class->discriminatorColumn['name'];
$columns[] = $this->class->getDiscriminatorColumn()['name'];
return $columns;
}
@@ -158,11 +159,12 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
$values[] = $this->conn->quote($discrValues[$subclassName]);
}
$discColumnName = $this->class->getDiscriminatorColumn()['name'];
$values = implode(', ', $values);
$discColumn = $this->class->discriminatorColumn['name'];
$tableAlias = $this->getSQLTableAlias($this->class->name);
return $tableAlias . '.' . $discColumn . ' IN (' . $values . ')';
return $tableAlias . '.' . $discColumnName . ' IN (' . $values . ')';
}
/**

View File

@@ -214,7 +214,7 @@ class Parser
*/
private $customOutputWalker;
/** @psalm-var list<AST\SelectExpression> */
/** @psalm-var array<string, AST\SelectExpression> */
private $identVariableExpressions = [];
/**

View File

@@ -369,7 +369,7 @@ class ResultSetMappingBuilder extends ResultSetMapping
{
if (isset($entityMapping['discriminatorColumn']) && $entityMapping['discriminatorColumn']) {
$discriminatorColumn = $entityMapping['discriminatorColumn'];
$discriminatorType = $classMetadata->discriminatorColumn['type'];
$discriminatorType = $classMetadata->getDiscriminatorColumn()['type'];
$this->setDiscriminatorColumn($alias, $discriminatorColumn);
$this->addMetaResult($alias, $discriminatorColumn, $discriminatorColumn, false, $discriminatorType);

View File

@@ -465,7 +465,7 @@ class SqlWalker implements TreeWalker
? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.'
: '';
$sqlParts[] = $sqlTableAlias . $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')';
$sqlParts[] = $sqlTableAlias . $class->getDiscriminatorColumn()['name'] . ' IN (' . implode(', ', $values) . ')';
}
$sql = implode(' AND ', $sqlParts);
@@ -739,7 +739,7 @@ class SqlWalker implements TreeWalker
// Add discriminator columns to SQL
$rootClass = $this->em->getClassMetadata($class->rootEntityName);
$tblAlias = $this->getSQLTableAlias($rootClass->getTableName(), $dqlAlias);
$discrColumn = $rootClass->discriminatorColumn;
$discrColumn = $rootClass->getDiscriminatorColumn();
$columnAlias = $this->getSQLColumnAlias($discrColumn['name']);
$sqlSelectExpressions[] = $tblAlias . '.' . $discrColumn['name'] . ' AS ' . $columnAlias;
@@ -2091,7 +2091,7 @@ class SqlWalker implements TreeWalker
$sql .= $this->getSQLTableAlias($discrClass->getTableName(), $dqlAlias) . '.';
}
$sql .= $class->discriminatorColumn['name'] . ($instanceOfExpr->not ? ' NOT IN ' : ' IN ');
$sql .= $class->getDiscriminatorColumn()['name'] . ($instanceOfExpr->not ? ' NOT IN ' : ' IN ');
$sql .= $this->getChildDiscriminatorsFromClassMetadata($discrClass, $instanceOfExpr);
return $sql;

View File

@@ -151,7 +151,7 @@ EOT
if (empty($metadata)) {
$ui->success('No Metadata Classes to process.');
return;
return 0;
}
foreach ($metadata as $class) {

View File

@@ -1140,7 +1140,11 @@ public function __construct(<params>)
return '';
}
$discrColumn = $metadata->discriminatorColumn;
$discrColumn = $metadata->discriminatorColumn;
if ($discrColumn === null) {
return '';
}
$columnDefinition = 'name="' . $discrColumn['name']
. '", type="' . $discrColumn['type']
. '", length=' . $discrColumn['length'];

View File

@@ -100,6 +100,11 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php
-
message: "#^PHPDoc type Doctrine\\\\Common\\\\Cache\\\\Cache\\|Doctrine\\\\Common\\\\Cache\\\\MultiGetCache of property Doctrine\\\\ORM\\\\Cache\\\\Region\\\\DefaultMultiGetRegion\\:\\:\\$cache is not covariant with PHPDoc type Doctrine\\\\Common\\\\Cache\\\\Cache of overridden property Doctrine\\\\ORM\\\\Cache\\\\Region\\\\DefaultRegion\\:\\:\\$cache\\.$#"
count: 1
path: lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php
-
message: "#^Method Doctrine\\\\ORM\\\\Cache\\\\Region\\\\DefaultRegion\\:\\:getCache\\(\\) should return Doctrine\\\\Common\\\\Cache\\\\CacheProvider but returns Doctrine\\\\Common\\\\Cache\\\\Cache\\.$#"
count: 1
@@ -180,6 +185,11 @@ parameters:
count: 2
path: lib/Doctrine/ORM/EntityManager.php
-
message: "#^Template type T of method Doctrine\\\\ORM\\\\EntityManagerInterface\\:\\:getClassMetadata\\(\\) is not referenced in a parameter\\.$#"
count: 1
path: lib/Doctrine/ORM/EntityManagerInterface.php
-
message: "#^Method Doctrine\\\\ORM\\\\EntityRepository\\:\\:findOneBy\\(\\) should return T\\|null but returns object\\|null\\.$#"
count: 1
@@ -235,6 +245,16 @@ parameters:
count: 1
path: lib/Doctrine/ORM/LazyCriteriaCollection.php
-
message: "#^Offset 'indexes' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php
-
message: "#^Offset 'uniqueConstraints' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php
-
message: "#^Access to an undefined property Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\:\\:\\$cache\\.$#"
count: 2
@@ -417,7 +437,12 @@ parameters:
-
message: "#^Negated boolean expression is always false\\.$#"
count: 2
count: 1
path: lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
-
message: "#^Offset 'indexes'\\|'uniqueConstraints' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
-
@@ -525,21 +550,6 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
-
message: "#^Array \\(array\\('name' \\=\\> string, 'schema' \\=\\> string, 'indexes' \\=\\> array, 'uniqueConstraints' \\=\\> array\\)\\) does not accept key 'options'\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
-
message: "#^Array \\(array\\('name' \\=\\> string, 'schema' \\=\\> string, 'indexes' \\=\\> array, 'uniqueConstraints' \\=\\> array\\)\\) does not accept key 'quoted'\\.$#"
count: 2
path: lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
-
message: "#^Array \\(array\\<string, array\\|string\\>\\) does not accept true\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
-
message: "#^Call to an undefined method ReflectionProperty\\:\\:getType\\(\\)\\.$#"
count: 3
@@ -561,13 +571,13 @@ parameters:
path: lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
-
message: "#^Parameter \\#2 \\$type of static method Doctrine\\\\ORM\\\\Mapping\\\\MappingException\\:\\:invalidInheritanceType\\(\\) expects string, int given\\.$#"
message: "#^Offset 'schema' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} on left side of \\?\\? always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
-
message: "#^Result of && is always false\\.$#"
count: 2
message: "#^Parameter \\#2 \\$type of static method Doctrine\\\\ORM\\\\Mapping\\\\MappingException\\:\\:invalidInheritanceType\\(\\) expects string, int given\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
-
@@ -765,6 +775,11 @@ parameters:
count: 2
path: lib/Doctrine/ORM/Mapping/Driver/AttributeDriver.php
-
message: "#^PHPDoc type array\\<string, int\\> of property Doctrine\\\\ORM\\\\Mapping\\\\Driver\\\\AttributeDriver\\:\\:\\$entityAnnotationClasses is not covariant with PHPDoc type array\\<class\\-string, bool\\|int\\> of overridden property Doctrine\\\\Persistence\\\\Mapping\\\\Driver\\\\AnnotationDriver\\:\\:\\$entityAnnotationClasses\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/Driver/AttributeDriver.php
-
message: "#^Parameter \\#1 \\$metadata of static method Doctrine\\\\ORM\\\\Mapping\\\\Builder\\\\EntityListenerBuilder\\:\\:bindEntityListener\\(\\) expects Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadata, Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadataInfo&Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<T of object\\> given\\.$#"
count: 1
@@ -960,6 +975,11 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
-
message: "#^Offset 'version' on \\*NEVER\\* in isset\\(\\) always exists and is always null\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php
-
message: "#^Parameter \\#1 \\$metadata of static method Doctrine\\\\ORM\\\\Mapping\\\\Builder\\\\EntityListenerBuilder\\:\\:bindEntityListener\\(\\) expects Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadata, Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<T of object\\> given\\.$#"
count: 1
@@ -1115,6 +1135,11 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
-
message: "#^Offset 'usage' on array\\{usage\\: string, region\\?\\: string\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
-
message: "#^Parameter \\#1 \\$metadata of static method Doctrine\\\\ORM\\\\Mapping\\\\Builder\\\\EntityListenerBuilder\\:\\:bindEntityListener\\(\\) expects Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadata, Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<T of object\\> given\\.$#"
count: 1
@@ -1380,15 +1405,30 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php
-
message: "#^PHPDoc type array\\<string\\> of property Doctrine\\\\ORM\\\\Query\\\\Expr\\\\Andx\\:\\:\\$allowedClasses is not covariant with PHPDoc type array\\<int, class\\-string\\> of overridden property Doctrine\\\\ORM\\\\Query\\\\Expr\\\\Base\\:\\:\\$allowedClasses\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/Expr/Andx.php
-
message: "#^PHPDoc type array\\<string\\> of property Doctrine\\\\ORM\\\\Query\\\\Expr\\\\Orx\\:\\:\\$allowedClasses is not covariant with PHPDoc type array\\<int, class\\-string\\> of overridden property Doctrine\\\\ORM\\\\Query\\\\Expr\\\\Base\\:\\:\\$allowedClasses\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/Expr/Orx.php
-
message: "#^PHPDoc type array\\<string\\> of property Doctrine\\\\ORM\\\\Query\\\\Expr\\\\Select\\:\\:\\$allowedClasses is not covariant with PHPDoc type array\\<int, class\\-string\\> of overridden property Doctrine\\\\ORM\\\\Query\\\\Expr\\\\Base\\:\\:\\$allowedClasses\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/Expr/Select.php
-
message: "#^Property Doctrine\\\\ORM\\\\Query\\\\FilterCollection\\:\\:\\$em \\(Doctrine\\\\ORM\\\\EntityManager\\) does not accept Doctrine\\\\ORM\\\\EntityManagerInterface\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/FilterCollection.php
-
message: "#^Array \\(array\\<int, Doctrine\\\\ORM\\\\Query\\\\AST\\\\SelectExpression\\>\\) does not accept key non\\-empty\\-string\\.$#"
message: "#^Property Doctrine\\\\ORM\\\\Query\\\\FilterCollection\\:\\:\\$filterHash is never written, only read\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/Parser.php
path: lib/Doctrine/ORM/Query/FilterCollection.php
-
message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#"
@@ -1422,14 +1462,19 @@ parameters:
path: lib/Doctrine/ORM/Query/Parser.php
-
message: "#^Result of && is always false\\.$#"
count: 1
message: "#^Unreachable statement \\- code above always terminates\\.$#"
count: 3
path: lib/Doctrine/ORM/Query/Parser.php
-
message: "#^Unreachable statement \\- code above always terminates\\.$#"
count: 4
path: lib/Doctrine/ORM/Query/Parser.php
message: "#^Offset 'columns' on array\\{name\\: string, entities\\: array, columns\\: array\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php
-
message: "#^Offset 'entities' on array\\{name\\: string, entities\\: array, columns\\: array\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php
-
message: "#^Parameter \\#2 \\$class of static method Doctrine\\\\ORM\\\\Utility\\\\PersisterHelper\\:\\:getTypeOfColumn\\(\\) expects Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadata, Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadataInfo given\\.$#"
@@ -1476,6 +1521,16 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Query/SqlWalker.php
-
message: "#^Offset 'resultVariable' on array\\{metadata\\: Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadata, parent\\: string, relation\\: array, map\\: mixed, nestingLevel\\: int, token\\: array\\} in isset\\(\\) does not exist\\.$#"
count: 3
path: lib/Doctrine/ORM/Query/SqlWalker.php
-
message: "#^Offset string on array\\<int, array\\{class\\: Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadata, dqlAlias\\: string, resultAlias\\: string\\}\\> in isset\\(\\) does not exist\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/SqlWalker.php
-
message: "#^Parameter \\#1 \\$entity of static method Doctrine\\\\ORM\\\\OptimisticLockException\\:\\:lockFailed\\(\\) expects object, class\\-string\\<object\\> given\\.$#"
count: 1
@@ -1982,7 +2037,7 @@ parameters:
path: lib/Doctrine/ORM/QueryBuilder.php
-
message: "#^Parameter \\#2 \\$dqlPart of method Doctrine\\\\ORM\\\\QueryBuilder\\:\\:add\\(\\) expects array\\<'join'\\|int, array\\<int\\|string, object\\>\\|string\\>\\|object\\|string, array\\<string, Doctrine\\\\ORM\\\\Query\\\\Expr\\\\Join\\>&nonEmpty given\\.$#"
message: "#^Parameter \\#2 \\$dqlPart of method Doctrine\\\\ORM\\\\QueryBuilder\\:\\:add\\(\\) expects array\\<'join'\\|int, array\\<int\\|string, object\\>\\|string\\>\\|object\\|string, non\\-empty\\-array\\<string, Doctrine\\\\ORM\\\\Query\\\\Expr\\\\Join\\> given\\.$#"
count: 2
path: lib/Doctrine/ORM/QueryBuilder.php
@@ -2021,11 +2076,6 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php
-
message: "#^Method Doctrine\\\\ORM\\\\Tools\\\\Console\\\\Command\\\\ConvertMappingCommand\\:\\:execute\\(\\) should return int but empty return statement found\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php
-
message: "#^Parameter \\#1 \\$metadata of method Doctrine\\\\ORM\\\\Tools\\\\Export\\\\Driver\\\\AbstractExporter\\:\\:setMetadata\\(\\) expects array\\<int, Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadata\\>, array\\<Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\> given\\.$#"
count: 1
@@ -2062,7 +2112,47 @@ parameters:
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Result of && is always false\\.$#"
message: "#^Offset 'allocationSize' on array\\{sequenceName\\: string, allocationSize\\: string, initialValue\\: string, quoted\\?\\: mixed\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Offset 'indexes' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Offset 'initialValue' on array\\{sequenceName\\: string, allocationSize\\: string, initialValue\\: string, quoted\\?\\: mixed\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Offset 'name' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Offset 'options' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Offset 'schema' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Offset 'sequenceName' on array\\{sequenceName\\: string, allocationSize\\: string, initialValue\\: string, quoted\\?\\: mixed\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Offset 'uniqueConstraints' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
-
message: "#^Property Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadataInfo\\<object\\>\\:\\:\\$lifecycleCallbacks \\(array\\<string, array\\<int, string\\>\\>\\) in isset\\(\\) is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/EntityGenerator.php
@@ -2096,6 +2186,36 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php
-
message: "#^Offset 'indexes' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
-
message: "#^Offset 'name' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
-
message: "#^Offset 'options' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
-
message: "#^Offset 'schema' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
-
message: "#^Offset 'uniqueConstraints' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
-
message: "#^Offset 'version' on array\\{type\\: string, fieldName\\: string, columnName\\?\\: string, length\\?\\: int, id\\?\\: bool, nullable\\?\\: bool, columnDefinition\\?\\: string, precision\\?\\: int, \\.\\.\\.\\} in isset\\(\\) does not exist\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
-
message: "#^Parameter \\#1 \\$policy of method Doctrine\\\\ORM\\\\Tools\\\\Export\\\\Driver\\\\AbstractExporter\\:\\:_getChangeTrackingPolicyString\\(\\) expects 1\\|2\\|3, int given\\.$#"
count: 1
@@ -2106,6 +2226,11 @@ parameters:
count: 2
path: lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
-
message: "#^Property Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadataInfo\\<object\\>\\:\\:\\$lifecycleCallbacks \\(array\\<string, array\\<int, string\\>\\>\\) in isset\\(\\) is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php
-
message: "#^Right side of && is always true\\.$#"
count: 2
@@ -2116,6 +2241,16 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php
-
message: "#^Property Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadataInfo\\<object\\>\\:\\:\\$lifecycleCallbacks \\(array\\<string, array\\<int, string\\>\\>\\) in isset\\(\\) is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php
-
message: "#^Property Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadataInfo\\<object\\>\\:\\:\\$table \\(array\\<string, array\\|bool\\|string\\>\\) on left side of \\?\\? is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php
-
message: "#^Return type \\(void\\) of method Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\CountWalker\\:\\:walkSelectStatement\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\ORM\\\\Query\\\\TreeWalker\\:\\:walkSelectStatement\\(\\)$#"
count: 1
@@ -2126,6 +2261,11 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php
-
message: "#^Offset 'parent' on array\\{metadata\\: Doctrine\\\\ORM\\\\Mapping\\\\ClassMetadata, parent\\: string, relation\\: array, map\\: mixed, nestingLevel\\: int, token\\: array\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php
-
message: "#^Return type \\(void\\) of method Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\LimitSubqueryWalker\\:\\:walkSelectStatement\\(\\) should be compatible with return type \\(string\\) of method Doctrine\\\\ORM\\\\Query\\\\TreeWalker\\:\\:walkSelectStatement\\(\\)$#"
count: 1
@@ -2161,6 +2301,21 @@ parameters:
count: 1
path: lib/Doctrine/ORM/Tools/SchemaTool.php
-
message: "#^Offset 'indexes' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/SchemaTool.php
-
message: "#^Offset 'options' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/SchemaTool.php
-
message: "#^Offset 'uniqueConstraints' on array\\{name\\: string, schema\\: string, indexes\\: array, uniqueConstraints\\: array, options\\: array\\<string, mixed\\>, quoted\\?\\: bool\\} in isset\\(\\) always exists and is not nullable\\.$#"
count: 1
path: lib/Doctrine/ORM/Tools/SchemaTool.php
-
message: "#^Binary operation \"&\" between string and 3 results in an error\\.$#"
count: 1

View File

@@ -21,7 +21,7 @@ parameters:
message: '/^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getSQLResultCasing\(\)\.$/'
path: lib/Doctrine/ORM/Internal/SQLResultCasing.php
-
message: '/^Parameter \$stmt of method .* has invalid typehint type Doctrine\\DBAL\\Driver\\ResultStatement\.$/'
message: '/^Parameter \$stmt of method .* has invalid type Doctrine\\DBAL\\Driver\\ResultStatement\.$/'
path: lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
-
message: '/^Class Doctrine\\DBAL\\Driver\\ResultStatement not found\.$/'
@@ -30,15 +30,6 @@ parameters:
message: '/^Call to static method ensure\(\) on an unknown class Doctrine\\DBAL\\ForwardCompatibility\\Result\.$/'
path: lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
# Forward compatibility for DBAL 3.2
- '/^Call to an undefined method Doctrine\\DBAL\\Cache\\QueryCacheProfile::[gs]etResultCache\(\)\.$/'
-
message: '/^Call to an undefined static method Doctrine\\DBAL\\Configuration::[gs]etResultCache\(\)\.$/'
path: lib/Doctrine/ORM/Configuration.php
-
message: '/^Parameter #3 \$resultCache of class Doctrine\\DBAL\\Cache\\QueryCacheProfile constructor/'
path: lib/Doctrine/ORM/AbstractQuery.php
# False positive
-
message: '/^Variable \$offset in isset\(\) always exists and is not nullable\.$/'

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.10.0@916b098b008f6de4543892b1e0651c1c3b92cbfa">
<files psalm-version="4.13.1@5cf660f63b548ccd4a56f62d916ee4d6028e01a3">
<file src="lib/Doctrine/ORM/AbstractQuery.php">
<DeprecatedClass occurrences="1">
<code>IterableResult</code>
@@ -7,9 +7,6 @@
<DeprecatedMethod occurrences="1">
<code>iterate</code>
</DeprecatedMethod>
<DocblockTypeContradiction occurrences="1">
<code>$resultCacheDriver !== null &amp;&amp; ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache)</code>
</DocblockTypeContradiction>
<FalsableReturnStatement occurrences="1">
<code>! $filteredParameters-&gt;isEmpty() ? $filteredParameters-&gt;first() : null</code>
</FalsableReturnStatement>
@@ -518,15 +515,16 @@
<PropertyTypeCoercion occurrences="1">
<code>new $metadataFactoryClassName()</code>
</PropertyTypeCoercion>
<RedundantCondition occurrences="1">
<RedundantCondition occurrences="2">
<code>is_object($connection)</code>
<code>is_object($connection)</code>
</RedundantCondition>
<RedundantConditionGivenDocblockType occurrences="1">
<code>$this-&gt;filterCollection !== null</code>
</RedundantConditionGivenDocblockType>
<TypeDoesNotContainType occurrences="2">
<code>$connection instanceof Connection</code>
<code>': "' . $connection . '"'</code>
<code>gettype($connection)</code>
</TypeDoesNotContainType>
</file>
<file src="lib/Doctrine/ORM/EntityManagerInterface.php">
@@ -604,9 +602,6 @@
<PossiblyNullPropertyAssignmentValue occurrences="1">
<code>$sequenceName</code>
</PossiblyNullPropertyAssignmentValue>
<RedundantCastGivenDocblockType occurrences="1">
<code>(string) $em-&gt;getConnection()-&gt;lastInsertId($this-&gt;sequenceName)</code>
</RedundantCastGivenDocblockType>
</file>
<file src="lib/Doctrine/ORM/Id/TableGenerator.php">
<PossiblyFalseOperand occurrences="3">
@@ -777,9 +772,7 @@
</RedundantCastGivenDocblockType>
</file>
<file src="lib/Doctrine/ORM/Mapping/ClassMetadata.php">
<PropertyNotSetInConstructor occurrences="8">
<code>ClassMetadata</code>
<code>ClassMetadata</code>
<PropertyNotSetInConstructor occurrences="6">
<code>ClassMetadata</code>
<code>ClassMetadata</code>
<code>ClassMetadata</code>
@@ -821,12 +814,13 @@
<DeprecatedConstant occurrences="1">
<code>ClassMetadata::GENERATOR_TYPE_UUID</code>
</DeprecatedConstant>
<DeprecatedMethod occurrences="2">
<DeprecatedMethod occurrences="3">
<code>addNamedNativeQuery</code>
<code>addNamedQuery</code>
<code>getName</code>
</DeprecatedMethod>
<DocblockTypeContradiction occurrences="2">
<code>$class-&gt;reflClass</code>
<code>! $definition</code>
<code>$definition</code>
</DocblockTypeContradiction>
<InvalidArrayOffset occurrences="1">
@@ -869,6 +863,9 @@
<code>$parent-&gt;table</code>
<code>$parent-&gt;versionField</code>
</NoInterfaceProperties>
<PossiblyInvalidArrayAssignment occurrences="1">
<code>$subClass-&gt;table[$indexType][$indexName]</code>
</PossiblyInvalidArrayAssignment>
<PossiblyInvalidIterator occurrences="1">
<code>$parentClass-&gt;table[$indexType]</code>
</PossiblyInvalidIterator>
@@ -890,7 +887,8 @@
<PropertyTypeCoercion occurrences="1">
<code>$subClass-&gt;table</code>
</PropertyTypeCoercion>
<RedundantConditionGivenDocblockType occurrences="1">
<RedundantConditionGivenDocblockType occurrences="2">
<code>$parent-&gt;idGenerator</code>
<code>$parent-&gt;idGenerator</code>
</RedundantConditionGivenDocblockType>
<UndefinedInterfaceMethod occurrences="17">
@@ -921,13 +919,17 @@
<DeprecatedConstant occurrences="1">
<code>self::GENERATOR_TYPE_UUID</code>
</DeprecatedConstant>
<DeprecatedMethod occurrences="1">
<code>canEmulateSchemas</code>
</DeprecatedMethod>
<DeprecatedProperty occurrences="4">
<code>$this-&gt;columnNames</code>
<code>$this-&gt;columnNames</code>
<code>$this-&gt;columnNames</code>
<code>$this-&gt;columnNames</code>
</DeprecatedProperty>
<DocblockTypeContradiction occurrences="1">
<DocblockTypeContradiction occurrences="2">
<code>! $this-&gt;table</code>
<code>$this-&gt;table</code>
</DocblockTypeContradiction>
<InvalidDocblock occurrences="4">
@@ -936,9 +938,10 @@
<code>protected function _validateAndCompleteOneToOneMapping(array $mapping)</code>
<code>public $inheritanceType = self::INHERITANCE_TYPE_NONE;</code>
</InvalidDocblock>
<InvalidNullableReturnType occurrences="2">
<InvalidNullableReturnType occurrences="3">
<code>ReflectionProperty</code>
<code>ReflectionProperty</code>
<code>getReflectionClass</code>
</InvalidNullableReturnType>
<InvalidPropertyAssignmentValue occurrences="1">
<code>$definition</code>
@@ -967,7 +970,8 @@
<MoreSpecificReturnType occurrences="1">
<code>array{usage: int, region: string|null}</code>
</MoreSpecificReturnType>
<NullableReturnStatement occurrences="2">
<NullableReturnStatement occurrences="3">
<code>$this-&gt;reflClass</code>
<code>$this-&gt;reflFields[$name]</code>
<code>$this-&gt;reflFields[$this-&gt;identifier[0]]</code>
</NullableReturnStatement>
@@ -987,12 +991,17 @@
<code>$queryMapping['resultClass']</code>
<code>$reflService-&gt;getAccessibleProperty($mapping['originalClass'], $mapping['originalField'])</code>
</PossiblyNullArgument>
<PossiblyNullPropertyAssignmentValue occurrences="3">
<code>$reflService-&gt;getClass($this-&gt;name)</code>
<code>$reflService-&gt;getClass($this-&gt;name)</code>
<PossiblyNullPropertyAssignmentValue occurrences="1">
<code>null</code>
</PossiblyNullPropertyAssignmentValue>
<PossiblyNullReference occurrences="6">
<PossiblyNullPropertyFetch occurrences="2">
<code>$embeddable-&gt;reflClass-&gt;name</code>
<code>$this-&gt;reflClass-&gt;name</code>
</PossiblyNullPropertyFetch>
<PossiblyNullReference occurrences="9">
<code>getProperty</code>
<code>getProperty</code>
<code>getProperty</code>
<code>getValue</code>
<code>getValue</code>
<code>getValue</code>
@@ -1013,12 +1022,10 @@
<code>$this-&gt;fieldMappings[$idProperty]['columnName']</code>
<code>$this-&gt;fieldMappings[$idProperty]['columnName']</code>
</PossiblyUndefinedArrayOffset>
<PropertyNotSetInConstructor occurrences="8">
<code>$discriminatorColumn</code>
<PropertyNotSetInConstructor occurrences="6">
<code>$idGenerator</code>
<code>$isVersioned</code>
<code>$namespace</code>
<code>$reflClass</code>
<code>$sequenceGeneratorDefinition</code>
<code>$table</code>
<code>$tableGeneratorDefinition</code>
@@ -1041,21 +1048,11 @@
<code>$mapping !== false</code>
<code>$mapping !== false</code>
</RedundantConditionGivenDocblockType>
<RedundantPropertyInitializationCheck occurrences="1"/>
<TooManyArguments occurrences="2">
<code>joinColumnName</code>
<code>joinColumnName</code>
</TooManyArguments>
</file>
<file src="lib/Doctrine/ORM/Mapping/Column.php">
<PossiblyNullPropertyAssignmentValue occurrences="5">
<code>$columnDefinition</code>
<code>$length</code>
<code>$name</code>
<code>$precision</code>
<code>$scale</code>
</PossiblyNullPropertyAssignmentValue>
</file>
<file src="lib/Doctrine/ORM/Mapping/ColumnResult.php">
<MissingConstructor occurrences="1">
<code>$name</code>
@@ -1084,6 +1081,10 @@
</PossiblyFalseOperand>
</file>
<file src="lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php">
<DeprecatedMethod occurrences="2">
<code>canEmulateSchemas</code>
<code>canEmulateSchemas</code>
</DeprecatedMethod>
<MissingClosureParamType occurrences="1">
<code>$joinColumn</code>
</MissingClosureParamType>
@@ -1104,9 +1105,14 @@
<ArgumentTypeCoercion occurrences="1">
<code>$metadata</code>
</ArgumentTypeCoercion>
<DocblockTypeContradiction occurrences="1">
<DocblockTypeContradiction occurrences="2">
<code>! $class</code>
<code>$class</code>
</DocblockTypeContradiction>
<LessSpecificReturnStatement occurrences="1">
<code>$mapping</code>
</LessSpecificReturnStatement>
<MoreSpecificReturnType occurrences="1"/>
<NoInterfaceProperties occurrences="5">
<code>$metadata-&gt;inheritanceType</code>
<code>$metadata-&gt;isEmbeddedClass</code>
@@ -1121,10 +1127,6 @@
<code>$primaryTable['indexes']</code>
<code>$primaryTable['uniqueConstraints']</code>
</PossiblyUndefinedArrayOffset>
<RedundantConditionGivenDocblockType occurrences="2">
<code>isset($column-&gt;columnDefinition)</code>
<code>isset($column-&gt;name)</code>
</RedundantConditionGivenDocblockType>
<UndefinedInterfaceMethod occurrences="32">
<code>addEntityListener</code>
<code>addLifecycleCallback</code>
@@ -1173,6 +1175,10 @@
<code>$value[1]</code>
<code>$value[1]</code>
</InvalidArrayAccess>
<LessSpecificReturnStatement occurrences="1">
<code>$mapping</code>
</LessSpecificReturnStatement>
<MoreSpecificReturnType occurrences="1"/>
<NonInvariantDocblockPropertyType occurrences="1">
<code>$entityAnnotationClasses</code>
</NonInvariantDocblockPropertyType>
@@ -1189,10 +1195,8 @@
<code>assert($method instanceof ReflectionMethod)</code>
<code>assert($property instanceof ReflectionProperty)</code>
</RedundantCondition>
<RedundantConditionGivenDocblockType occurrences="3">
<RedundantConditionGivenDocblockType occurrences="1">
<code>assert($cacheAttribute instanceof Mapping\Cache)</code>
<code>isset($column-&gt;columnDefinition)</code>
<code>isset($column-&gt;name)</code>
</RedundantConditionGivenDocblockType>
</file>
<file src="lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php">
@@ -1287,11 +1291,7 @@
<code>$indexXml-&gt;options</code>
<code>$uniqueXml-&gt;options</code>
</PossiblyInvalidPropertyFetch>
<RedundantCast occurrences="1">
<code>(string) $attributes-&gt;name</code>
</RedundantCast>
<RedundantCondition occurrences="20">
<code>isset($attributes-&gt;name)</code>
<RedundantCondition occurrences="19">
<code>isset($xmlRoot-&gt;cache)</code>
<code>isset($xmlRoot-&gt;embedded)</code>
<code>isset($xmlRoot-&gt;field)</code>
@@ -1583,16 +1583,7 @@
<InvalidDocblock occurrences="1">
<code>final class PersistentCollection extends AbstractLazyCollection implements Selectable</code>
</InvalidDocblock>
<InvalidReturnStatement occurrences="5">
<code>$persister-&gt;slice($this, $offset, $length)</code>
<code>$this-&gt;collection</code>
<code>new ArrayCollection($persister-&gt;loadCriteria($this, $criteria))</code>
<code>parent::slice($offset, $length)</code>
</InvalidReturnStatement>
<InvalidReturnType occurrences="2">
<code>Collection&lt;TKey, T&gt;</code>
<code>array&lt;TKey,T&gt;</code>
</InvalidReturnType>
<InvalidReturnStatement occurrences="1"/>
<MissingParamType occurrences="2">
<code>$key</code>
<code>$offset</code>
@@ -1627,7 +1618,9 @@
<PropertyNotSetInConstructor occurrences="1">
<code>$backRefFieldName</code>
</PropertyNotSetInConstructor>
<RedundantConditionGivenDocblockType occurrences="3">
<RedundantConditionGivenDocblockType occurrences="5">
<code>$this-&gt;em</code>
<code>$this-&gt;em</code>
<code>is_object($this-&gt;collection)</code>
<code>is_object($value) &amp;&amp; $this-&gt;em</code>
<code>is_object($value) &amp;&amp; $this-&gt;em</code>
@@ -1853,9 +1846,6 @@
<PropertyTypeCoercion occurrences="1">
<code>$this-&gt;currentPersisterContext-&gt;sqlTableAliases</code>
</PropertyTypeCoercion>
<RedundantCondition occurrences="1">
<code>($comparison === Comparison::EQ || $comparison === Comparison::IS) &amp;&amp; $value === null</code>
</RedundantCondition>
<RedundantConditionGivenDocblockType occurrences="1">
<code>$this-&gt;insertSql !== null</code>
</RedundantConditionGivenDocblockType>
@@ -1896,11 +1886,6 @@
<code>$columnList</code>
</PossiblyUndefinedVariable>
</file>
<file src="lib/Doctrine/ORM/Persisters/SqlValueVisitor.php">
<RedundantCondition occurrences="1">
<code>($operator === Comparison::EQ || $operator === Comparison::IS) &amp;&amp; $value === null</code>
</RedundantCondition>
</file>
<file src="lib/Doctrine/ORM/Proxy/ProxyFactory.php">
<ArgumentTypeCoercion occurrences="2">
<code>$classMetadata</code>
@@ -2196,6 +2181,9 @@
<ArgumentTypeCoercion occurrences="1">
<code>$this-&gt;stringPrimary</code>
</ArgumentTypeCoercion>
<DeprecatedMethod occurrences="1">
<code>getLowerExpression</code>
</DeprecatedMethod>
<PropertyNotSetInConstructor occurrences="1">
<code>$stringPrimary</code>
</PropertyNotSetInConstructor>
@@ -2225,6 +2213,9 @@
</PropertyNotSetInConstructor>
</file>
<file src="lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php">
<DeprecatedMethod occurrences="1">
<code>getSqrtExpression</code>
</DeprecatedMethod>
<PropertyNotSetInConstructor occurrences="1">
<code>$simpleArithmeticExpression</code>
</PropertyNotSetInConstructor>
@@ -2263,6 +2254,9 @@
<ArgumentTypeCoercion occurrences="1">
<code>$this-&gt;stringPrimary</code>
</ArgumentTypeCoercion>
<DeprecatedMethod occurrences="1">
<code>getUpperExpression</code>
</DeprecatedMethod>
<PropertyNotSetInConstructor occurrences="1">
<code>$stringPrimary</code>
</PropertyNotSetInConstructor>
@@ -2629,16 +2623,9 @@
<code>call_user_func($functionClass, $functionName)</code>
<code>call_user_func($functionClass, $functionName)</code>
</DocblockTypeContradiction>
<InvalidArrayOffset occurrences="2">
<code>$this-&gt;identVariableExpressions[$dqlAlias]</code>
<code>$this-&gt;queryComponents[$dqlAlias]</code>
</InvalidArrayOffset>
<InvalidNullableReturnType occurrences="1">
<code>SelectStatement|UpdateStatement|DeleteStatement</code>
</InvalidNullableReturnType>
<InvalidPropertyAssignmentValue occurrences="1">
<code>$this-&gt;identVariableExpressions</code>
</InvalidPropertyAssignmentValue>
<InvalidReturnStatement occurrences="9">
<code>$primary</code>
<code>$this-&gt;CollectionMemberExpression()</code>
@@ -2843,27 +2830,36 @@
<code>$renameMode</code>
<code>$renameMode</code>
</ArgumentTypeCoercion>
<PossiblyNullPropertyFetch occurrences="1">
<code>$classMetadata-&gt;reflClass-&gt;name</code>
</PossiblyNullPropertyFetch>
<PossiblyNullReference occurrences="3">
<code>getShortName</code>
<code>getShortName</code>
<code>getShortName</code>
</PossiblyNullReference>
<PossiblyUndefinedArrayOffset occurrences="1">
<code>$class-&gt;fieldMappings[$this-&gt;fieldMappings[$columnName]]['columnName']</code>
</PossiblyUndefinedArrayOffset>
</file>
<file src="lib/Doctrine/ORM/Query/SqlWalker.php">
<DocblockTypeContradiction occurrences="10">
<code>! ($factor instanceof AST\ConditionalFactor)</code>
<code>$condExpr instanceof AST\ConditionalExpression</code>
<code>$condTerm instanceof AST\ConditionalTerm</code>
<code>$simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression</code>
<DocblockTypeContradiction occurrences="8">
<code>$likeExpr-&gt;stringPattern instanceof AST\Functions\FunctionNode</code>
<code>$likeExpr-&gt;stringPattern instanceof AST\PathExpression</code>
<code>$this-&gt;queryComponents[$dqlAlias]['relation'] === null</code>
<code>''</code>
<code>is_numeric($leftExpr) ? $leftExpr : $this-&gt;conn-&gt;quote($leftExpr)</code>
<code>is_numeric($rightExpr) ? $rightExpr : $this-&gt;conn-&gt;quote($rightExpr)</code>
<code>is_numeric($leftExpr)</code>
<code>is_numeric($rightExpr)</code>
<code>is_string($expression)</code>
<code>is_string($stringExpr)</code>
</DocblockTypeContradiction>
<ImplicitToStringCast occurrences="1">
<code>$expr</code>
</ImplicitToStringCast>
<InvalidArgument occurrences="1">
<InvalidArgument occurrences="4">
<code>$condExpr</code>
<code>$condTerm</code>
<code>$factor</code>
<code>$selectedClass['class']-&gt;name</code>
</InvalidArgument>
<InvalidArrayOffset occurrences="1">
@@ -2934,10 +2930,12 @@
<code>$this-&gt;queryComponents</code>
<code>$this-&gt;selectedClasses</code>
</PropertyTypeCoercion>
<RedundantConditionGivenDocblockType occurrences="5">
<RedundantConditionGivenDocblockType occurrences="7">
<code>$leftExpr instanceof AST\Node</code>
<code>$likeExpr-&gt;stringPattern instanceof AST\InputParameter</code>
<code>$rightExpr instanceof AST\Node</code>
<code>$this-&gt;conn-&gt;quote($leftExpr)</code>
<code>$this-&gt;conn-&gt;quote($rightExpr)</code>
<code>$whereClause !== null</code>
<code>($factor-&gt;not ? 'NOT ' : '') . $this-&gt;walkConditionalPrimary($factor-&gt;conditionalPrimary)</code>
</RedundantConditionGivenDocblockType>
@@ -3300,13 +3298,9 @@
<MissingReturnType occurrences="1">
<code>configure</code>
</MissingReturnType>
<PossiblyNullArgument occurrences="2">
<code>$cacheDriver</code>
<PossiblyNullArgument occurrences="1">
<code>$cacheDriver</code>
</PossiblyNullArgument>
<PossiblyNullReference occurrences="1">
<code>deleteAll</code>
</PossiblyNullReference>
</file>
<file src="lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php">
<ArgumentTypeCoercion occurrences="1">
@@ -3337,9 +3331,6 @@
<code>new ClassMetadataExporter()</code>
<code>new EntityGenerator()</code>
</DeprecatedClass>
<InvalidNullableReturnType occurrences="1">
<code>int</code>
</InvalidNullableReturnType>
<MissingReturnType occurrences="1">
<code>configure</code>
</MissingReturnType>
@@ -3479,10 +3470,8 @@
<DeprecatedConstant occurrences="1">
<code>ClassMetadataInfo::GENERATOR_TYPE_UUID</code>
</DeprecatedConstant>
<DocblockTypeContradiction occurrences="3">
<code>$metadata-&gt;reflClass !== null</code>
<DocblockTypeContradiction occurrences="1">
<code>class_exists($metadata-&gt;name)</code>
<code>new ReflectionClass($metadata-&gt;name)</code>
</DocblockTypeContradiction>
<InvalidDocblock occurrences="1">
<code>public function setFieldVisibility($visibility)</code>
@@ -3508,12 +3497,13 @@
<PropertyNotSetInConstructor occurrences="1">
<code>$classToExtend</code>
</PropertyNotSetInConstructor>
<RedundantCastGivenDocblockType occurrences="1">
<RedundantCastGivenDocblockType occurrences="2">
<code>(array) $metadata-&gt;table['options']</code>
<code>(bool) $embeddablesImmutable</code>
</RedundantCastGivenDocblockType>
<RedundantConditionGivenDocblockType occurrences="3">
<code>$metadata-&gt;reflClass</code>
<code>$metadata-&gt;reflClass !== null</code>
<code>$metadata-&gt;sequenceGeneratorDefinition</code>
<code>$metadata-&gt;sequenceGeneratorDefinition</code>
<code>isset($metadata-&gt;lifecycleCallbacks)</code>
</RedundantConditionGivenDocblockType>
</file>
@@ -3588,6 +3578,10 @@
<NonInvariantDocblockPropertyType occurrences="1">
<code>$_extension</code>
</NonInvariantDocblockPropertyType>
<RedundantConditionGivenDocblockType occurrences="2">
<code>$metadata-&gt;table</code>
<code>$metadata-&gt;table</code>
</RedundantConditionGivenDocblockType>
</file>
<file src="lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php">
<ArgumentTypeCoercion occurrences="3">
@@ -3614,10 +3608,12 @@
<PossiblyNullReference occurrences="1">
<code>addAttribute</code>
</PossiblyNullReference>
<RedundantCondition occurrences="1">
<RedundantCondition occurrences="2">
<code>$field['associationKey']</code>
<code>isset($field['associationKey']) &amp;&amp; $field['associationKey']</code>
</RedundantCondition>
<RedundantConditionGivenDocblockType occurrences="1">
<RedundantConditionGivenDocblockType occurrences="2">
<code>$sequenceDefinition</code>
<code>isset($metadata-&gt;lifecycleCallbacks)</code>
</RedundantConditionGivenDocblockType>
</file>
@@ -3654,6 +3650,10 @@
</RedundantConditionGivenDocblockType>
</file>
<file src="lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php">
<DeprecatedMethod occurrences="2">
<code>getCountExpression</code>
<code>getCountExpression</code>
</DeprecatedMethod>
<MoreSpecificImplementedParamType occurrences="1">
<code>$query</code>
</MoreSpecificImplementedParamType>
@@ -3707,7 +3707,8 @@
</PropertyNotSetInConstructor>
</file>
<file src="lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php">
<DocblockTypeContradiction occurrences="2">
<DocblockTypeContradiction occurrences="3">
<code>$AST-&gt;whereClause-&gt;conditionalExpression instanceof ConditionalFactor</code>
<code>$AST-&gt;whereClause-&gt;conditionalExpression instanceof ConditionalPrimary</code>
</DocblockTypeContradiction>
<ImplementedReturnTypeMismatch occurrences="1">
@@ -3719,12 +3720,16 @@
<PossiblyInvalidPropertyAssignmentValue occurrences="1">
<code>$AST-&gt;whereClause-&gt;conditionalExpression</code>
</PossiblyInvalidPropertyAssignmentValue>
<RedundantConditionGivenDocblockType occurrences="1">
<code>$AST-&gt;whereClause-&gt;conditionalExpression instanceof ConditionalExpression</code>
</RedundantConditionGivenDocblockType>
<RedundantConditionGivenDocblockType occurrences="1"/>
</file>
<file src="lib/Doctrine/ORM/Tools/SchemaTool.php">
<DocblockTypeContradiction occurrences="1">
<DeprecatedMethod occurrences="3">
<code>canEmulateSchemas</code>
<code>compare</code>
<code>setExplicitForeignKeyIndexes</code>
</DeprecatedMethod>
<DocblockTypeContradiction occurrences="2">
<code>! $definingClass</code>
<code>$definingClass</code>
</DocblockTypeContradiction>
<MissingClosureParamType occurrences="1">
@@ -3752,6 +3757,11 @@
<code>$indexName</code>
</TypeDoesNotContainType>
</file>
<file src="lib/Doctrine/ORM/Tools/SchemaValidator.php">
<PossiblyNullReference occurrences="1">
<code>isAbstract</code>
</PossiblyNullReference>
</file>
<file src="lib/Doctrine/ORM/Tools/Setup.php">
<DeprecatedClass occurrences="3">
<code>new ClassLoader('Doctrine', $directory)</code>

View File

@@ -30,6 +30,10 @@
<!-- We're calling the deprecated method for BC here. -->
<file name="lib/Doctrine/ORM/Internal/SQLResultCasing.php"/>
<!-- We need to keep the calls for DBAL 2.13 compatibility. -->
<referencedMethod name="Doctrine\DBAL\Cache\QueryCacheProfile::getResultCacheDriver"/>
<referencedMethod name="Doctrine\DBAL\Cache\QueryCacheProfile::setResultCacheDriver"/>
<referencedMethod name="Doctrine\DBAL\Configuration::getResultCacheImpl"/>
<referencedMethod name="Doctrine\DBAL\Configuration::setResultCacheImpl"/>
<referencedMethod name="Doctrine\DBAL\Connection::getSchemaManager"/>
<referencedMethod name="Doctrine\DBAL\Platforms\AbstractPlatform::getGuidExpression"/>
</errorLevel>
@@ -83,6 +87,13 @@
<file name="lib/Doctrine/ORM/QueryBuilder.php"/>
</errorLevel>
</RedundantCastGivenDocblockType>
<!-- Workaround for https://github.com/vimeo/psalm/issues/7026 -->
<ReservedWord>
<errorLevel type="suppress">
<directory name="lib"/>
<directory name="tests"/>
</errorLevel>
</ReservedWord>
<TypeDoesNotContainType>
<errorLevel type="suppress">
<file name="lib/Doctrine/ORM/Internal/SQLResultCasing.php"/>

View File

@@ -17,16 +17,14 @@ abstract class GetMetadata
{
/**
* @param string|object $class
* @phpstan-param class-string|object $class
* @psalm-param class-string|object $class
*/
abstract public function getEntityManager($class): EntityManagerInterface;
/**
* @psalm-param class-string<TObject> $class
* @phpstan-param class-string $class
*
* @psalm-return ClassMetadata<TObject>
* @phpstan-return ClassMetadata<object>
*
* @psalm-template TObject of object
*/

View File

@@ -0,0 +1,217 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\ManyToMany;
use Doctrine\Tests\OrmFunctionalTestCase;
/**
* @group GH-9109
*/
class GH9109Test extends OrmFunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();
$this->_schemaTool->createSchema(
[
$this->_em->getClassMetadata(GH9109User::class),
$this->_em->getClassMetadata(GH9109Product::class),
]
);
}
protected function tearDown(): void
{
$this->_schemaTool->dropSchema(
[
$this->_em->getClassMetadata(GH9109User::class),
$this->_em->getClassMetadata(GH9109Product::class),
]
);
parent::tearDown();
}
public function testIssue(): void
{
$userFirstName = 'GH9109Test';
$userLastName = 'UserGH9109';
$productTitle = 'Test product';
$userRepository = $this->_em->getRepository(GH9109User::class);
$user = new GH9109User();
$user->setFirstName($userFirstName);
$user->setLastName($userLastName);
$product = new GH9109Product();
$product->setTitle($productTitle);
$this->_em->persist($user);
$this->_em->persist($product);
$this->_em->flush();
$product->addBuyer($user);
$this->_em->persist($product);
$this->_em->flush();
$this->_em->clear();
$persistedProduct = $this->_em->find(GH9109Product::class, $product->getId());
// assert Product was persisted
self::assertInstanceOf(GH9109Product::class, $persistedProduct);
self::assertEquals($productTitle, $persistedProduct->getTitle());
// assert Product has a Buyer
$count = $persistedProduct->getBuyers()->count();
self::assertEquals(1, $count);
// assert NOT QUOTED will WORK with findOneBy
$user = $userRepository->findOneBy(['lastName' => $userLastName]);
self::assertInstanceOf(GH9109User::class, $user);
self::assertEquals($userLastName, $user->getLastName());
// assert NOT QUOTED will WORK with Criteria
$criteria = Criteria::create();
$criteria->where($criteria->expr()->eq('lastName', $userLastName));
$user = $persistedProduct->getBuyers()->matching($criteria)->first();
self::assertInstanceOf(GH9109User::class, $user);
self::assertEquals($userLastName, $user->getLastName());
// assert QUOTED will WORK with findOneBy
$user = $userRepository->findOneBy(['firstName' => $userFirstName]);
self::assertInstanceOf(GH9109User::class, $user);
self::assertEquals($userFirstName, $user->getFirstName());
// assert QUOTED will WORK with Criteria
$criteria = Criteria::create();
$criteria->where($criteria->expr()->eq('firstName', $userFirstName));
$user = $persistedProduct->getBuyers()->matching($criteria)->first();
self::assertInstanceOf(GH9109User::class, $user);
self::assertEquals($userFirstName, $user->getFirstName());
}
}
/**
* @Entity
*/
class GH9109Product
{
/**
* @var int $id
* @Column(name="`id`", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string $title
* @Column(name="`title`", type="string", length=255)
*/
private $title;
/**
* @var Collection|GH9109User[]
* @psalm-var Collection<int, GH9109User>
* @ManyToMany(targetEntity="GH9109User")
*/
private $buyers;
public function __construct()
{
$this->buyers = new ArrayCollection();
}
public function getId(): int
{
return $this->id;
}
public function setTitle(string $title): void
{
$this->title = $title;
}
public function getTitle(): string
{
return $this->title;
}
/**
* @psalm-return Collection<int, GH9109User>
*/
public function getBuyers(): Collection
{
return $this->buyers;
}
public function addBuyer(GH9109User $buyer): void
{
$this->buyers[] = $buyer;
}
}
/**
* @Entity
*/
class GH9109User
{
/**
* @var int
* @Column(name="`id`", type="integer")
* @Id
* @GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
* @Column(name="`first_name`", type="string")
*/
private $firstName;
/**
* @var string
* @Column(name="last_name", type="string")
*/
private $lastName;
public function getId(): int
{
return $this->id;
}
public function getFirstName(): string
{
return $this->firstName;
}
public function setFirstName(string $firstName): void
{
$this->firstName = $firstName;
}
public function getLastName(): string
{
return $this->lastName;
}
public function setLastName(string $lastName): void
{
$this->lastName = $lastName;
}
}

View File

@@ -1119,6 +1119,13 @@ abstract class AbstractMappingDriverTest extends OrmTestCase
$class = $this->createClassMetadata(SingleTableEntityIncompleteDiscriminatorColumnMapping::class);
self::assertEquals('dtype', $class->discriminatorColumn['name']);
}
public function testReservedWordInTableColumn(): void
{
$metadata = $this->createClassMetadata(ReservedWordInTableColumn::class);
self::assertSame('count', $metadata->getFieldMapping('count')['columnName']);
}
}
/**
@@ -1774,3 +1781,42 @@ class SingleTableEntityIncompleteDiscriminatorColumnMappingSub1 extends SingleTa
class SingleTableEntityIncompleteDiscriminatorColumnMappingSub2 extends SingleTableEntityIncompleteDiscriminatorColumnMapping
{
}
/** @Entity */
#[ORM\Entity]
class ReservedWordInTableColumn
{
/**
* @var int
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="NONE")
*/
#[ORM\Id, ORM\Column(type: 'integer'), ORM\GeneratedValue(strategy: 'NONE')]
public $id;
/**
* @var string|null
* @Column(name="`count`", type="integer")
*/
#[ORM\Column(name: '`count`', type: 'integer')]
public $count;
public static function loadMetadata(ClassMetadataInfo $metadata): void
{
$metadata->mapField(
[
'id' => true,
'fieldName' => 'id',
'type' => 'integer',
]
);
$metadata->mapField(
[
'fieldName' => 'count',
'type' => 'integer',
'columnName' => '`count`',
]
);
}
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
$metadata->mapField(
[
'id' => true,
'fieldName' => 'id',
'type' => 'integer',
]
);
$metadata->mapField(
[
'fieldName' => 'count',
'type' => 'integer',
'columnName' => '`count`',
]
);

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\ORM\Mapping\ReservedWordInTableColumn">
<id name="id" type="integer" column="id">
<generator strategy="NONE"/>
</id>
<field name="count" column="`count`" type="integer"/>
</entity>
</doctrine-mapping>

View File

@@ -0,0 +1,10 @@
Doctrine\Tests\ORM\Mapping\ReservedWordInTableColumn:
type: entity
id:
id:
generator:
strategy: NONE
fields:
count:
type: integer
column: '`count`'

View File

@@ -76,7 +76,7 @@ class SelectSqlGenerationTest extends OrmTestCase
parent::assertEquals(
$sqlToBeConfirmed,
$sqlGenerated,
sprintf('"%s" is not equal of "%s"', $sqlGenerated, $sqlToBeConfirmed)
sprintf('"%s" is not equal to "%s"', $sqlGenerated, $sqlToBeConfirmed)
);
$query->free();
@@ -2116,26 +2116,6 @@ class SelectSqlGenerationTest extends OrmTestCase
'SELECT CONCAT(c0_.id, c0_.name, c0_.status) AS sclr_0 FROM cms_users c0_ WHERE c0_.id = ?'
);
$connMock->setDatabasePlatform(new PostgreSQL94Platform());
$this->assertSqlGeneration(
"SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CONCAT(u.name, u.status, 's') = ?1",
"SELECT c0_.id AS id_0 FROM cms_users c0_ WHERE c0_.name || c0_.status || 's' = ?"
);
$this->assertSqlGeneration(
'SELECT CONCAT(u.id, u.name, u.status) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1',
'SELECT c0_.id || c0_.name || c0_.status AS sclr_0 FROM cms_users c0_ WHERE c0_.id = ?'
);
$connMock->setDatabasePlatform(new SQLServer2012Platform());
$this->assertSqlGeneration(
"SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE CONCAT(u.name, u.status, 's') = ?1",
"SELECT c0_.id AS id_0 FROM cms_users c0_ WHERE (c0_.name + c0_.status + 's') = ?"
);
$this->assertSqlGeneration(
'SELECT CONCAT(u.id, u.name, u.status) FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1',
'SELECT (c0_.id + c0_.name + c0_.status) AS sclr_0 FROM cms_users c0_ WHERE c0_.id = ?'
);
$connMock->setDatabasePlatform($orgPlatform);
}