mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 15:02:22 +01:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f1891d3e2 | ||
|
|
c9fc4d90e5 | ||
|
|
17d28b5c4c | ||
|
|
a2d510c6f4 | ||
|
|
0e3cff0c6a | ||
|
|
5c50ed925a | ||
|
|
5a1e560f87 | ||
|
|
78e8887759 | ||
|
|
5eb298b99b | ||
|
|
5eb0255f47 | ||
|
|
28575f58af | ||
|
|
457d2d2841 | ||
|
|
2a4ebca90e | ||
|
|
5d01c66c84 | ||
|
|
a2516b67dc | ||
|
|
3d4e9b3ecf | ||
|
|
d1ee40e7d5 | ||
|
|
65d2720764 | ||
|
|
3e18a58de6 | ||
|
|
a9f9202c00 | ||
|
|
d8cb71fe4a | ||
|
|
d659591b6c | ||
|
|
e2430ac9a7 | ||
|
|
0b373f6c27 | ||
|
|
36b9064dbe | ||
|
|
cc29ae0d36 | ||
|
|
bd4a053d29 | ||
|
|
52fbfb3785 | ||
|
|
c259371e5f | ||
|
|
dcdd58b642 | ||
|
|
7b9c53854f | ||
|
|
cdc5fe11dd | ||
|
|
69ece00564 | ||
|
|
4baa7bd252 | ||
|
|
c55f10e501 | ||
|
|
f3fb79658e | ||
|
|
10a32cb824 | ||
|
|
c679d1b007 | ||
|
|
1e15b22dcb | ||
|
|
d88371331d | ||
|
|
b260ec8a00 | ||
|
|
44057b4683 | ||
|
|
013df03795 | ||
|
|
2d2a34407c | ||
|
|
1072ea6db4 | ||
|
|
baf2c60cc4 | ||
|
|
8e620cad40 | ||
|
|
daf0f82884 | ||
|
|
3303cd3b5d | ||
|
|
afcf91e839 | ||
|
|
c61a9b3b6d | ||
|
|
bd0509a064 | ||
|
|
708bd84fe2 | ||
|
|
3aed6912a3 | ||
|
|
36bef3f959 | ||
|
|
980ccc58dc | ||
|
|
62ca4624a9 | ||
|
|
1aed318b7b | ||
|
|
158605bf24 | ||
|
|
2c2ef65817 | ||
|
|
f8fdeaf41e | ||
|
|
1c33a86983 | ||
|
|
310fe1cccb | ||
|
|
a67f677747 | ||
|
|
c9557c588b | ||
|
|
19912de927 | ||
|
|
737cca5b78 | ||
|
|
aff82af7de | ||
|
|
9e999ea1ff | ||
|
|
6755bb0c7b | ||
|
|
aa141bf001 | ||
|
|
cf39e00553 | ||
|
|
27b47841be | ||
|
|
c2a49327a7 | ||
|
|
9bd7242376 | ||
|
|
fff085b63f | ||
|
|
5ad5b11ae1 | ||
|
|
c12fd2cb94 | ||
|
|
44d5d4a779 | ||
|
|
5a599233c9 | ||
|
|
596da353c2 | ||
|
|
68c87740aa | ||
|
|
55dc02c39f | ||
|
|
4feaa470af | ||
|
|
14866461c5 |
2
.github/workflows/coding-standards.yml
vendored
2
.github/workflows/coding-standards.yml
vendored
@@ -24,4 +24,4 @@ on:
|
||||
|
||||
jobs:
|
||||
coding-standards:
|
||||
uses: "doctrine/.github/.github/workflows/coding-standards.yml@7.1.0"
|
||||
uses: "doctrine/.github/.github/workflows/coding-standards.yml@7.2.2"
|
||||
|
||||
2
.github/workflows/continuous-integration.yml
vendored
2
.github/workflows/continuous-integration.yml
vendored
@@ -9,7 +9,6 @@ on:
|
||||
- ci/**
|
||||
- composer.*
|
||||
- src/**
|
||||
- phpunit.xml.dist
|
||||
- tests/**
|
||||
push:
|
||||
branches:
|
||||
@@ -19,7 +18,6 @@ on:
|
||||
- ci/**
|
||||
- composer.*
|
||||
- src/**
|
||||
- phpunit.xml.dist
|
||||
- tests/**
|
||||
|
||||
env:
|
||||
|
||||
2
.github/workflows/documentation.yml
vendored
2
.github/workflows/documentation.yml
vendored
@@ -17,4 +17,4 @@ on:
|
||||
jobs:
|
||||
documentation:
|
||||
name: "Documentation"
|
||||
uses: "doctrine/.github/.github/workflows/documentation.yml@7.1.0"
|
||||
uses: "doctrine/.github/.github/workflows/documentation.yml@7.2.2"
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@7.1.0"
|
||||
uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@7.2.2"
|
||||
secrets:
|
||||
GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||
GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}
|
||||
|
||||
30
UPGRADE.md
30
UPGRADE.md
@@ -124,6 +124,36 @@ WARNING: This was relaxed in ORM 3.2 when partial was re-allowed for array-hydra
|
||||
`Doctrine\ORM\Query::HINT_FORCE_PARTIAL_LOAD` are removed.
|
||||
- `Doctrine\ORM\EntityManager*::getPartialReference()` is removed.
|
||||
|
||||
## BC BREAK: Enforce ArrayCollection Type on `\Doctrine\ORM\QueryBuilder::setParameters(ArrayCollection $parameters)`
|
||||
|
||||
The argument $parameters can no longer be a key=>value array. Only ArrayCollection types are allowed.
|
||||
|
||||
### Before
|
||||
|
||||
```php
|
||||
$qb = $em->createQueryBuilder()
|
||||
->select('u')
|
||||
->from('User', 'u')
|
||||
->where('u.id = :user_id1 OR u.id = :user_id2')
|
||||
->setParameters(array(
|
||||
'user_id1' => 1,
|
||||
'user_id2' => 2
|
||||
));
|
||||
```
|
||||
|
||||
### After
|
||||
|
||||
```php
|
||||
$qb = $em->createQueryBuilder()
|
||||
->select('u')
|
||||
->from('User', 'u')
|
||||
->where('u.id = :user_id1 OR u.id = :user_id2')
|
||||
->setParameters(new ArrayCollection(array(
|
||||
new Parameter('user_id1', 1),
|
||||
new Parameter('user_id2', 2)
|
||||
)));
|
||||
```
|
||||
|
||||
## BC BREAK: `Doctrine\ORM\Persister\Entity\EntityPersister::executeInserts()` return type changed to `void`
|
||||
|
||||
Implementors should adapt to the new signature, and should call
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
displayDetailsOnTestsThatTriggerNotices="true"
|
||||
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
failOnRisky="true"
|
||||
cacheDirectory=".phpunit.cache"
|
||||
>
|
||||
@@ -19,6 +24,7 @@
|
||||
|
||||
<!-- necessary change for some CLI/console output test assertions -->
|
||||
<env name="COLUMNS" value="120"/>
|
||||
<env name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
@@ -27,7 +33,7 @@
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<source>
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory suffix=".php">../../../src</directory>
|
||||
</include>
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
displayDetailsOnTestsThatTriggerNotices="true"
|
||||
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
failOnRisky="true"
|
||||
cacheDirectory=".phpunit.cache"
|
||||
>
|
||||
@@ -19,6 +24,7 @@
|
||||
|
||||
<!-- necessary change for some CLI/console output test assertions -->
|
||||
<env name="COLUMNS" value="120"/>
|
||||
<env name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
@@ -27,7 +33,7 @@
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<source>
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory suffix=".php">../../../src</directory>
|
||||
</include>
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
displayDetailsOnTestsThatTriggerNotices="true"
|
||||
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
failOnRisky="true"
|
||||
cacheDirectory=".phpunit.cache"
|
||||
>
|
||||
@@ -16,6 +21,7 @@
|
||||
|
||||
<!-- necessary change for some CLI/console output test assertions -->
|
||||
<env name="COLUMNS" value="120"/>
|
||||
<env name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
@@ -24,7 +30,7 @@
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<source>
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory suffix=".php">../../../src</directory>
|
||||
</include>
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
displayDetailsOnTestsThatTriggerNotices="true"
|
||||
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
failOnRisky="true"
|
||||
cacheDirectory=".phpunit.cache"
|
||||
>
|
||||
@@ -14,6 +19,7 @@
|
||||
|
||||
<!-- necessary change for some CLI/console output test assertions -->
|
||||
<env name="COLUMNS" value="120"/>
|
||||
<env name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
@@ -22,7 +28,7 @@
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<source>
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory suffix=".php">../../../src</directory>
|
||||
</include>
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
displayDetailsOnTestsThatTriggerNotices="true"
|
||||
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
failOnRisky="true"
|
||||
cacheDirectory=".phpunit.cache"
|
||||
>
|
||||
@@ -16,6 +21,7 @@
|
||||
|
||||
<!-- necessary change for some CLI/console output test assertions -->
|
||||
<env name="COLUMNS" value="120"/>
|
||||
<env name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
@@ -24,7 +30,7 @@
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<source>
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory suffix=".php">../../../src</directory>
|
||||
</include>
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
displayDetailsOnTestsThatTriggerNotices="true"
|
||||
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
failOnRisky="true"
|
||||
cacheDirectory=".phpunit.cache"
|
||||
>
|
||||
@@ -14,6 +19,7 @@
|
||||
|
||||
<!-- necessary change for some CLI/console output test assertions -->
|
||||
<env name="COLUMNS" value="120"/>
|
||||
<env name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
@@ -22,7 +28,7 @@
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<source>
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory suffix=".php">../../../src</directory>
|
||||
</include>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"symfony/var-exporter": "^6.3.9 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^12.0",
|
||||
"doctrine/coding-standard": "^13.0",
|
||||
"phpbench/phpbench": "^1.0",
|
||||
"phpdocumentor/guides-cli": "^1.4",
|
||||
"phpstan/extension-installer": "^1.4",
|
||||
@@ -45,7 +45,7 @@
|
||||
"phpstan/phpstan-deprecation-rules": "^2",
|
||||
"phpunit/phpunit": "^10.4.0",
|
||||
"psr/log": "^1 || ^2 || ^3",
|
||||
"squizlabs/php_codesniffer": "3.7.2",
|
||||
"squizlabs/php_codesniffer": "3.12.0",
|
||||
"symfony/cache": "^5.4 || ^6.2 || ^7.0"
|
||||
},
|
||||
"suggest": {
|
||||
|
||||
@@ -71,8 +71,8 @@ Configuration Options
|
||||
The following sections describe all the configuration options
|
||||
available on a ``Doctrine\ORM\Configuration`` instance.
|
||||
|
||||
Proxy Directory (***REQUIRED***)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Proxy Directory (**REQUIRED**)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -85,8 +85,8 @@ classes. For a detailed explanation on proxy classes and how they
|
||||
are used in Doctrine, refer to the "Proxy Objects" section further
|
||||
down.
|
||||
|
||||
Proxy Namespace (***REQUIRED***)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Proxy Namespace (**REQUIRED**)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -98,8 +98,8 @@ Gets or sets the namespace to use for generated proxy classes. For
|
||||
a detailed explanation on proxy classes and how they are used in
|
||||
Doctrine, refer to the "Proxy Objects" section further down.
|
||||
|
||||
Metadata Driver (***REQUIRED***)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Metadata Driver (**REQUIRED**)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -139,8 +139,8 @@ accept either a single directory as a string or an array of
|
||||
directories. With this feature a single driver can support multiple
|
||||
directories of Entities.
|
||||
|
||||
Metadata Cache (***RECOMMENDED***)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Metadata Cache (**RECOMMENDED**)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -161,8 +161,8 @@ For development you should use an array cache like
|
||||
``Symfony\Component\Cache\Adapter\ArrayAdapter``
|
||||
which only caches data on a per-request basis.
|
||||
|
||||
Query Cache (***RECOMMENDED***)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Query Cache (**RECOMMENDED**)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -184,8 +184,8 @@ For development you should use an array cache like
|
||||
``Symfony\Component\Cache\Adapter\ArrayAdapter``
|
||||
which only caches data on a per-request basis.
|
||||
|
||||
SQL Logger (***Optional***)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
SQL Logger (**Optional**)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
@@ -197,8 +197,8 @@ Gets or sets the logger to use for logging all SQL statements
|
||||
executed by Doctrine. The logger class must implement the
|
||||
deprecated ``Doctrine\DBAL\Logging\SQLLogger`` interface.
|
||||
|
||||
Auto-generating Proxy Classes (***OPTIONAL***)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Auto-generating Proxy Classes (**OPTIONAL**)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Proxy classes can either be generated manually through the Doctrine
|
||||
Console or automatically at runtime by Doctrine. The configuration
|
||||
@@ -441,7 +441,7 @@ correctly if sub-namespaces use different metadata driver
|
||||
implementations.
|
||||
|
||||
|
||||
Default Repository (***OPTIONAL***)
|
||||
Default Repository (**OPTIONAL**)
|
||||
-----------------------------------
|
||||
|
||||
Specifies the FQCN of a subclass of the EntityRepository.
|
||||
@@ -456,7 +456,7 @@ That will be available for all entities without a custom repository class.
|
||||
The default value is ``Doctrine\ORM\EntityRepository``.
|
||||
Any repository class must be a subclass of EntityRepository otherwise you got an ORMException
|
||||
|
||||
Ignoring entities (***OPTIONAL***)
|
||||
Ignoring entities (**OPTIONAL**)
|
||||
-----------------------------------
|
||||
|
||||
Specifies the Entity FQCNs to ignore.
|
||||
|
||||
@@ -903,8 +903,7 @@ defaults to "id", just as in one-to-one or many-to-one mappings.
|
||||
|
||||
Additionally, when using typed properties with Doctrine 2.9 or newer
|
||||
you can skip ``targetEntity`` in ``ManyToOne`` and ``OneToOne``
|
||||
associations as they will be set based on type. Also ``nullable``
|
||||
attribute on ``JoinColumn`` will be inherited from PHP type. So that:
|
||||
associations as they will be set based on type. So that:
|
||||
|
||||
.. configuration-block::
|
||||
|
||||
@@ -931,7 +930,7 @@ Is essentially the same as following:
|
||||
<?php
|
||||
/** One Product has One Shipment. */
|
||||
#[OneToOne(targetEntity: Shipment::class)]
|
||||
#[JoinColumn(name: 'shipment_id', referencedColumnName: 'id', nullable: false)]
|
||||
#[JoinColumn(name: 'shipment_id', referencedColumnName: 'id')]
|
||||
private Shipment $shipment;
|
||||
|
||||
.. code-block:: annotation
|
||||
@@ -940,7 +939,7 @@ Is essentially the same as following:
|
||||
/**
|
||||
* One Product has One Shipment.
|
||||
* @OneToOne(targetEntity="Shipment")
|
||||
* @JoinColumn(name="shipment_id", referencedColumnName="id", nullable=false)
|
||||
* @JoinColumn(name="shipment_id", referencedColumnName="id")
|
||||
*/
|
||||
private Shipment $shipment;
|
||||
|
||||
@@ -949,7 +948,7 @@ Is essentially the same as following:
|
||||
<doctrine-mapping>
|
||||
<entity class="Product">
|
||||
<one-to-one field="shipment" target-entity="Shipment">
|
||||
<join-column name="shipment_id" referenced-column-name="id" nulable=false />
|
||||
<join-column name="shipment_id" referenced-column-name="id" nullable=false />
|
||||
</one-to-one>
|
||||
</entity>
|
||||
</doctrine-mapping>
|
||||
|
||||
@@ -265,7 +265,7 @@ specific to a particular entity class's lifecycle.
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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="User">
|
||||
|
||||
@@ -16,7 +16,7 @@ is common to multiple entity classes.
|
||||
Mapped superclasses, just as regular, non-mapped classes, can
|
||||
appear in the middle of an otherwise mapped inheritance hierarchy
|
||||
(through Single Table Inheritance or Class Table Inheritance). They
|
||||
are not query-able, and need not have an ``#[Id]`` property.
|
||||
are not query-able, and do not require an ``#[Id]`` property.
|
||||
|
||||
No database table will be created for a mapped superclass itself,
|
||||
only for entity classes inheriting from it. That implies that a
|
||||
|
||||
@@ -299,7 +299,7 @@ level cache region.
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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="Country">
|
||||
@@ -351,7 +351,7 @@ It caches the primary keys of association and cache each element will be cached
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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="State">
|
||||
|
||||
@@ -736,6 +736,35 @@ methods:
|
||||
|
||||
.. note::
|
||||
|
||||
There is a limitation on the compatibility of Criteria comparisons.
|
||||
You have to use scalar values only as the value in a comparison or
|
||||
the behaviour between different backends is not the same.
|
||||
Depending on whether the collection has already been loaded from the
|
||||
database or not, criteria matching may happen at the database/SQL level
|
||||
or on objects in memory. This may lead to different results and come
|
||||
surprising, for example when a code change in one place leads to a collection
|
||||
becoming initialized and, as a side effect, returning a different result
|
||||
or even breaking a ``matching()`` call somewhere else. Also, collection
|
||||
initialization state in practical use cases may differ from the one covered
|
||||
in unit tests.
|
||||
|
||||
Database level comparisons are based on scalar representations of the values
|
||||
stored in entity properties. The field names passed to expressions correspond
|
||||
to property names. Comparison and sorting may be affected by
|
||||
database-specific behavior. For example, MySQL enum types sort by index position,
|
||||
not lexicographically by value.
|
||||
|
||||
In-memory handling is based on the ``Selectable`` API of `Doctrine Collections <https://www.doctrine-project.org/projects/doctrine-collections/en/stable/index.html#matching>`.
|
||||
In this case, field names passed to expressions are being used to derive accessor
|
||||
method names. Strict type comparisons are used for equal and not-equal checks,
|
||||
and generally PHP language rules are being used for other comparison operators
|
||||
or sorting.
|
||||
|
||||
As a general guidance, for consistent results use the Criteria API with scalar
|
||||
values only. Note that ``DateTime`` and ``DateTimeImmutable`` are two predominant
|
||||
examples of value objects that are *not* scalars.
|
||||
|
||||
Refrain from using special database-level column types or custom Doctrine Types
|
||||
that may lead to database-specific comparison or sorting rules being applied, or
|
||||
to database-level values being different from object field values.
|
||||
|
||||
Provide accessor methods for all entity fields used in criteria expressions,
|
||||
and implement those methods in a way that their return value is the
|
||||
same as the database-level value.
|
||||
|
||||
@@ -166,7 +166,7 @@ your code. See the following code:
|
||||
|
||||
Traversing the object graph for parts that are lazy-loaded will
|
||||
easily trigger lots of SQL queries and will perform badly if used
|
||||
to heavily. Make sure to use DQL to fetch-join all the parts of the
|
||||
too heavily. Make sure to use DQL to fetch-join all the parts of the
|
||||
object-graph that you need as efficiently as possible.
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ setup for the latest code in trunk.
|
||||
.. code-block:: xml
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
@@ -46,7 +46,7 @@ In order to work, this requires certain conventions:
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$driver->setFileExtension('.xml');
|
||||
$driver->getLocator()->setFileExtension('.xml');
|
||||
|
||||
It is recommended to put all XML mapping documents in a single
|
||||
folder but you can spread the documents over several folders if you
|
||||
@@ -104,7 +104,7 @@ of several common elements:
|
||||
// Doctrine.Tests.ORM.Mapping.User.dcm.xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
@@ -770,7 +770,7 @@ entity relationship. You can define this in XML with the "association-key" attri
|
||||
.. code-block:: xml
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ and year of production as primary keys:
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
@@ -85,11 +85,12 @@ And for querying you can use arrays to both DQL and EntityRepositories:
|
||||
namespace VehicleCatalogue\Model;
|
||||
|
||||
// $em is the EntityManager
|
||||
$audi = $em->find("VehicleCatalogue\Model\Car", array("name" => "Audi A8", "year" => 2010));
|
||||
$audi = $em->find("VehicleCatalogue\Model\Car", ["name" => "Audi A8", "year" => 2010]);
|
||||
|
||||
$dql = "SELECT c FROM VehicleCatalogue\Model\Car c WHERE c.id = ?1";
|
||||
$dql = "SELECT c FROM VehicleCatalogue\Model\Car c WHERE c.name = ?1 AND c.year = ?2";
|
||||
$audi = $em->createQuery($dql)
|
||||
->setParameter(1, ["name" => "Audi A8", "year" => 2010])
|
||||
->setParameter(1, "Audi A8")
|
||||
->setParameter(2, 2010)
|
||||
->getSingleResult();
|
||||
|
||||
You can also use this entity in associations. Doctrine will then generate two foreign keys one for ``name``
|
||||
@@ -174,7 +175,7 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
|
||||
.. code-block:: xml
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
@@ -249,7 +250,7 @@ of products purchased and maybe even the current price.
|
||||
|
||||
public function __construct(
|
||||
#[ManyToOne(targetEntity: Customer::class)]
|
||||
private Customer $customer,
|
||||
private Customer $customer
|
||||
) {
|
||||
$this->items = new ArrayCollection();
|
||||
$this->created = new DateTime("now");
|
||||
@@ -294,6 +295,7 @@ of products purchased and maybe even the current price.
|
||||
$this->order = $order;
|
||||
$this->product = $product;
|
||||
$this->offeredPrice = $product->getCurrentPrice();
|
||||
$this->amount = $amount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ switch to extra lazy as shown in these examples:
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
|
||||
@@ -514,7 +514,7 @@ methods, but you only need to choose one.
|
||||
|
||||
<!-- config/xml/Product.dcm.xml -->
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
@@ -1023,7 +1023,7 @@ the ``Product`` before:
|
||||
|
||||
<!-- config/xml/Bug.dcm.xml -->
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
@@ -1103,7 +1103,7 @@ Finally, we'll add metadata mappings for the ``User`` entity.
|
||||
|
||||
<!-- config/xml/User.dcm.xml -->
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
@@ -1586,7 +1586,7 @@ we have to adjust the metadata slightly.
|
||||
.. code-block:: xml
|
||||
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ here are the code and mappings for it:
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
|
||||
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
|
||||
@@ -1350,12 +1350,72 @@ parameters:
|
||||
count: 1
|
||||
path: src/Mapping/Driver/AttributeDriver.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencedColumnNames\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencedTableName\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencingColumnNames\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\Index\:\:getIndexedColumns\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\Table\:\:getPrimaryKeyConstraint\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Call to method getColumnName\(\) on an unknown class Doctrine\\DBAL\\Schema\\Index\\IndexedColumn\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Call to method getColumnNames\(\) on an unknown class Doctrine\\DBAL\\Schema\\PrimaryKeyConstraint\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Call to method toString\(\) on an unknown class Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\.$#'
|
||||
identifier: class.notFound
|
||||
count: 5
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Cannot call method getName\(\) on Doctrine\\DBAL\\Schema\\Column\|false\.$#'
|
||||
identifier: method.nonObject
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Class Doctrine\\DBAL\\Schema\\Index\\IndexType not found\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Class Doctrine\\DBAL\\Schema\\PrimaryKeyConstraint not found\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Instanceof between Doctrine\\ORM\\Mapping\\ClassMetadata\<T of object\> and Doctrine\\ORM\\Mapping\\ClassMetadata will always evaluate to true\.$#'
|
||||
identifier: instanceof.alwaysTrue
|
||||
@@ -1392,12 +1452,30 @@ parameters:
|
||||
count: 2
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#1 \$array of function sort contains unresolvable type\.$#'
|
||||
identifier: argument.unresolvableType
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#2 \$columnName of method Doctrine\\ORM\\Mapping\\Driver\\DatabaseDriver\:\:getFieldNameForColumn\(\) expects string, string\|false given\.$#'
|
||||
identifier: argument.type
|
||||
count: 4
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \$indexedColumn of anonymous function has invalid type Doctrine\\DBAL\\Schema\\Index\\IndexedColumn\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \$name of anonymous function has invalid type Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\.$#'
|
||||
identifier: class.notFound
|
||||
count: 5
|
||||
path: src/Mapping/Driver/DatabaseDriver.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Mapping\\Driver\\SimplifiedXmlDriver\:\:__construct\(\) has parameter \$fileExtension with no type specified\.$#'
|
||||
identifier: missingType.parameter
|
||||
@@ -3048,12 +3126,72 @@ parameters:
|
||||
count: 3
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencedColumnNames\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencedTableName\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint\:\:getReferencingColumnNames\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\Index\:\:getIndexedColumns\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Doctrine\\DBAL\\Schema\\Table\:\:dropForeignKey\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to function is_numeric\(\) with int\<0, max\> will always evaluate to true\.$#'
|
||||
identifier: function.alreadyNarrowedType
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to method getColumnName\(\) on an unknown class Doctrine\\DBAL\\Schema\\Index\\IndexedColumn\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to method getColumnNames\(\) on an unknown class Doctrine\\DBAL\\Schema\\PrimaryKeyConstraint\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Call to method toString\(\) on an unknown class Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\.$#'
|
||||
identifier: class.notFound
|
||||
count: 3
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Class Doctrine\\DBAL\\Schema\\PrimaryKeyConstraint not found\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\DBAL\\Schema\\AbstractSchemaManager\<Doctrine\\DBAL\\Platforms\\AbstractPlatform\>\:\:createComparator\(\) invoked with 1 parameter, 0 required\.$#'
|
||||
identifier: arguments.count
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Method Doctrine\\ORM\\Tools\\SchemaTool\:\:addDiscriminatorColumnDefinition\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
|
||||
identifier: missingType.generics
|
||||
@@ -3156,6 +3294,18 @@ parameters:
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \$indexedColumn of anonymous function has invalid type Doctrine\\DBAL\\Schema\\Index\\IndexedColumn\.$#'
|
||||
identifier: class.notFound
|
||||
count: 1
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \$name of anonymous function has invalid type Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\.$#'
|
||||
identifier: class.notFound
|
||||
count: 3
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '#^Property Doctrine\\ORM\\Tools\\SchemaTool\:\:\$schemaManager with generic class Doctrine\\DBAL\\Schema\\AbstractSchemaManager does not specify its types\: T$#'
|
||||
identifier: missingType.generics
|
||||
|
||||
@@ -22,6 +22,18 @@ parameters:
|
||||
message: '~.*getTrimExpression.*expects int.*~'
|
||||
path: src/Query/AST/Functions/TrimFunction.php
|
||||
|
||||
-
|
||||
message: '~^Call to static method unquoted\(\) on an unknown class Doctrine\\DBAL\\Schema\\Name\\Identifier\.$~'
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '~^Instantiated class Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName not found\.$~'
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '~^Call to an undefined method Doctrine\\DBAL\\Schema\\Table::addPrimaryKeyConstraint\(\)\.$~'
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
- '~^Class Doctrine\\DBAL\\Platforms\\SQLitePlatform not found\.$~'
|
||||
|
||||
# To be removed in 4.0
|
||||
|
||||
12
phpstan.neon
12
phpstan.neon
@@ -20,6 +20,18 @@ parameters:
|
||||
message: '~^Method Doctrine\\ORM\\Persisters\\Entity\\BasicEntityPersister\:\:getArrayBindingType\(\) never returns .* so it can be removed from the return type\.$~'
|
||||
path: src/Persisters/Entity/BasicEntityPersister.php
|
||||
|
||||
-
|
||||
message: '~^Call to static method unquoted\(\) on an unknown class Doctrine\\DBAL\\Schema\\Name\\Identifier\.$~'
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '~^Instantiated class Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName not found\.$~'
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
-
|
||||
message: '~^Call to an undefined method Doctrine\\DBAL\\Schema\\Table::addPrimaryKeyConstraint\(\)\.$~'
|
||||
path: src/Tools/SchemaTool.php
|
||||
|
||||
# Compatibility with DBAL 3
|
||||
# See https://github.com/doctrine/dbal/pull/3480
|
||||
-
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
displayDetailsOnTestsThatTriggerNotices="true"
|
||||
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||
failOnNotice="true"
|
||||
@@ -67,5 +69,12 @@
|
||||
<var name="privileged_db_port" value="3306"/>
|
||||
-->
|
||||
<env name="COLUMNS" value="120"/>
|
||||
<env name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
|
||||
@@ -286,7 +286,7 @@ abstract class AbstractQuery
|
||||
$key = Parameter::normalizeName($key);
|
||||
|
||||
$filteredParameters = $this->parameters->filter(
|
||||
static fn (Parameter $parameter): bool => $parameter->getName() === $key
|
||||
static fn (Parameter $parameter): bool => $parameter->getName() === $key,
|
||||
);
|
||||
|
||||
return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null;
|
||||
|
||||
@@ -29,11 +29,14 @@ class CollectionCacheKey extends CacheKey
|
||||
public readonly string $entityClass,
|
||||
public readonly string $association,
|
||||
array $ownerIdentifier,
|
||||
string $filterHash = '',
|
||||
) {
|
||||
ksort($ownerIdentifier);
|
||||
|
||||
$this->ownerIdentifier = $ownerIdentifier;
|
||||
|
||||
parent::__construct(str_replace('\\', '.', strtolower($entityClass)) . '_' . implode(' ', $ownerIdentifier) . '__' . $association);
|
||||
$filterHash = $filterHash === '' ? '' : '_' . $filterHash;
|
||||
|
||||
parent::__construct(str_replace('\\', '.', strtolower($entityClass)) . '_' . implode(' ', $ownerIdentifier) . '__' . $association . $filterHash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Persisters\Collection\CollectionPersister;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\Query\FilterCollection;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
use function array_values;
|
||||
@@ -35,6 +36,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
|
||||
protected array $queuedCache = [];
|
||||
|
||||
protected string $regionName;
|
||||
protected FilterCollection $filters;
|
||||
protected CollectionHydrator $hydrator;
|
||||
protected CacheLogger|null $cacheLogger;
|
||||
|
||||
@@ -48,6 +50,10 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
|
||||
$cacheConfig = $configuration->getSecondLevelCacheConfiguration();
|
||||
$cacheFactory = $cacheConfig->getCacheFactory();
|
||||
|
||||
$this->region = $region;
|
||||
$this->persister = $persister;
|
||||
$this->association = $association;
|
||||
$this->filters = $em->getFilters();
|
||||
$this->regionName = $region->getName();
|
||||
$this->uow = $em->getUnitOfWork();
|
||||
$this->metadataFactory = $em->getMetadataFactory();
|
||||
@@ -135,7 +141,7 @@ abstract class AbstractCollectionPersister implements CachedCollectionPersister
|
||||
public function count(PersistentCollection $collection): int
|
||||
{
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId);
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
$entry = $this->region->get($key);
|
||||
|
||||
if ($entry !== null) {
|
||||
|
||||
@@ -36,7 +36,7 @@ class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPers
|
||||
public function delete(PersistentCollection $collection): void
|
||||
{
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId);
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
|
||||
$this->persister->delete($collection);
|
||||
|
||||
@@ -53,7 +53,7 @@ class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPers
|
||||
}
|
||||
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId);
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
|
||||
// Invalidate non initialized collections OR ordered collection
|
||||
if ($isDirty && ! $isInitialized || $this->association->isOrdered()) {
|
||||
|
||||
@@ -61,7 +61,7 @@ class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister
|
||||
public function delete(PersistentCollection $collection): void
|
||||
{
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId);
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
$lock = $this->region->lock($key);
|
||||
|
||||
$this->persister->delete($collection);
|
||||
@@ -88,7 +88,7 @@ class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister
|
||||
$this->persister->update($collection);
|
||||
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId);
|
||||
$key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association->fieldName, $ownerId, $this->filters->getHash());
|
||||
$lock = $this->region->lock($key);
|
||||
|
||||
if ($lock === null) {
|
||||
|
||||
@@ -24,10 +24,12 @@ use Doctrine\ORM\Mapping\ClassMetadataFactory;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use Doctrine\ORM\Persisters\Entity\EntityPersister;
|
||||
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
|
||||
use Doctrine\ORM\Query\FilterCollection;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
|
||||
use function array_merge;
|
||||
use function func_get_args;
|
||||
use function serialize;
|
||||
use function sha1;
|
||||
|
||||
@@ -43,6 +45,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
||||
protected TimestampCacheKey $timestampKey;
|
||||
protected EntityHydrator $hydrator;
|
||||
protected Cache $cache;
|
||||
protected FilterCollection $filters;
|
||||
protected CacheLogger|null $cacheLogger = null;
|
||||
protected string $regionName;
|
||||
|
||||
@@ -64,6 +67,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
||||
$cacheFactory = $cacheConfig->getCacheFactory();
|
||||
|
||||
$this->cache = $em->getCache();
|
||||
$this->filters = $em->getFilters();
|
||||
$this->regionName = $region->getName();
|
||||
$this->uow = $em->getUnitOfWork();
|
||||
$this->metadataFactory = $em->getMetadataFactory();
|
||||
@@ -215,7 +219,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
||||
? $this->persister->expandCriteriaParameters($criteria)
|
||||
: $this->persister->expandParameters($criteria);
|
||||
|
||||
return sha1($query . serialize($params) . serialize($orderBy) . $limit . $offset);
|
||||
return sha1($query . serialize($params) . serialize($orderBy) . $limit . $offset . $this->filters->getHash());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -472,7 +476,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
||||
}
|
||||
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = $this->buildCollectionCacheKey($assoc, $ownerId);
|
||||
$key = $this->buildCollectionCacheKey($assoc, $ownerId, $this->filters->getHash());
|
||||
$list = $persister->loadCollectionCache($collection, $key);
|
||||
|
||||
if ($list !== null) {
|
||||
@@ -503,7 +507,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
||||
}
|
||||
|
||||
$ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
|
||||
$key = $this->buildCollectionCacheKey($assoc, $ownerId);
|
||||
$key = $this->buildCollectionCacheKey($assoc, $ownerId, $this->filters->getHash());
|
||||
$list = $persister->loadCollectionCache($collection, $key);
|
||||
|
||||
if ($list !== null) {
|
||||
@@ -546,12 +550,15 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $ownerId */
|
||||
protected function buildCollectionCacheKey(AssociationMapping $association, array $ownerId): CollectionCacheKey
|
||||
protected function buildCollectionCacheKey(AssociationMapping $association, array $ownerId, /* string $filterHash */): CollectionCacheKey
|
||||
{
|
||||
$filterHash = (string) (func_get_args()[2] ?? ''); // todo: move to argument in next major release
|
||||
|
||||
return new CollectionCacheKey(
|
||||
$this->metadataFactory->getMetadataFor($association->sourceEntity)->rootEntityName,
|
||||
$association->fieldName,
|
||||
$ownerId,
|
||||
$filterHash,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,14 @@ use Generator;
|
||||
use LogicException;
|
||||
use ReflectionClass;
|
||||
|
||||
use function array_key_exists;
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function count;
|
||||
use function end;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function ksort;
|
||||
|
||||
/**
|
||||
* Base class for all hydrators. A hydrator is a class that provides some form
|
||||
@@ -263,6 +265,17 @@ abstract class AbstractHydrator
|
||||
{
|
||||
$rowData = ['data' => [], 'newObjects' => []];
|
||||
|
||||
foreach ($this->rsm->newObjectMappings as $mapping) {
|
||||
if (! array_key_exists($mapping['objIndex'], $this->rsm->newObject)) {
|
||||
$this->rsm->newObject[$mapping['objIndex']] = $mapping['className'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->rsm->newObject as $objIndex => $newObject) {
|
||||
$rowData['newObjects'][$objIndex]['class'] = new ReflectionClass($newObject);
|
||||
$rowData['newObjects'][$objIndex]['args'] = [];
|
||||
}
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
$cacheKeyInfo = $this->hydrateColumnInfo($key);
|
||||
if ($cacheKeyInfo === null) {
|
||||
@@ -282,7 +295,6 @@ abstract class AbstractHydrator
|
||||
$value = $this->buildEnum($value, $cacheKeyInfo['enumType']);
|
||||
}
|
||||
|
||||
$rowData['newObjects'][$objIndex]['class'] = $cacheKeyInfo['class'];
|
||||
$rowData['newObjects'][$objIndex]['args'][$argIndex] = $value;
|
||||
break;
|
||||
|
||||
@@ -336,21 +348,17 @@ abstract class AbstractHydrator
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->resultSetMapping()->nestedNewObjectArguments as $objIndex => ['ownerIndex' => $ownerIndex, 'argIndex' => $argIndex]) {
|
||||
if (! isset($rowData['newObjects'][$ownerIndex . ':' . $argIndex])) {
|
||||
continue;
|
||||
foreach ($this->resultSetMapping()->nestedNewObjectArguments as ['ownerIndex' => $ownerIndex, 'argIndex' => $argIndex, 'argAlias' => $argAlias]) {
|
||||
if (array_key_exists($argAlias, $rowData['newObjects'])) {
|
||||
ksort($rowData['newObjects'][$argAlias]['args']);
|
||||
$rowData['newObjects'][$ownerIndex]['args'][$argIndex] = $rowData['newObjects'][$argAlias]['class']->newInstanceArgs($rowData['newObjects'][$argAlias]['args']);
|
||||
unset($rowData['newObjects'][$argAlias]);
|
||||
}
|
||||
|
||||
$newObject = $rowData['newObjects'][$ownerIndex . ':' . $argIndex];
|
||||
unset($rowData['newObjects'][$ownerIndex . ':' . $argIndex]);
|
||||
|
||||
$obj = $newObject['class']->newInstanceArgs($newObject['args']);
|
||||
|
||||
$rowData['newObjects'][$ownerIndex]['args'][$argIndex] = $obj;
|
||||
}
|
||||
|
||||
foreach ($rowData['newObjects'] as $objIndex => $newObject) {
|
||||
$obj = $newObject['class']->newInstanceArgs($newObject['args']);
|
||||
ksort($rowData['newObjects'][$objIndex]['args']);
|
||||
$obj = $rowData['newObjects'][$objIndex]['class']->newInstanceArgs($rowData['newObjects'][$objIndex]['args']);
|
||||
|
||||
$rowData['newObjects'][$objIndex]['obj'] = $obj;
|
||||
}
|
||||
@@ -454,7 +462,6 @@ abstract class AbstractHydrator
|
||||
'type' => Type::getType($this->rsm->typeMappings[$key]),
|
||||
'argIndex' => $mapping['argIndex'],
|
||||
'objIndex' => $mapping['objIndex'],
|
||||
'class' => new ReflectionClass($mapping['className']),
|
||||
'enumType' => $this->rsm->enumMappings[$key] ?? null,
|
||||
];
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ use function array_search;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function key;
|
||||
use function reset;
|
||||
use function sprintf;
|
||||
@@ -138,14 +139,21 @@ class SimpleObjectHydrator extends AbstractHydrator
|
||||
}
|
||||
|
||||
if ($value !== null && isset($cacheKeyInfo['enumType'])) {
|
||||
$originalValue = $value;
|
||||
$originalValue = $currentValue = $value;
|
||||
try {
|
||||
$value = $this->buildEnum($originalValue, $cacheKeyInfo['enumType']);
|
||||
if (! is_array($originalValue)) {
|
||||
$value = $this->buildEnum($originalValue, $cacheKeyInfo['enumType']);
|
||||
} else {
|
||||
$value = [];
|
||||
foreach ($originalValue as $i => $currentValue) {
|
||||
$value[$i] = $this->buildEnum($currentValue, $cacheKeyInfo['enumType']);
|
||||
}
|
||||
}
|
||||
} catch (ValueError $e) {
|
||||
throw MappingException::invalidEnumValue(
|
||||
$entityName,
|
||||
$cacheKeyInfo['fieldName'],
|
||||
(string) $originalValue,
|
||||
(string) $currentValue,
|
||||
$cacheKeyInfo['enumType'],
|
||||
$e,
|
||||
);
|
||||
|
||||
@@ -57,6 +57,8 @@ use function strtolower;
|
||||
use function trait_exists;
|
||||
use function trim;
|
||||
|
||||
use const PHP_VERSION_ID;
|
||||
|
||||
/**
|
||||
* A <tt>ClassMetadata</tt> instance holds all the object-relational mapping metadata
|
||||
* of an entity and its associations.
|
||||
@@ -2673,6 +2675,10 @@ class ClassMetadata implements PersistenceClassMetadata, Stringable
|
||||
}
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID >= 80400 && $reflectionProperty !== null && count($reflectionProperty->getHooks()) > 0) {
|
||||
throw new LogicException('Doctrine ORM does not support property hooks in this version. Check https://github.com/doctrine/orm/issues/11624 for details of versions that support property hooks.');
|
||||
}
|
||||
|
||||
return $reflectionProperty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
|
||||
public function getColumnName(string $fieldName, ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return isset($class->fieldMappings[$fieldName]->quoted)
|
||||
? $platform->quoteIdentifier($class->fieldMappings[$fieldName]->columnName)
|
||||
? $platform->quoteSingleIdentifier($class->fieldMappings[$fieldName]->columnName)
|
||||
: $class->fieldMappings[$fieldName]->columnName;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
|
||||
}
|
||||
|
||||
return isset($class->table['quoted'])
|
||||
? $platform->quoteIdentifier($tableName)
|
||||
? $platform->quoteSingleIdentifier($tableName)
|
||||
: $tableName;
|
||||
}
|
||||
|
||||
@@ -52,14 +52,14 @@ class DefaultQuoteStrategy implements QuoteStrategy
|
||||
public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return isset($definition['quoted'])
|
||||
? $platform->quoteIdentifier($definition['sequenceName'])
|
||||
? $platform->quoteSingleIdentifier($definition['sequenceName'])
|
||||
: $definition['sequenceName'];
|
||||
}
|
||||
|
||||
public function getJoinColumnName(JoinColumnMapping $joinColumn, ClassMetadata $class, AbstractPlatform $platform): string
|
||||
{
|
||||
return isset($joinColumn->quoted)
|
||||
? $platform->quoteIdentifier($joinColumn->name)
|
||||
? $platform->quoteSingleIdentifier($joinColumn->name)
|
||||
: $joinColumn->name;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
|
||||
AbstractPlatform $platform,
|
||||
): string {
|
||||
return isset($joinColumn->quoted)
|
||||
? $platform->quoteIdentifier($joinColumn->referencedColumnName)
|
||||
? $platform->quoteSingleIdentifier($joinColumn->referencedColumnName)
|
||||
: $joinColumn->referencedColumnName;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
|
||||
$tableName = $association->joinTable->name;
|
||||
|
||||
if (isset($association->joinTable->quoted)) {
|
||||
$tableName = $platform->quoteIdentifier($tableName);
|
||||
$tableName = $platform->quoteSingleIdentifier($tableName);
|
||||
}
|
||||
|
||||
return $schema . $tableName;
|
||||
@@ -113,7 +113,7 @@ class DefaultQuoteStrategy implements QuoteStrategy
|
||||
$joinColumns = $assoc->joinColumns;
|
||||
$assocQuotedColumnNames = array_map(
|
||||
static fn (JoinColumnMapping $joinColumn) => isset($joinColumn->quoted)
|
||||
? $platform->quoteIdentifier($joinColumn->name)
|
||||
? $platform->quoteSingleIdentifier($joinColumn->name)
|
||||
: $joinColumn->name,
|
||||
$joinColumns,
|
||||
);
|
||||
|
||||
@@ -6,6 +6,12 @@ namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||
use Doctrine\DBAL\Schema\Column;
|
||||
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\Index;
|
||||
use Doctrine\DBAL\Schema\Index\IndexedColumn;
|
||||
use Doctrine\DBAL\Schema\Index\IndexType;
|
||||
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
|
||||
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\SchemaException;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
@@ -21,12 +27,15 @@ use TypeError;
|
||||
|
||||
use function array_diff;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function current;
|
||||
use function enum_exists;
|
||||
use function get_debug_type;
|
||||
use function in_array;
|
||||
use function method_exists;
|
||||
use function preg_replace;
|
||||
use function sort;
|
||||
use function sprintf;
|
||||
@@ -187,7 +196,7 @@ class DatabaseDriver implements MappingDriver
|
||||
foreach ($this->manyToManyTables as $manyTable) {
|
||||
foreach ($manyTable->getForeignKeys() as $foreignKey) {
|
||||
// foreign key maps to the table of the current entity, many to many association probably exists
|
||||
if (! (strtolower($tableName) === strtolower($foreignKey->getForeignTableName()))) {
|
||||
if (! (strtolower($tableName) === strtolower(self::getReferencedTableName($foreignKey)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -207,22 +216,22 @@ class DatabaseDriver implements MappingDriver
|
||||
continue;
|
||||
}
|
||||
|
||||
$localColumn = current($myFk->getLocalColumns());
|
||||
$localColumn = current(self::getReferencingColumnNames($myFk));
|
||||
|
||||
$associationMapping = [];
|
||||
$associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getLocalColumns()), true);
|
||||
$associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName());
|
||||
$associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current(self::getReferencingColumnNames($otherFk)), true);
|
||||
$associationMapping['targetEntity'] = $this->getClassNameForTable(self::getReferencedTableName($otherFk));
|
||||
|
||||
if (current($manyTable->getColumns())->getName() === $localColumn) {
|
||||
$associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getLocalColumns()), true);
|
||||
$associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current(self::getReferencingColumnNames($myFk)), true);
|
||||
$associationMapping['joinTable'] = [
|
||||
'name' => strtolower($manyTable->getName()),
|
||||
'joinColumns' => [],
|
||||
'inverseJoinColumns' => [],
|
||||
];
|
||||
|
||||
$fkCols = $myFk->getForeignColumns();
|
||||
$cols = $myFk->getLocalColumns();
|
||||
$fkCols = self::getReferencedColumnNames($myFk);
|
||||
$cols = self::getReferencingColumnNames($myFk);
|
||||
|
||||
for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) {
|
||||
$associationMapping['joinTable']['joinColumns'][] = [
|
||||
@@ -231,8 +240,8 @@ class DatabaseDriver implements MappingDriver
|
||||
];
|
||||
}
|
||||
|
||||
$fkCols = $otherFk->getForeignColumns();
|
||||
$cols = $otherFk->getLocalColumns();
|
||||
$fkCols = self::getReferencedColumnNames($otherFk);
|
||||
$cols = self::getReferencingColumnNames($otherFk);
|
||||
|
||||
for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) {
|
||||
$associationMapping['joinTable']['inverseJoinColumns'][] = [
|
||||
@@ -241,7 +250,7 @@ class DatabaseDriver implements MappingDriver
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getLocalColumns()), true);
|
||||
$associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current(self::getReferencingColumnNames($myFk)), true);
|
||||
}
|
||||
|
||||
$metadata->mapManyToMany($associationMapping);
|
||||
@@ -267,10 +276,15 @@ class DatabaseDriver implements MappingDriver
|
||||
$allForeignKeyColumns = [];
|
||||
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
|
||||
$allForeignKeyColumns = array_merge($allForeignKeyColumns, self::getReferencingColumnNames($foreignKey));
|
||||
}
|
||||
|
||||
if (method_exists($table, 'getPrimaryKeyConstraint')) {
|
||||
$primaryKey = $table->getPrimaryKeyConstraint();
|
||||
} else {
|
||||
$primaryKey = $table->getPrimaryKey();
|
||||
}
|
||||
|
||||
$primaryKey = $table->getPrimaryKey();
|
||||
if ($primaryKey === null) {
|
||||
throw new MappingException(
|
||||
'Table ' . $tableName . ' has no primary key. Doctrine does not ' .
|
||||
@@ -278,7 +292,11 @@ class DatabaseDriver implements MappingDriver
|
||||
);
|
||||
}
|
||||
|
||||
$pkColumns = $primaryKey->getColumns();
|
||||
if ($primaryKey instanceof PrimaryKeyConstraint) {
|
||||
$pkColumns = array_map(static fn (UnqualifiedName $name) => $name->toString(), $primaryKey->getColumnNames());
|
||||
} else {
|
||||
$pkColumns = self::getIndexedColumns($primaryKey);
|
||||
}
|
||||
|
||||
sort($pkColumns);
|
||||
sort($allForeignKeyColumns);
|
||||
@@ -301,17 +319,25 @@ class DatabaseDriver implements MappingDriver
|
||||
*/
|
||||
private function buildIndexes(ClassMetadata $metadata): void
|
||||
{
|
||||
$tableName = $metadata->table['name'];
|
||||
$indexes = $this->tables[$tableName]->getIndexes();
|
||||
$tableName = $metadata->table['name'];
|
||||
$table = $this->tables[$tableName];
|
||||
$primaryKey = self::getPrimaryKey($table);
|
||||
$indexes = $table->getIndexes();
|
||||
|
||||
foreach ($indexes as $index) {
|
||||
if ($index->isPrimary()) {
|
||||
if ($index === $primaryKey) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enum_exists(IndexType::class) && method_exists($index, 'getType')) {
|
||||
$isUnique = $index->getType() === IndexType::UNIQUE;
|
||||
} else {
|
||||
$isUnique = $index->isUnique();
|
||||
}
|
||||
|
||||
$indexName = $index->getName();
|
||||
$indexColumns = $index->getColumns();
|
||||
$constraintType = $index->isUnique()
|
||||
$indexColumns = self::getIndexedColumns($index);
|
||||
$constraintType = $isUnique
|
||||
? 'uniqueConstraints'
|
||||
: 'indexes';
|
||||
|
||||
@@ -331,7 +357,7 @@ class DatabaseDriver implements MappingDriver
|
||||
$allForeignKeys = [];
|
||||
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$allForeignKeys = array_merge($allForeignKeys, $foreignKey->getLocalColumns());
|
||||
$allForeignKeys = array_merge($allForeignKeys, self::getReferencingColumnNames($foreignKey));
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
@@ -441,9 +467,9 @@ class DatabaseDriver implements MappingDriver
|
||||
$foreignKeys = $this->tables[$tableName]->getForeignKeys();
|
||||
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$foreignTableName = $foreignKey->getForeignTableName();
|
||||
$fkColumns = $foreignKey->getLocalColumns();
|
||||
$fkForeignColumns = $foreignKey->getForeignColumns();
|
||||
$foreignTableName = self::getReferencedTableName($foreignKey);
|
||||
$fkColumns = self::getReferencingColumnNames($foreignKey);
|
||||
$fkForeignColumns = self::getReferencedColumnNames($foreignKey);
|
||||
$localColumn = current($fkColumns);
|
||||
$associationMapping = [
|
||||
'fieldName' => $this->getFieldNameForColumn($tableName, $localColumn, true),
|
||||
@@ -482,7 +508,11 @@ class DatabaseDriver implements MappingDriver
|
||||
private function getTablePrimaryKeys(Table $table): array
|
||||
{
|
||||
try {
|
||||
return $table->getPrimaryKey()->getColumns();
|
||||
if (method_exists($table, 'getPrimaryKeyConstraint')) {
|
||||
return array_map(static fn (UnqualifiedName $name) => $name->toString(), $table->getPrimaryKeyConstraint()->getColumnNames());
|
||||
}
|
||||
|
||||
return self::getIndexedColumns($table->getPrimaryKey());
|
||||
} catch (SchemaException) {
|
||||
// Do nothing
|
||||
}
|
||||
@@ -527,4 +557,66 @@ class DatabaseDriver implements MappingDriver
|
||||
|
||||
return $this->inflector->camelize($columnName);
|
||||
}
|
||||
|
||||
private static function getReferencedTableName(ForeignKeyConstraint $foreignKey): string
|
||||
{
|
||||
if (method_exists(ForeignKeyConstraint::class, 'getReferencedTableName')) {
|
||||
return $foreignKey->getReferencedTableName()->toString();
|
||||
}
|
||||
|
||||
return $foreignKey->getForeignTableName();
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private static function getReferencingColumnNames(ForeignKeyConstraint $foreignKey): array
|
||||
{
|
||||
if (method_exists(ForeignKeyConstraint::class, 'getReferencingColumnNames')) {
|
||||
return array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencingColumnNames());
|
||||
}
|
||||
|
||||
return $foreignKey->getLocalColumns();
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private static function getReferencedColumnNames(ForeignKeyConstraint $foreignKey): array
|
||||
{
|
||||
if (method_exists(ForeignKeyConstraint::class, 'getReferencedColumnNames')) {
|
||||
return array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencedColumnNames());
|
||||
}
|
||||
|
||||
return $foreignKey->getForeignColumns();
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private static function getIndexedColumns(Index $index): array
|
||||
{
|
||||
if (method_exists(Index::class, 'getIndexedColumns')) {
|
||||
return array_map(static fn (IndexedColumn $indexedColumn) => $indexedColumn->getColumnName()->toString(), $index->getIndexedColumns());
|
||||
}
|
||||
|
||||
return $index->getColumns();
|
||||
}
|
||||
|
||||
private static function getPrimaryKey(Table $table): Index|null
|
||||
{
|
||||
$primaryKeyConstraint = null;
|
||||
|
||||
if (method_exists(Table::class, 'getPrimaryKeyConstraint')) {
|
||||
$primaryKeyConstraint = $table->getPrimaryKeyConstraint();
|
||||
}
|
||||
|
||||
foreach ($table->getIndexes() as $index) {
|
||||
if ($primaryKeyConstraint !== null) {
|
||||
$primaryKeyConstraintColumns = array_map(static fn (UnqualifiedName $name) => $name->toString(), $primaryKeyConstraint->getColumnNames());
|
||||
|
||||
if ($primaryKeyConstraintColumns === self::getIndexedColumns($index)) {
|
||||
return $index;
|
||||
}
|
||||
} elseif ($index->isPrimary()) {
|
||||
return $index;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,13 @@ trait ReflectionBasedDriver
|
||||
*/
|
||||
private function isRepeatedPropertyDeclaration(ReflectionProperty $property, ClassMetadata $metadata): bool
|
||||
{
|
||||
/** @var class-string $declaringClass */
|
||||
$declaringClass = $property->class;
|
||||
|
||||
if ($this->isTransient($declaringClass)) {
|
||||
return isset($metadata->fieldMappings[$property->name]);
|
||||
}
|
||||
|
||||
if (
|
||||
isset($metadata->fieldMappings[$property->name]->declared)
|
||||
&& $metadata->fieldMappings[$property->name]->declared === $declaringClass
|
||||
|
||||
@@ -185,7 +185,7 @@ EXCEPTION
|
||||
. ' configured to cascade persist operations for entity: ' . self::objToStr($entity) . '.'
|
||||
. ' To solve this issue: Either explicitly call EntityManager#persist()'
|
||||
. ' on this unknown entity or configure cascade persist'
|
||||
. ' this association in the mapping for example @ManyToOne(..,cascade={"persist"}).'
|
||||
. ' this association in the mapping for example #[ORM\ManyToOne(..., cascade: [\'persist\'])].'
|
||||
. ($entity instanceof Stringable
|
||||
? ''
|
||||
: ' If you cannot find out which entity causes the problem implement \''
|
||||
|
||||
@@ -1334,6 +1334,12 @@ class BasicEntityPersister implements EntityPersister
|
||||
$joinCondition[] = $this->getSQLTableAlias($association->sourceEntity, $assocAlias) . '.' . $sourceCol . ' = '
|
||||
. $this->getSQLTableAlias($association->targetEntity) . '.' . $targetCol;
|
||||
}
|
||||
|
||||
// Add filter SQL
|
||||
$filterSql = $this->generateFilterConditionSQL($eagerEntity, $joinTableAlias);
|
||||
if ($filterSql) {
|
||||
$joinCondition[] = $filterSql;
|
||||
}
|
||||
}
|
||||
|
||||
$this->currentPersisterContext->selectJoinSql .= ' ' . $joinTableName . ' ' . $joinTableAlias . ' ON ';
|
||||
@@ -1500,7 +1506,15 @@ class BasicEntityPersister implements EntityPersister
|
||||
$tableAlias = $this->getSQLTableAlias($class->name, $root);
|
||||
$fieldMapping = $class->fieldMappings[$field];
|
||||
$sql = sprintf('%s.%s', $tableAlias, $this->quoteStrategy->getColumnName($field, $class, $this->platform));
|
||||
$columnAlias = $this->getSQLColumnAlias($fieldMapping->columnName);
|
||||
|
||||
$columnAlias = null;
|
||||
if ($this->currentPersisterContext->rsm->hasColumnAliasByField($alias, $field)) {
|
||||
$columnAlias = $this->currentPersisterContext->rsm->getColumnAliasByField($alias, $field);
|
||||
}
|
||||
|
||||
if ($columnAlias === null) {
|
||||
$columnAlias = $this->getSQLColumnAlias($fieldMapping->columnName);
|
||||
}
|
||||
|
||||
$this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field);
|
||||
if (! empty($fieldMapping->enumType)) {
|
||||
|
||||
@@ -233,7 +233,7 @@ EOPHP;
|
||||
$class = $entityPersister->getClassMetadata();
|
||||
|
||||
foreach ($class->getReflectionProperties() as $property) {
|
||||
if (! $property || isset($identifier[$property->getName()]) || ! $class->hasField($property->getName()) && ! $class->hasAssociation($property->getName())) {
|
||||
if (! $property || isset($identifier[$property->getName()])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ EOPHP;
|
||||
foreach ($reflector->getProperties($filter) as $property) {
|
||||
$name = $property->name;
|
||||
|
||||
if ($property->isStatic() || (($class->hasField($name) || $class->hasAssociation($name)) && ! isset($identifiers[$name]))) {
|
||||
if ($property->isStatic() || ! isset($identifiers[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ namespace Doctrine\ORM\Query\AST;
|
||||
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
|
||||
use function func_get_arg;
|
||||
use function func_num_args;
|
||||
|
||||
/**
|
||||
* NewObjectExpression ::= "NEW" IdentificationVariable "(" NewObjectArg {"," NewObjectArg}* ")"
|
||||
*
|
||||
@@ -13,13 +16,18 @@ use Doctrine\ORM\Query\SqlWalker;
|
||||
*/
|
||||
class NewObjectExpression extends Node
|
||||
{
|
||||
/** @param mixed[] $args */
|
||||
/**
|
||||
* @param class-string $className
|
||||
* @param mixed[] $args
|
||||
*/
|
||||
public function __construct(public string $className, public array $args)
|
||||
{
|
||||
}
|
||||
|
||||
public function dispatch(SqlWalker $walker): string
|
||||
public function dispatch(SqlWalker $walker /*, string|null $parentAlias = null */): string
|
||||
{
|
||||
return $walker->walkNewObject($this);
|
||||
$parentAlias = func_num_args() > 1 ? func_get_arg(1) : null;
|
||||
|
||||
return $walker->walkNewObject($this, $parentAlias);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1767,6 +1767,7 @@ final class Parser
|
||||
$useNamedArguments = true;
|
||||
}
|
||||
|
||||
/** @var class-string $className */
|
||||
$className = $this->AbstractSchemaName(); // note that this is not yet validated
|
||||
$token = $this->lexer->token;
|
||||
|
||||
@@ -1854,7 +1855,11 @@ final class Parser
|
||||
|
||||
if ($this->lexer->isNextToken(TokenType::T_AS)) {
|
||||
$this->match(TokenType::T_AS);
|
||||
$fieldAlias = $this->AliasIdentificationVariable();
|
||||
$this->match(TokenType::T_IDENTIFIER);
|
||||
|
||||
assert($this->lexer->token !== null);
|
||||
|
||||
$fieldAlias = $this->lexer->token->value;
|
||||
}
|
||||
|
||||
return $expression;
|
||||
|
||||
@@ -66,6 +66,13 @@ class ResultSetMapping
|
||||
*/
|
||||
public array $fieldMappings = [];
|
||||
|
||||
/**
|
||||
* Map field names for each class to alias
|
||||
*
|
||||
* @var array<class-string, array<string, array<string, string>>>
|
||||
*/
|
||||
public array $columnAliasMappings = [];
|
||||
|
||||
/**
|
||||
* Maps column names in the result set to the alias/field name to use in the mapped result.
|
||||
*
|
||||
@@ -152,6 +159,13 @@ class ResultSetMapping
|
||||
*/
|
||||
public array $newObjectMappings = [];
|
||||
|
||||
/**
|
||||
* Maps object Ids in the result set to classnames.
|
||||
*
|
||||
* @phpstan-var array<string|int, class-string>
|
||||
*/
|
||||
public array $newObject = [];
|
||||
|
||||
/**
|
||||
* Maps last argument for new objects in order to initiate object construction
|
||||
*
|
||||
@@ -328,7 +342,10 @@ class ResultSetMapping
|
||||
// column name => alias of owner
|
||||
$this->columnOwnerMap[$columnName] = $alias;
|
||||
// field name => class name of declaring class
|
||||
$this->declaringClasses[$columnName] = $declaringClass ?: $this->aliasMap[$alias];
|
||||
$declaringClass = $declaringClass ?: $this->aliasMap[$alias];
|
||||
$this->declaringClasses[$columnName] = $declaringClass;
|
||||
|
||||
$this->columnAliasMappings[$declaringClass][$alias][$fieldName] = $columnName;
|
||||
|
||||
if (! $this->isMixed && $this->scalarMappings) {
|
||||
$this->isMixed = true;
|
||||
@@ -337,6 +354,20 @@ class ResultSetMapping
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasColumnAliasByField(string $alias, string $fieldName): bool
|
||||
{
|
||||
$declaringClass = $this->aliasMap[$alias];
|
||||
|
||||
return isset($this->columnAliasMappings[$declaringClass][$alias][$fieldName]);
|
||||
}
|
||||
|
||||
public function getColumnAliasByField(string $alias, string $fieldName): string
|
||||
{
|
||||
$declaringClass = $this->aliasMap[$alias];
|
||||
|
||||
return $this->columnAliasMappings[$declaringClass][$alias][$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a joined entity result.
|
||||
*
|
||||
|
||||
@@ -24,10 +24,8 @@ use function array_filter;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function array_pop;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function end;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
@@ -84,13 +82,6 @@ class SqlWalker
|
||||
*/
|
||||
private int $newObjectCounter = 0;
|
||||
|
||||
/**
|
||||
* Contains nesting levels of new objects arguments
|
||||
*
|
||||
* @phpstan-var array<int, array{0: string|int, 1: int}>
|
||||
*/
|
||||
private array $newObjectStack = [];
|
||||
|
||||
private readonly EntityManagerInterface $em;
|
||||
private readonly Connection $conn;
|
||||
|
||||
@@ -1507,14 +1498,7 @@ class SqlWalker
|
||||
public function walkNewObject(AST\NewObjectExpression $newObjectExpression, string|null $newObjectResultAlias = null): string
|
||||
{
|
||||
$sqlSelectExpressions = [];
|
||||
$objOwner = $objOwnerIdx = null;
|
||||
|
||||
if ($this->newObjectStack !== []) {
|
||||
[$objOwner, $objOwnerIdx] = end($this->newObjectStack);
|
||||
$objIndex = $objOwner . ':' . $objOwnerIdx;
|
||||
} else {
|
||||
$objIndex = $newObjectResultAlias ?: $this->newObjectCounter++;
|
||||
}
|
||||
$objIndex = $newObjectResultAlias ?: $this->newObjectCounter++;
|
||||
|
||||
foreach ($newObjectExpression->args as $argIndex => $e) {
|
||||
$resultAlias = $this->scalarResultCounter++;
|
||||
@@ -1523,10 +1507,8 @@ class SqlWalker
|
||||
|
||||
switch (true) {
|
||||
case $e instanceof AST\NewObjectExpression:
|
||||
$this->newObjectStack[] = [$objIndex, $argIndex];
|
||||
$sqlSelectExpressions[] = $e->dispatch($this);
|
||||
array_pop($this->newObjectStack);
|
||||
$this->rsm->nestedNewObjectArguments[$columnAlias] = ['ownerIndex' => $objIndex, 'argIndex' => $argIndex];
|
||||
$sqlSelectExpressions[] = $e->dispatch($this, $columnAlias);
|
||||
$this->rsm->nestedNewObjectArguments[$columnAlias] = ['ownerIndex' => $objIndex, 'argIndex' => $argIndex, 'argAlias' => $columnAlias];
|
||||
break;
|
||||
|
||||
case $e instanceof AST\Subselect:
|
||||
@@ -1576,12 +1558,13 @@ class SqlWalker
|
||||
$this->rsm->addScalarResult($columnAlias, $resultAlias, $fieldType);
|
||||
|
||||
$this->rsm->newObjectMappings[$columnAlias] = [
|
||||
'className' => $newObjectExpression->className,
|
||||
'objIndex' => $objIndex,
|
||||
'argIndex' => $argIndex,
|
||||
];
|
||||
}
|
||||
|
||||
$this->rsm->newObject[$objIndex] = $newObjectExpression->className;
|
||||
|
||||
return implode(', ', $sqlSelectExpressions);
|
||||
}
|
||||
|
||||
|
||||
@@ -504,7 +504,7 @@ class QueryBuilder implements Stringable
|
||||
$key = Parameter::normalizeName($key);
|
||||
|
||||
$filteredParameters = $this->parameters->filter(
|
||||
static fn (Parameter $parameter): bool => $key === $parameter->getName()
|
||||
static fn (Parameter $parameter): bool => $key === $parameter->getName(),
|
||||
);
|
||||
|
||||
return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null;
|
||||
|
||||
@@ -162,7 +162,7 @@ EOT);
|
||||
|
||||
$matches = array_filter(
|
||||
$this->getMappedEntities($entityManager),
|
||||
static fn ($mappedEntity) => preg_match('{' . preg_quote($entityName) . '}', $mappedEntity)
|
||||
static fn ($mappedEntity) => preg_match('{' . preg_quote($entityName) . '}', $mappedEntity),
|
||||
);
|
||||
|
||||
if (! $matches) {
|
||||
|
||||
@@ -89,17 +89,24 @@ class LimitSubqueryOutputWalker extends SqlOutputWalker
|
||||
$this->platform = $query->getEntityManager()->getConnection()->getDatabasePlatform();
|
||||
$this->rsm = $parserResult->getResultSetMapping();
|
||||
|
||||
$query = clone $query;
|
||||
$cloneQuery = clone $query;
|
||||
|
||||
$cloneQuery->setParameters(clone $query->getParameters());
|
||||
$cloneQuery->setCacheable(false);
|
||||
|
||||
foreach ($query->getHints() as $name => $value) {
|
||||
$cloneQuery->setHint($name, $value);
|
||||
}
|
||||
|
||||
// Reset limit and offset
|
||||
$this->firstResult = $query->getFirstResult();
|
||||
$this->maxResults = $query->getMaxResults();
|
||||
$query->setFirstResult(0)->setMaxResults(null);
|
||||
$this->firstResult = $cloneQuery->getFirstResult();
|
||||
$this->maxResults = $cloneQuery->getMaxResults();
|
||||
$cloneQuery->setFirstResult(0)->setMaxResults(null);
|
||||
|
||||
$this->em = $query->getEntityManager();
|
||||
$this->em = $cloneQuery->getEntityManager();
|
||||
$this->quoteStrategy = $this->em->getConfiguration()->getQuoteStrategy();
|
||||
|
||||
parent::__construct($query, $parserResult, $queryComponents);
|
||||
parent::__construct($cloneQuery, $parserResult, $queryComponents);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,13 @@ use BackedEnum;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\AbstractAsset;
|
||||
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||
use Doctrine\DBAL\Schema\ComparatorConfig;
|
||||
use Doctrine\DBAL\Schema\ForeignKeyConstraintEditor;
|
||||
use Doctrine\DBAL\Schema\Index;
|
||||
use Doctrine\DBAL\Schema\Index\IndexedColumn;
|
||||
use Doctrine\DBAL\Schema\Name\Identifier;
|
||||
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
|
||||
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -31,12 +37,15 @@ use function array_diff_key;
|
||||
use function array_filter;
|
||||
use function array_flip;
|
||||
use function array_intersect_key;
|
||||
use function array_map;
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use function count;
|
||||
use function current;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function is_numeric;
|
||||
use function method_exists;
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
@@ -282,7 +291,7 @@ class SchemaTool
|
||||
}
|
||||
|
||||
if ($pkColumns !== []) {
|
||||
$table->setPrimaryKey($pkColumns);
|
||||
self::addPrimaryKeyConstraint($table, $pkColumns);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -306,7 +315,7 @@ class SchemaTool
|
||||
}
|
||||
|
||||
if (! $table->hasIndex('primary')) {
|
||||
$table->setPrimaryKey($pkColumns);
|
||||
self::addPrimaryKeyConstraint($table, $pkColumns);
|
||||
}
|
||||
|
||||
// there can be unique indexes automatically created for join column
|
||||
@@ -315,7 +324,7 @@ class SchemaTool
|
||||
$primaryKey = $table->getIndex('primary');
|
||||
|
||||
foreach ($table->getIndexes() as $idxKey => $existingIndex) {
|
||||
if ($primaryKey->overrules($existingIndex)) {
|
||||
if ($existingIndex !== $primaryKey && $primaryKey->spansColumns(self::getIndexedColumns($existingIndex))) {
|
||||
$table->dropIndex($idxKey);
|
||||
}
|
||||
}
|
||||
@@ -346,7 +355,7 @@ class SchemaTool
|
||||
}
|
||||
}
|
||||
|
||||
$table->addUniqueIndex($uniqIndex->getColumns(), is_numeric($indexName) ? null : $indexName, $indexData['options'] ?? []);
|
||||
$table->addUniqueIndex(self::getIndexedColumns($uniqIndex), is_numeric($indexName) ? null : $indexName, $indexData['options'] ?? []);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,7 +581,7 @@ class SchemaTool
|
||||
$blacklistedFks,
|
||||
);
|
||||
|
||||
$theJoinTable->setPrimaryKey($primaryKeyColumns);
|
||||
self::addPrimaryKeyConstraint($theJoinTable, $primaryKeyColumns);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -725,7 +734,18 @@ class SchemaTool
|
||||
) {
|
||||
foreach ($theJoinTable->getForeignKeys() as $fkName => $key) {
|
||||
if (
|
||||
count(array_diff($key->getLocalColumns(), $localColumns)) === 0
|
||||
class_exists(ForeignKeyConstraintEditor::class)
|
||||
&& count(array_diff(array_map(static fn (UnqualifiedName $name) => $name->toString(), $key->getReferencingColumnNames()), $localColumns)) === 0
|
||||
&& (($key->getReferencedTableName()->toString() !== $foreignTableName)
|
||||
|| 0 < count(array_diff(array_map(static fn (UnqualifiedName $name) => $name->toString(), $key->getReferencedColumnNames()), $foreignColumns)))
|
||||
) {
|
||||
$theJoinTable->dropForeignKey($fkName);
|
||||
break;
|
||||
}
|
||||
|
||||
if (
|
||||
! class_exists(ForeignKeyConstraintEditor::class)
|
||||
&& count(array_diff($key->getLocalColumns(), $localColumns)) === 0
|
||||
&& (($key->getForeignTableName() !== $foreignTableName)
|
||||
|| 0 < count(array_diff($key->getForeignColumns(), $foreignColumns)))
|
||||
) {
|
||||
@@ -843,12 +863,22 @@ class SchemaTool
|
||||
}
|
||||
|
||||
foreach ($schema->getTables() as $table) {
|
||||
$primaryKey = $table->getPrimaryKey();
|
||||
if (method_exists($table, 'getPrimaryKeyConstraint')) {
|
||||
$primaryKey = $table->getPrimaryKeyConstraint();
|
||||
} else {
|
||||
$primaryKey = $table->getPrimaryKey();
|
||||
}
|
||||
|
||||
if ($primaryKey === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$columns = $primaryKey->getColumns();
|
||||
if ($primaryKey instanceof PrimaryKeyConstraint) {
|
||||
$columns = array_map(static fn (UnqualifiedName $name) => $name->toString(), $primaryKey->getColumnNames());
|
||||
} else {
|
||||
$columns = self::getIndexedColumns($primaryKey);
|
||||
}
|
||||
|
||||
if (count($columns) === 1) {
|
||||
$checkSequence = $table->getName() . '_' . $columns[0] . '_seq';
|
||||
if ($deployedSchema->hasSequence($checkSequence) && ! $schema->hasSequence($checkSequence)) {
|
||||
@@ -888,7 +918,13 @@ class SchemaTool
|
||||
{
|
||||
$toSchema = $this->getSchemaFromMetadata($classes);
|
||||
$fromSchema = $this->createSchemaForComparison($toSchema);
|
||||
$comparator = $this->schemaManager->createComparator();
|
||||
|
||||
if (class_exists(ComparatorConfig::class)) {
|
||||
$comparator = $this->schemaManager->createComparator((new ComparatorConfig())->withReportModifiedIndexes(false));
|
||||
} else {
|
||||
$comparator = $this->schemaManager->createComparator();
|
||||
}
|
||||
|
||||
$schemaDiff = $comparator->compareSchemas($fromSchema, $toSchema);
|
||||
|
||||
return $this->platform->getAlterSchemaSQL($schemaDiff);
|
||||
@@ -923,4 +959,30 @@ class SchemaTool
|
||||
$config->setSchemaAssetsFilter($previousFilter);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param string[] $primaryKeyColumns */
|
||||
private function addPrimaryKeyConstraint(Table $table, array $primaryKeyColumns): void
|
||||
{
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$primaryKeyColumnNames = [];
|
||||
|
||||
foreach ($primaryKeyColumns as $primaryKeyColumn) {
|
||||
$primaryKeyColumnNames[] = new UnqualifiedName(Identifier::unquoted($primaryKeyColumn));
|
||||
}
|
||||
|
||||
$table->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, $primaryKeyColumnNames, true));
|
||||
} else {
|
||||
$table->setPrimaryKey($primaryKeyColumns);
|
||||
}
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private static function getIndexedColumns(Index $index): array
|
||||
{
|
||||
if (method_exists(Index::class, 'getIndexedColumns')) {
|
||||
return array_map(static fn (IndexedColumn $indexedColumn) => $indexedColumn->getColumnName()->toString(), $index->getIndexedColumns());
|
||||
}
|
||||
|
||||
return $index->getColumns();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ use Exception;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Stringable;
|
||||
use Symfony\Component\VarExporter\Hydrator;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function array_chunk;
|
||||
@@ -2024,7 +2025,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
static fn (AssociationMapping $assoc): bool => $assoc->isCascadeRefresh()
|
||||
static fn (AssociationMapping $assoc): bool => $assoc->isCascadeRefresh(),
|
||||
);
|
||||
|
||||
foreach ($associationMappings as $assoc) {
|
||||
@@ -2065,7 +2066,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
static fn (AssociationMapping $assoc): bool => $assoc->isCascadeDetach()
|
||||
static fn (AssociationMapping $assoc): bool => $assoc->isCascadeDetach(),
|
||||
);
|
||||
|
||||
foreach ($associationMappings as $assoc) {
|
||||
@@ -2111,7 +2112,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
static fn (AssociationMapping $assoc): bool => $assoc->isCascadePersist()
|
||||
static fn (AssociationMapping $assoc): bool => $assoc->isCascadePersist(),
|
||||
);
|
||||
|
||||
foreach ($associationMappings as $assoc) {
|
||||
@@ -2168,7 +2169,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
static fn (AssociationMapping $assoc): bool => $assoc->isCascadeRemove()
|
||||
static fn (AssociationMapping $assoc): bool => $assoc->isCascadeRemove(),
|
||||
);
|
||||
|
||||
if ($associationMappings) {
|
||||
@@ -2379,6 +2380,8 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
if ($this->isUninitializedObject($entity)) {
|
||||
$entity->__setInitialized(true);
|
||||
|
||||
Hydrator::hydrate($entity, (array) $class->reflClass->newInstanceWithoutConstructor());
|
||||
} else {
|
||||
if (
|
||||
! isset($hints[Query::HINT_REFRESH])
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Doctrine\Tests\Models\CMS;
|
||||
|
||||
class CmsAddressDTO
|
||||
{
|
||||
public function __construct(public string|null $country = null, public string|null $city = null, public string|null $zip = null, public CmsAddressDTO|string|null $address = null)
|
||||
public function __construct(public string|null $country = null, public string|null $city = null, public string|null $zip = null, public string|null $address = null, public CmsDumbDTO|null $other = null)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
17
tests/Tests/Models/CMS/CmsDumbDTO.php
Normal file
17
tests/Tests/Models/CMS/CmsDumbDTO.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\Models\CMS;
|
||||
|
||||
class CmsDumbDTO
|
||||
{
|
||||
public function __construct(
|
||||
public mixed $val1 = null,
|
||||
public mixed $val2 = null,
|
||||
public mixed $val3 = null,
|
||||
public mixed $val4 = null,
|
||||
public mixed $val5 = null,
|
||||
) {
|
||||
}
|
||||
}
|
||||
21
tests/Tests/Models/GH11524/GH11524Entity.php
Normal file
21
tests/Tests/Models/GH11524/GH11524Entity.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\Models\GH11524;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: 'gh11524_entities')]
|
||||
class GH11524Entity
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
#[ORM\GeneratedValue]
|
||||
public int|null $id = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: GH11524Relation::class)]
|
||||
#[ORM\JoinColumn(name: 'relation_id', referencedColumnName: 'id', nullable: true)]
|
||||
public GH11524Relation|null $relation = null;
|
||||
}
|
||||
21
tests/Tests/Models/GH11524/GH11524Listener.php
Normal file
21
tests/Tests/Models/GH11524/GH11524Listener.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\Models\GH11524;
|
||||
|
||||
use Doctrine\ORM\Event\PostLoadEventArgs;
|
||||
|
||||
class GH11524Listener
|
||||
{
|
||||
public function postLoad(PostloadEventArgs $eventArgs): void
|
||||
{
|
||||
$object = $eventArgs->getObject();
|
||||
|
||||
if (! $object instanceof GH11524Relation) {
|
||||
return;
|
||||
}
|
||||
|
||||
$object->setCurrentLocale('en');
|
||||
}
|
||||
}
|
||||
37
tests/Tests/Models/GH11524/GH11524Relation.php
Normal file
37
tests/Tests/Models/GH11524/GH11524Relation.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\Models\GH11524;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use LogicException;
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: 'gh11524_relations')]
|
||||
class GH11524Relation
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
#[ORM\GeneratedValue]
|
||||
public int|null $id;
|
||||
|
||||
#[ORM\Column(type: 'string')]
|
||||
public string $name;
|
||||
|
||||
private string|null $currentLocale;
|
||||
|
||||
public function setCurrentLocale(string $locale): void
|
||||
{
|
||||
$this->currentLocale = $locale;
|
||||
}
|
||||
|
||||
public function getTranslation(): string
|
||||
{
|
||||
if ($this->currentLocale === null) {
|
||||
throw new LogicException('The current locale must be set to retrieve translation.');
|
||||
}
|
||||
|
||||
return 'fake';
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,14 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
|
||||
use Doctrine\DBAL\Platforms\SQLServerPlatform;
|
||||
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||
use Doctrine\DBAL\Schema\Name\Identifier;
|
||||
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
|
||||
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function array_change_key_case;
|
||||
use function class_exists;
|
||||
use function count;
|
||||
use function strtolower;
|
||||
|
||||
@@ -36,12 +40,24 @@ class DatabaseDriverTest extends DatabaseDriverTestCase
|
||||
{
|
||||
$user = new Table('ddc2059_user');
|
||||
$user->addColumn('id', 'integer');
|
||||
$user->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$user->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$user->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$project = new Table('ddc2059_project');
|
||||
$project->addColumn('id', 'integer');
|
||||
$project->addColumn('user_id', 'integer');
|
||||
$project->addColumn('user', 'string');
|
||||
$project->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$project->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$project->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$project->addForeignKeyConstraint('ddc2059_user', ['user_id'], ['id']);
|
||||
|
||||
$metadata = $this->convertToClassMetadata([$project, $user], []);
|
||||
@@ -54,7 +70,13 @@ class DatabaseDriverTest extends DatabaseDriverTestCase
|
||||
{
|
||||
$table = new Table('dbdriver_foo');
|
||||
$table->addColumn('id', 'integer');
|
||||
$table->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$table->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$table->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$table->addColumn('bar', 'string', ['notnull' => false, 'length' => 200]);
|
||||
|
||||
$this->dropAndCreateTable($table);
|
||||
@@ -81,13 +103,24 @@ class DatabaseDriverTest extends DatabaseDriverTestCase
|
||||
{
|
||||
$tableB = new Table('dbdriver_bar');
|
||||
$tableB->addColumn('id', 'integer');
|
||||
$tableB->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$tableB->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$tableB->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$this->dropAndCreateTable($tableB);
|
||||
|
||||
$tableA = new Table('dbdriver_baz');
|
||||
$tableA->addColumn('id', 'integer');
|
||||
$tableA->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$tableA->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$tableA->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$tableA->addColumn('bar_id', 'integer');
|
||||
$tableA->addForeignKeyConstraint('dbdriver_bar', ['bar_id'], ['id']);
|
||||
|
||||
@@ -127,11 +160,21 @@ class DatabaseDriverTest extends DatabaseDriverTestCase
|
||||
{
|
||||
$tableB = new Table('dbdriver_bar');
|
||||
$tableB->addColumn('id', 'integer');
|
||||
$tableB->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$tableB->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$tableB->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$tableA = new Table('dbdriver_baz');
|
||||
$tableA->addColumn('id', 'integer');
|
||||
$tableA->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$tableA->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$tableA->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$tableMany = new Table('dbdriver_bar_baz');
|
||||
$tableMany->addColumn('bar_id', 'integer');
|
||||
@@ -148,7 +191,13 @@ class DatabaseDriverTest extends DatabaseDriverTestCase
|
||||
$table = new Table('dbdriver_foo');
|
||||
|
||||
$table->addColumn('id', 'integer', ['unsigned' => true]);
|
||||
$table->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$table->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$table->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$table->addColumn('column_unsigned', 'integer', ['unsigned' => true]);
|
||||
$table->addColumn('column_comment', 'string', ['length' => 16, 'comment' => 'test_comment']);
|
||||
$table->addColumn('column_default', 'string', ['length' => 16, 'default' => 'test_default']);
|
||||
|
||||
@@ -8,9 +8,11 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\ORM\Query\QueryException;
|
||||
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
|
||||
use function count;
|
||||
use function iterator_to_array;
|
||||
|
||||
class EagerFetchCollectionTest extends OrmFunctionalTestCase
|
||||
{
|
||||
@@ -97,6 +99,16 @@ class EagerFetchCollectionTest extends OrmFunctionalTestCase
|
||||
$this->assertIsString($query->getSql());
|
||||
}
|
||||
|
||||
public function testSubselectFetchJoinWithAllowedWhenOverriddenNotEagerPaginator(): void
|
||||
{
|
||||
$query = $this->_em->createQuery('SELECT o, c FROM ' . EagerFetchOwner::class . ' o JOIN o.children c WITH c.id = 1');
|
||||
$query->setMaxResults(1);
|
||||
$query->setFetchMode(EagerFetchChild::class, 'owner', ORM\ClassMetadata::FETCH_LAZY);
|
||||
|
||||
$paginator = new Paginator($query, true);
|
||||
$this->assertIsArray(iterator_to_array($paginator));
|
||||
}
|
||||
|
||||
public function testEagerFetchWithIterable(): void
|
||||
{
|
||||
$this->createOwnerWithChildren(2);
|
||||
|
||||
@@ -66,10 +66,11 @@ class LifecycleCallbackTest extends OrmFunctionalTestCase
|
||||
self::assertTrue($entity->postPersistCallbackInvoked);
|
||||
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
|
||||
$query = $this->_em->createQuery('select e from Doctrine\Tests\ORM\Functional\LifecycleCallbackTestEntity e');
|
||||
$result = $query->getResult();
|
||||
self::assertTrue($result[0]->postLoadCallbackInvoked);
|
||||
self::assertTrue($result[0]::$postLoadCallbackInvoked);
|
||||
|
||||
$result[0]->value = 'hello again';
|
||||
|
||||
@@ -130,12 +131,14 @@ class LifecycleCallbackTest extends OrmFunctionalTestCase
|
||||
$id = $entity->getId();
|
||||
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
|
||||
$reference = $this->_em->getReference(LifecycleCallbackTestEntity::class, $id);
|
||||
self::assertFalse($reference->postLoadCallbackInvoked);
|
||||
self::assertFalse($reference::$postLoadCallbackInvoked);
|
||||
$this->assertTrue($this->isUninitializedObject($reference));
|
||||
|
||||
$reference->getValue(); // trigger proxy load
|
||||
self::assertTrue($reference->postLoadCallbackInvoked);
|
||||
self::assertTrue($reference::$postLoadCallbackInvoked);
|
||||
}
|
||||
|
||||
#[Group('DDC-958')]
|
||||
@@ -148,13 +151,14 @@ class LifecycleCallbackTest extends OrmFunctionalTestCase
|
||||
$id = $entity->getId();
|
||||
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
|
||||
$reference = $this->_em->find(LifecycleCallbackTestEntity::class, $id);
|
||||
self::assertTrue($reference->postLoadCallbackInvoked);
|
||||
$reference->postLoadCallbackInvoked = false;
|
||||
self::assertTrue($reference::$postLoadCallbackInvoked);
|
||||
$reference::$postLoadCallbackInvoked = false;
|
||||
|
||||
$this->_em->refresh($reference);
|
||||
self::assertTrue($reference->postLoadCallbackInvoked, 'postLoad should be invoked when refresh() is called.');
|
||||
self::assertTrue($reference::$postLoadCallbackInvoked, 'postLoad should be invoked when refresh() is called.');
|
||||
}
|
||||
|
||||
#[Group('DDC-113')]
|
||||
@@ -195,6 +199,7 @@ class LifecycleCallbackTest extends OrmFunctionalTestCase
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
|
||||
$dql = <<<'DQL'
|
||||
SELECT
|
||||
@@ -212,9 +217,9 @@ DQL;
|
||||
->createQuery(sprintf($dql, $e1->getId(), $e2->getId()))
|
||||
->getResult();
|
||||
|
||||
self::assertTrue(current($entities)->postLoadCallbackInvoked);
|
||||
self::assertTrue(current($entities)::$postLoadCallbackInvoked);
|
||||
self::assertTrue(current($entities)->postLoadCascaderNotNull);
|
||||
self::assertTrue(current($entities)->cascader->postLoadCallbackInvoked);
|
||||
self::assertTrue(current($entities)->cascader::$postLoadCallbackInvoked);
|
||||
self::assertEquals(current($entities)->cascader->postLoadEntitiesCount, 2);
|
||||
}
|
||||
|
||||
@@ -235,6 +240,8 @@ DQL;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
LifecycleCallbackCascader::$postLoadCallbackInvoked = false;
|
||||
|
||||
$dql = <<<'DQL'
|
||||
SELECT
|
||||
@@ -252,7 +259,7 @@ DQL;
|
||||
$iterableResult = iterator_to_array($query->toIterable());
|
||||
|
||||
foreach ($iterableResult as $entity) {
|
||||
self::assertTrue($entity->postLoadCallbackInvoked);
|
||||
self::assertTrue($entity::$postLoadCallbackInvoked);
|
||||
self::assertFalse($entity->postLoadCascaderNotNull);
|
||||
|
||||
break;
|
||||
@@ -268,15 +275,15 @@ DQL;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
|
||||
$query = $this->_em->createQuery(
|
||||
$query = $this->_em->createQuery(
|
||||
'SELECT e FROM Doctrine\Tests\ORM\Functional\LifecycleCallbackTestEntity AS e',
|
||||
);
|
||||
|
||||
$result = iterator_to_array($query->toIterable([], Query::HYDRATE_SIMPLEOBJECT));
|
||||
|
||||
foreach ($result as $entity) {
|
||||
self::assertTrue($entity->postLoadCallbackInvoked);
|
||||
self::assertTrue($entity::$postLoadCallbackInvoked);
|
||||
self::assertFalse($entity->postLoadCascaderNotNull);
|
||||
|
||||
break;
|
||||
@@ -301,6 +308,8 @@ DQL;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
LifecycleCallbackCascader::$postLoadCallbackInvoked = false;
|
||||
|
||||
$dql = <<<'DQL'
|
||||
SELECT
|
||||
@@ -318,9 +327,9 @@ DQL;
|
||||
->createQuery($dql)->setParameter('entA_id', $entA->getId())
|
||||
->getOneOrNullResult();
|
||||
|
||||
self::assertTrue($fetchedA->postLoadCallbackInvoked);
|
||||
self::assertTrue($fetchedA::$postLoadCallbackInvoked);
|
||||
foreach ($fetchedA->entities as $fetchJoinedEntB) {
|
||||
self::assertTrue($fetchJoinedEntB->postLoadCallbackInvoked);
|
||||
self::assertTrue($fetchJoinedEntB::$postLoadCallbackInvoked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,7 +464,7 @@ class LifecycleCallbackTestEntity
|
||||
public $postPersistCallbackInvoked = false;
|
||||
|
||||
/** @var bool */
|
||||
public $postLoadCallbackInvoked = false;
|
||||
public static $postLoadCallbackInvoked = false;
|
||||
|
||||
/** @var bool */
|
||||
public $postLoadCascaderNotNull = false;
|
||||
@@ -502,7 +511,7 @@ class LifecycleCallbackTestEntity
|
||||
#[PostLoad]
|
||||
public function doStuffOnPostLoad(): void
|
||||
{
|
||||
$this->postLoadCallbackInvoked = true;
|
||||
self::$postLoadCallbackInvoked = true;
|
||||
$this->postLoadCascaderNotNull = isset($this->cascader);
|
||||
}
|
||||
|
||||
@@ -526,7 +535,7 @@ class LifecycleCallbackCascader
|
||||
{
|
||||
/* test stuff */
|
||||
/** @var bool */
|
||||
public $postLoadCallbackInvoked = false;
|
||||
public static $postLoadCallbackInvoked = false;
|
||||
|
||||
/** @var int */
|
||||
public $postLoadEntitiesCount = 0;
|
||||
@@ -548,7 +557,7 @@ class LifecycleCallbackCascader
|
||||
#[PostLoad]
|
||||
public function doStuffOnPostLoad(): void
|
||||
{
|
||||
$this->postLoadCallbackInvoked = true;
|
||||
self::$postLoadCallbackInvoked = true;
|
||||
$this->postLoadEntitiesCount = count($this->entities);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use Doctrine\ORM\Query\QueryException;
|
||||
use Doctrine\Tests\Models\CMS\CmsAddress;
|
||||
use Doctrine\Tests\Models\CMS\CmsAddressDTO;
|
||||
use Doctrine\Tests\Models\CMS\CmsAddressDTONamedArgs;
|
||||
use Doctrine\Tests\Models\CMS\CmsDumbDTO;
|
||||
use Doctrine\Tests\Models\CMS\CmsEmail;
|
||||
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||
use Doctrine\Tests\Models\CMS\CmsUser;
|
||||
@@ -1031,7 +1032,8 @@ class NewOperatorTest extends OrmFunctionalTestCase
|
||||
a.country,
|
||||
a.city,
|
||||
a.zip,
|
||||
new CmsAddressDTO(
|
||||
\'Abbey Road\',
|
||||
new CmsDumbDTO(
|
||||
a.country,
|
||||
a.city,
|
||||
a.zip
|
||||
@@ -1078,6 +1080,18 @@ class NewOperatorTest extends OrmFunctionalTestCase
|
||||
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->country);
|
||||
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->country);
|
||||
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[0]['user']->address->other);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[1]['user']->address->other);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[2]['user']->address->other);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->country, $result[0]['user']->address->other->val1);
|
||||
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->other->val1);
|
||||
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->other->val1);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->city, $result[0]['user']->address->other->val2);
|
||||
self::assertSame($this->fixtures[1]->address->city, $result[1]['user']->address->other->val2);
|
||||
self::assertSame($this->fixtures[2]->address->city, $result[2]['user']->address->other->val2);
|
||||
|
||||
self::assertSame($this->fixtures[0]->status, $result[0]['status']);
|
||||
self::assertSame($this->fixtures[1]->status, $result[1]['status']);
|
||||
self::assertSame($this->fixtures[2]->status, $result[2]['status']);
|
||||
@@ -1087,6 +1101,135 @@ class NewOperatorTest extends OrmFunctionalTestCase
|
||||
self::assertSame($this->fixtures[2]->username, $result[2]['cmsUserUsername']);
|
||||
}
|
||||
|
||||
public function testShouldSupportNestedNewOperatorsWithDtoFirst(): void
|
||||
{
|
||||
$dql = '
|
||||
SELECT
|
||||
new CmsUserDTO(
|
||||
u.name,
|
||||
e.email,
|
||||
new CmsAddressDTO(
|
||||
a.country,
|
||||
a.city,
|
||||
a.zip
|
||||
),
|
||||
555812452
|
||||
) as user,
|
||||
u.status,
|
||||
u.username as cmsUserUsername
|
||||
FROM
|
||||
Doctrine\Tests\Models\CMS\CmsUser u
|
||||
JOIN
|
||||
u.email e
|
||||
JOIN
|
||||
u.address a
|
||||
ORDER BY
|
||||
u.name';
|
||||
|
||||
$query = $this->getEntityManager()->createQuery($dql);
|
||||
$result = $query->getResult();
|
||||
|
||||
self::assertCount(3, $result);
|
||||
|
||||
self::assertInstanceOf(CmsUserDTO::class, $result[0]['user']);
|
||||
self::assertInstanceOf(CmsUserDTO::class, $result[1]['user']);
|
||||
self::assertInstanceOf(CmsUserDTO::class, $result[2]['user']);
|
||||
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[0]['user']->address);
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[1]['user']->address);
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[2]['user']->address);
|
||||
|
||||
self::assertSame($this->fixtures[0]->name, $result[0]['user']->name);
|
||||
self::assertSame($this->fixtures[1]->name, $result[1]['user']->name);
|
||||
self::assertSame($this->fixtures[2]->name, $result[2]['user']->name);
|
||||
|
||||
self::assertSame($this->fixtures[0]->email->email, $result[0]['user']->email);
|
||||
self::assertSame($this->fixtures[1]->email->email, $result[1]['user']->email);
|
||||
self::assertSame($this->fixtures[2]->email->email, $result[2]['user']->email);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->city, $result[0]['user']->address->city);
|
||||
self::assertSame($this->fixtures[1]->address->city, $result[1]['user']->address->city);
|
||||
self::assertSame($this->fixtures[2]->address->city, $result[2]['user']->address->city);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->country, $result[0]['user']->address->country);
|
||||
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->country);
|
||||
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->country);
|
||||
|
||||
self::assertSame(555812452, $result[0]['user']->phonenumbers);
|
||||
self::assertSame(555812452, $result[1]['user']->phonenumbers);
|
||||
self::assertSame(555812452, $result[2]['user']->phonenumbers);
|
||||
|
||||
self::assertSame($this->fixtures[0]->status, $result[0]['status']);
|
||||
self::assertSame($this->fixtures[1]->status, $result[1]['status']);
|
||||
self::assertSame($this->fixtures[2]->status, $result[2]['status']);
|
||||
|
||||
self::assertSame($this->fixtures[0]->username, $result[0]['cmsUserUsername']);
|
||||
self::assertSame($this->fixtures[1]->username, $result[1]['cmsUserUsername']);
|
||||
self::assertSame($this->fixtures[2]->username, $result[2]['cmsUserUsername']);
|
||||
}
|
||||
|
||||
public function testOnlyObjectInObject(): void
|
||||
{
|
||||
$dql = '
|
||||
SELECT
|
||||
new CmsDumbDTO(
|
||||
new CmsDumbDTO(
|
||||
u.name,
|
||||
e.email
|
||||
),
|
||||
new CmsAddressDTO(
|
||||
a.country,
|
||||
a.city,
|
||||
a.zip
|
||||
)
|
||||
) as user
|
||||
FROM
|
||||
Doctrine\Tests\Models\CMS\CmsUser u
|
||||
JOIN
|
||||
u.email e
|
||||
JOIN
|
||||
u.address a
|
||||
ORDER BY
|
||||
u.name';
|
||||
|
||||
$query = $this->getEntityManager()->createQuery($dql);
|
||||
$result = $query->getResult();
|
||||
|
||||
self::assertCount(3, $result);
|
||||
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[0]);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[1]);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[2]);
|
||||
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[0]->val1);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[1]->val1);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[2]->val1);
|
||||
|
||||
self::assertSame($this->fixtures[0]->name, $result[0]->val1->val1);
|
||||
self::assertSame($this->fixtures[1]->name, $result[1]->val1->val1);
|
||||
self::assertSame($this->fixtures[2]->name, $result[2]->val1->val1);
|
||||
|
||||
self::assertSame($this->fixtures[0]->email->email, $result[0]->val1->val2);
|
||||
self::assertSame($this->fixtures[1]->email->email, $result[1]->val1->val2);
|
||||
self::assertSame($this->fixtures[2]->email->email, $result[2]->val1->val2);
|
||||
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[0]->val2);
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[1]->val2);
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[2]->val2);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->country, $result[0]->val2->country);
|
||||
self::assertSame($this->fixtures[1]->address->country, $result[1]->val2->country);
|
||||
self::assertSame($this->fixtures[2]->address->country, $result[2]->val2->country);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->city, $result[0]->val2->city);
|
||||
self::assertSame($this->fixtures[1]->address->city, $result[1]->val2->city);
|
||||
self::assertSame($this->fixtures[2]->address->city, $result[2]->val2->city);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->zip, $result[0]->val2->zip);
|
||||
self::assertSame($this->fixtures[1]->address->zip, $result[1]->val2->zip);
|
||||
self::assertSame($this->fixtures[2]->address->zip, $result[2]->val2->zip);
|
||||
}
|
||||
|
||||
public function testNamedArguments(): void
|
||||
{
|
||||
$dql = <<<'SQL'
|
||||
@@ -1159,6 +1302,111 @@ class NewOperatorTest extends OrmFunctionalTestCase
|
||||
self::assertSame($this->fixtures[2]->username, $result[2]['cmsUserUsername']);
|
||||
}
|
||||
|
||||
public function testShouldSupportNestedNewOperatorsWithNestedDtoNotLast(): void
|
||||
{
|
||||
$dql = '
|
||||
SELECT
|
||||
new CmsUserDTO(
|
||||
u.name,
|
||||
e.email,
|
||||
new CmsAddressDTO(
|
||||
a.country,
|
||||
a.city,
|
||||
a.zip,
|
||||
\'Abbey Road\',
|
||||
new CmsDumbDTO(
|
||||
a.country,
|
||||
a.city,
|
||||
new CmsDumbDTO(
|
||||
a.zip,
|
||||
456
|
||||
),
|
||||
a.zip
|
||||
)
|
||||
),
|
||||
555812452
|
||||
) as user,
|
||||
u.status,
|
||||
u.username as cmsUserUsername
|
||||
FROM
|
||||
Doctrine\Tests\Models\CMS\CmsUser u
|
||||
JOIN
|
||||
u.email e
|
||||
JOIN
|
||||
u.address a
|
||||
ORDER BY
|
||||
u.name';
|
||||
|
||||
$query = $this->getEntityManager()->createQuery($dql);
|
||||
$result = $query->getResult();
|
||||
|
||||
self::assertCount(3, $result);
|
||||
|
||||
self::assertInstanceOf(CmsUserDTO::class, $result[0]['user']);
|
||||
self::assertInstanceOf(CmsUserDTO::class, $result[1]['user']);
|
||||
self::assertInstanceOf(CmsUserDTO::class, $result[2]['user']);
|
||||
|
||||
self::assertSame($this->fixtures[0]->name, $result[0]['user']->name);
|
||||
self::assertSame($this->fixtures[1]->name, $result[1]['user']->name);
|
||||
self::assertSame($this->fixtures[2]->name, $result[2]['user']->name);
|
||||
|
||||
self::assertSame($this->fixtures[0]->email->email, $result[0]['user']->email);
|
||||
self::assertSame($this->fixtures[1]->email->email, $result[1]['user']->email);
|
||||
self::assertSame($this->fixtures[2]->email->email, $result[2]['user']->email);
|
||||
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[0]['user']->address);
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[1]['user']->address);
|
||||
self::assertInstanceOf(CmsAddressDTO::class, $result[2]['user']->address);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->country, $result[0]['user']->address->country);
|
||||
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->country);
|
||||
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->country);
|
||||
|
||||
self::assertSame($this->fixtures[2]->address->city, $result[2]['user']->address->city);
|
||||
self::assertSame($this->fixtures[0]->address->city, $result[0]['user']->address->city);
|
||||
self::assertSame($this->fixtures[1]->address->city, $result[1]['user']->address->city);
|
||||
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[0]['user']->address->other);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[1]['user']->address->other);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[2]['user']->address->other);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->country, $result[0]['user']->address->other->val1);
|
||||
self::assertSame($this->fixtures[1]->address->country, $result[1]['user']->address->other->val1);
|
||||
self::assertSame($this->fixtures[2]->address->country, $result[2]['user']->address->other->val1);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->city, $result[0]['user']->address->other->val2);
|
||||
self::assertSame($this->fixtures[1]->address->city, $result[1]['user']->address->other->val2);
|
||||
self::assertSame($this->fixtures[2]->address->city, $result[2]['user']->address->other->val2);
|
||||
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[0]['user']->address->other->val3);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[1]['user']->address->other->val3);
|
||||
self::assertInstanceOf(CmsDumbDTO::class, $result[2]['user']->address->other->val3);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->zip, $result[0]['user']->address->other->val3->val1);
|
||||
self::assertSame($this->fixtures[1]->address->zip, $result[1]['user']->address->other->val3->val1);
|
||||
self::assertSame($this->fixtures[2]->address->zip, $result[2]['user']->address->other->val3->val1);
|
||||
|
||||
self::assertSame(456, $result[0]['user']->address->other->val3->val2);
|
||||
self::assertSame(456, $result[1]['user']->address->other->val3->val2);
|
||||
self::assertSame(456, $result[2]['user']->address->other->val3->val2);
|
||||
|
||||
self::assertSame($this->fixtures[0]->address->zip, $result[0]['user']->address->other->val4);
|
||||
self::assertSame($this->fixtures[1]->address->zip, $result[1]['user']->address->other->val4);
|
||||
self::assertSame($this->fixtures[2]->address->zip, $result[2]['user']->address->other->val4);
|
||||
|
||||
self::assertSame(555812452, $result[0]['user']->phonenumbers);
|
||||
self::assertSame(555812452, $result[1]['user']->phonenumbers);
|
||||
self::assertSame(555812452, $result[2]['user']->phonenumbers);
|
||||
|
||||
self::assertSame($this->fixtures[0]->status, $result[0]['status']);
|
||||
self::assertSame($this->fixtures[1]->status, $result[1]['status']);
|
||||
self::assertSame($this->fixtures[2]->status, $result[2]['status']);
|
||||
|
||||
self::assertSame($this->fixtures[0]->username, $result[0]['cmsUserUsername']);
|
||||
self::assertSame($this->fixtures[1]->username, $result[1]['cmsUserUsername']);
|
||||
self::assertSame($this->fixtures[2]->username, $result[2]['cmsUserUsername']);
|
||||
}
|
||||
|
||||
public function testVariadicArgument(): void
|
||||
{
|
||||
$dql = <<<'SQL'
|
||||
|
||||
@@ -12,6 +12,7 @@ use Doctrine\ORM\Query\AST\Literal;
|
||||
use Doctrine\ORM\Query\AST\PathExpression;
|
||||
use Doctrine\ORM\Query\AST\SelectStatement;
|
||||
use Doctrine\ORM\Query\AST\WhereClause;
|
||||
use Doctrine\ORM\Query\SqlOutputWalker;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
use Doctrine\ORM\Query\TreeWalkerAdapter;
|
||||
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||
@@ -643,7 +644,7 @@ class PaginationTest extends OrmFunctionalTestCase
|
||||
self::assertCount(2, $getCountQuery->invoke($paginator)->getParameters());
|
||||
self::assertCount(9, $paginator);
|
||||
|
||||
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, SqlWalker::class);
|
||||
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, SqlOutputWalker::class);
|
||||
|
||||
$paginator = new Paginator($query);
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use Generator;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use ReflectionMethod;
|
||||
use Symfony\Component\VarExporter\Instantiator;
|
||||
use Symfony\Component\VarExporter\VarExporter;
|
||||
@@ -34,6 +35,7 @@ class ParserResultSerializationTest extends OrmFunctionalTestCase
|
||||
|
||||
/** @param Closure(ParserResult): ParserResult $toSerializedAndBack */
|
||||
#[DataProvider('provideToSerializedAndBack')]
|
||||
#[WithoutErrorHandler]
|
||||
public function testSerializeParserResultForQueryWithSqlWalker(Closure $toSerializedAndBack): void
|
||||
{
|
||||
$query = $this->_em
|
||||
|
||||
@@ -538,7 +538,9 @@ class QueryTest extends OrmFunctionalTestCase
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$data = $this->_em->createQuery('SELECT u FROM ' . CmsUser::class . ' u')
|
||||
$query = 'SELECT u FROM ' . CmsUser::class . ' u ORDER BY u.username';
|
||||
|
||||
$data = $this->_em->createQuery($query)
|
||||
->setFirstResult(1)
|
||||
->setMaxResults(2)
|
||||
->getResult();
|
||||
@@ -547,7 +549,7 @@ class QueryTest extends OrmFunctionalTestCase
|
||||
self::assertEquals('gblanco1', $data[0]->username);
|
||||
self::assertEquals('gblanco2', $data[1]->username);
|
||||
|
||||
$data = $this->_em->createQuery('SELECT u FROM ' . CmsUser::class . ' u')
|
||||
$data = $this->_em->createQuery($query)
|
||||
->setFirstResult(3)
|
||||
->setMaxResults(2)
|
||||
->getResult();
|
||||
@@ -556,7 +558,7 @@ class QueryTest extends OrmFunctionalTestCase
|
||||
self::assertEquals('gblanco3', $data[0]->username);
|
||||
self::assertEquals('gblanco4', $data[1]->username);
|
||||
|
||||
$data = $this->_em->createQuery('SELECT u FROM ' . CmsUser::class . ' u')
|
||||
$data = $this->_em->createQuery($query)
|
||||
->setFirstResult(3)
|
||||
->setMaxResults(2)
|
||||
->getScalarResult();
|
||||
|
||||
@@ -503,6 +503,21 @@ class SQLFilterTest extends OrmFunctionalTestCase
|
||||
self::assertEquals(2, count($query->getResult()));
|
||||
}
|
||||
|
||||
public function testOneToOneInverseSideWithFilter(): void
|
||||
{
|
||||
$this->loadFixtureData();
|
||||
|
||||
$conf = $this->_em->getConfiguration();
|
||||
$conf->addFilter('country', '\Doctrine\Tests\ORM\Functional\CMSCountryFilter');
|
||||
$this->_em->getFilters()->enable('country')->setParameterList('country', ['Germany'], Types::STRING);
|
||||
|
||||
$user = $this->_em->find(CmsUser::class, $this->userId);
|
||||
self::assertNotEmpty($user->address);
|
||||
|
||||
$user2 = $this->_em->find(CmsUser::class, $this->userId2);
|
||||
self::assertEmpty($user2->address);
|
||||
}
|
||||
|
||||
public function testManyToManyFilter(): void
|
||||
{
|
||||
$this->loadFixtureData();
|
||||
|
||||
@@ -5,11 +5,13 @@ declare(strict_types=1);
|
||||
namespace Doctrine\Tests\ORM\Functional\SchemaTool;
|
||||
|
||||
use Doctrine\DBAL\Platforms\SQLitePlatform;
|
||||
use Doctrine\DBAL\Schema\ComparatorConfig;
|
||||
use Doctrine\Tests\Models;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function array_filter;
|
||||
use function class_exists;
|
||||
use function implode;
|
||||
use function str_contains;
|
||||
|
||||
@@ -68,7 +70,13 @@ class DDC214Test extends OrmFunctionalTestCase
|
||||
|
||||
$fromSchema = $sm->introspectSchema();
|
||||
$toSchema = $this->getSchemaForModels(...$classes);
|
||||
$comparator = $sm->createComparator();
|
||||
|
||||
if (class_exists(ComparatorConfig::class)) {
|
||||
$comparator = $sm->createComparator((new ComparatorConfig())->withReportModifiedIndexes(false));
|
||||
} else {
|
||||
$comparator = $sm->createComparator();
|
||||
}
|
||||
|
||||
$schemaDiff = $comparator->compareSchemas($fromSchema, $toSchema);
|
||||
|
||||
$sql = $this->_em->getConnection()->getDatabasePlatform()->getAlterSchemaSQL($schemaDiff);
|
||||
|
||||
@@ -50,24 +50,58 @@ class MySqlSchemaToolTest extends OrmFunctionalTestCase
|
||||
$tool = new SchemaTool($this->_em);
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
self::assertEquals('CREATE TABLE cms_groups (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[0]);
|
||||
self::assertThat($sql[0], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE cms_groups (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE cms_groups (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertThat($sql[1], self::logicalOr(
|
||||
// DBAL 3
|
||||
self::equalTo('CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, email_id INT DEFAULT NULL, status VARCHAR(50) DEFAULT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_3AF03EC5F85E0677 (username), UNIQUE INDEX UNIQ_3AF03EC5A832C1C9 (email_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4 (see https://github.com/doctrine/dbal/pull/4777)
|
||||
self::equalTo('CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, status VARCHAR(50) DEFAULT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, email_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_3AF03EC5F85E0677 (username), UNIQUE INDEX UNIQ_3AF03EC5A832C1C9 (email_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, status VARCHAR(50) DEFAULT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, email_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_3AF03EC5F85E0677 (username), UNIQUE INDEX UNIQ_3AF03EC5A832C1C9 (email_id), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertThat($sql[2], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, INDEX IDX_7EA9409AA76ED395 (user_id), INDEX IDX_7EA9409AFE54D947 (group_id), PRIMARY KEY(user_id, group_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, INDEX IDX_7EA9409AA76ED395 (user_id), INDEX IDX_7EA9409AFE54D947 (group_id), PRIMARY KEY (user_id, group_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertThat($sql[3], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE cms_users_tags (user_id INT NOT NULL, tag_id INT NOT NULL, INDEX IDX_93F5A1ADA76ED395 (user_id), INDEX IDX_93F5A1ADBAD26311 (tag_id), PRIMARY KEY(user_id, tag_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE cms_users_tags (user_id INT NOT NULL, tag_id INT NOT NULL, INDEX IDX_93F5A1ADA76ED395 (user_id), INDEX IDX_93F5A1ADBAD26311 (tag_id), PRIMARY KEY (user_id, tag_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertThat($sql[4], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE cms_tags (id INT AUTO_INCREMENT NOT NULL, tag_name VARCHAR(50) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE cms_tags (id INT AUTO_INCREMENT NOT NULL, tag_name VARCHAR(50) DEFAULT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertEquals('CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, INDEX IDX_7EA9409AA76ED395 (user_id), INDEX IDX_7EA9409AFE54D947 (group_id), PRIMARY KEY(user_id, group_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[2]);
|
||||
self::assertEquals('CREATE TABLE cms_users_tags (user_id INT NOT NULL, tag_id INT NOT NULL, INDEX IDX_93F5A1ADA76ED395 (user_id), INDEX IDX_93F5A1ADBAD26311 (tag_id), PRIMARY KEY(user_id, tag_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[3]);
|
||||
self::assertEquals('CREATE TABLE cms_tags (id INT AUTO_INCREMENT NOT NULL, tag_name VARCHAR(50) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[4]);
|
||||
self::assertThat($sql[5], self::logicalOr(
|
||||
// DBAL 3
|
||||
self::equalTo('CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, UNIQUE INDEX UNIQ_ACAC157BA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4 (see https://github.com/doctrine/dbal/pull/4777)
|
||||
self::equalTo('CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_ACAC157BA76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_ACAC157BA76ED395 (user_id), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertThat($sql[6], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE cms_emails (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(250) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE cms_emails (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(250) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertThat($sql[7], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, INDEX IDX_F21F790FA76ED395 (user_id), PRIMARY KEY(phonenumber)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, INDEX IDX_F21F790FA76ED395 (user_id), PRIMARY KEY (phonenumber)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertEquals('CREATE TABLE cms_emails (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(250) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[6]);
|
||||
self::assertEquals('CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, INDEX IDX_F21F790FA76ED395 (user_id), PRIMARY KEY(phonenumber)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[7]);
|
||||
self::assertEquals('ALTER TABLE cms_users ADD CONSTRAINT FK_3AF03EC5A832C1C9 FOREIGN KEY (email_id) REFERENCES cms_emails (id)', $sql[8]);
|
||||
self::assertEquals('ALTER TABLE cms_users_groups ADD CONSTRAINT FK_7EA9409AA76ED395 FOREIGN KEY (user_id) REFERENCES cms_users (id)', $sql[9]);
|
||||
self::assertEquals('ALTER TABLE cms_users_groups ADD CONSTRAINT FK_7EA9409AFE54D947 FOREIGN KEY (group_id) REFERENCES cms_groups (id)', $sql[10]);
|
||||
@@ -87,7 +121,12 @@ class MySqlSchemaToolTest extends OrmFunctionalTestCase
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
self::assertCount(1, $sql);
|
||||
self::assertEquals('CREATE TABLE decimal_model (id INT AUTO_INCREMENT NOT NULL, `decimal` NUMERIC(5, 2) NOT NULL, `high_scale` NUMERIC(14, 4) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[0]);
|
||||
self::assertThat($sql[0], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE decimal_model (id INT AUTO_INCREMENT NOT NULL, `decimal` NUMERIC(5, 2) NOT NULL, `high_scale` NUMERIC(14, 4) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE decimal_model (id INT AUTO_INCREMENT NOT NULL, `decimal` NUMERIC(5, 2) NOT NULL, `high_scale` NUMERIC(14, 4) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testGetCreateSchemaSql3(): void
|
||||
@@ -98,7 +137,12 @@ class MySqlSchemaToolTest extends OrmFunctionalTestCase
|
||||
$sql = $tool->getCreateSchemaSql($classes);
|
||||
|
||||
self::assertCount(1, $sql);
|
||||
self::assertEquals('CREATE TABLE boolean_model (id INT AUTO_INCREMENT NOT NULL, booleanField TINYINT(1) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[0]);
|
||||
self::assertThat($sql[0], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE boolean_model (id INT AUTO_INCREMENT NOT NULL, booleanField TINYINT(1) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE boolean_model (id INT AUTO_INCREMENT NOT NULL, booleanField TINYINT(1) NOT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
}
|
||||
|
||||
#[Group('DBAL-204')]
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\ForeignKeyConstraintEditor;
|
||||
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
|
||||
use Doctrine\DBAL\Schema\Table as DbalTable;
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
use Doctrine\ORM\Mapping\DiscriminatorColumn;
|
||||
@@ -22,7 +24,9 @@ use Doctrine\Tests\ORM\Functional\Ticket\Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function array_map;
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use function reset;
|
||||
|
||||
class DDC2138Test extends OrmFunctionalTestCase
|
||||
@@ -42,19 +46,38 @@ class DDC2138Test extends OrmFunctionalTestCase
|
||||
|
||||
$table = $schema->getTable('users_followed_objects');
|
||||
assert($table instanceof DbalTable);
|
||||
self::assertTrue($table->columnsAreIndexed(['object_id']));
|
||||
self::assertTrue($table->columnsAreIndexed(['user_id']));
|
||||
self::assertTrue(self::columnIsIndexed($table, 'object_id'));
|
||||
self::assertTrue(self::columnIsIndexed($table, 'user_id'));
|
||||
$foreignKeys = $table->getForeignKeys();
|
||||
self::assertCount(1, $foreignKeys, 'user_id column has to have FK, but not object_id');
|
||||
|
||||
$fk = reset($foreignKeys);
|
||||
assert($fk instanceof ForeignKeyConstraint);
|
||||
self::assertEquals('users', $fk->getForeignTableName());
|
||||
|
||||
$localColumns = $fk->getLocalColumns();
|
||||
if (class_exists(ForeignKeyConstraintEditor::class)) {
|
||||
self::assertEquals('users', $fk->getReferencedTableName()->toString());
|
||||
|
||||
$localColumns = array_map(static fn (UnqualifiedName $name) => $name->toString(), $fk->getReferencingColumnNames());
|
||||
} else {
|
||||
self::assertEquals('users', $fk->getForeignTableName());
|
||||
|
||||
$localColumns = $fk->getLocalColumns();
|
||||
}
|
||||
|
||||
self::assertContains('user_id', $localColumns);
|
||||
self::assertCount(1, $localColumns);
|
||||
}
|
||||
|
||||
private static function columnIsIndexed(DbalTable $table, string $column): bool
|
||||
{
|
||||
foreach ($table->getIndexes() as $index) {
|
||||
if ($index->spansColumns([$column])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,8 +27,18 @@ class DDC2182Test extends OrmFunctionalTestCase
|
||||
$this->_em->getClassMetadata(DDC2182OptionChild::class),
|
||||
],
|
||||
);
|
||||
self::assertEquals('CREATE TABLE DDC2182OptionParent (id INT UNSIGNED NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[0]);
|
||||
self::assertEquals('CREATE TABLE DDC2182OptionChild (id VARCHAR(255) NOT NULL, parent_id INT UNSIGNED DEFAULT NULL, INDEX IDX_B314D4AD727ACA70 (parent_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB', $sql[1]);
|
||||
self::assertThat($sql[0], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE DDC2182OptionParent (id INT UNSIGNED NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE DDC2182OptionParent (id INT UNSIGNED NOT NULL, PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertThat($sql[1], self::logicalOr(
|
||||
// DBAL < 4.3
|
||||
self::equalTo('CREATE TABLE DDC2182OptionChild (id VARCHAR(255) NOT NULL, parent_id INT UNSIGNED DEFAULT NULL, INDEX IDX_B314D4AD727ACA70 (parent_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
// DBAL 4.3 (see https://github.com/doctrine/dbal/pull/6864)
|
||||
self::equalTo('CREATE TABLE DDC2182OptionChild (id VARCHAR(255) NOT NULL, parent_id INT UNSIGNED DEFAULT NULL, INDEX IDX_B314D4AD727ACA70 (parent_id), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'),
|
||||
));
|
||||
self::assertEquals('ALTER TABLE DDC2182OptionChild ADD CONSTRAINT FK_B314D4AD727ACA70 FOREIGN KEY (parent_id) REFERENCES DDC2182OptionParent (id)', $sql[2]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\DBAL\Schema\Name\Identifier;
|
||||
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
|
||||
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\Tests\ORM\Functional\DatabaseDriverTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function class_exists;
|
||||
|
||||
class DDC2387Test extends DatabaseDriverTestCase
|
||||
{
|
||||
#[Group('DDC-2387')]
|
||||
@@ -16,12 +21,23 @@ class DDC2387Test extends DatabaseDriverTestCase
|
||||
{
|
||||
$product = new Table('ddc2387_product');
|
||||
$product->addColumn('id', 'integer');
|
||||
$product->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$product->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$product->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$attributes = new Table('ddc2387_attributes');
|
||||
$attributes->addColumn('product_id', 'integer');
|
||||
$attributes->addColumn('attribute_name', 'string');
|
||||
$attributes->setPrimaryKey(['product_id', 'attribute_name']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$attributes->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('product_id')), new UnqualifiedName(Identifier::unquoted('attribute_name'))], true));
|
||||
} else {
|
||||
$attributes->setPrimaryKey(['product_id', 'attribute_name']);
|
||||
}
|
||||
|
||||
$attributes->addForeignKeyConstraint('ddc2387_product', ['product_id'], ['product_id']);
|
||||
|
||||
$metadata = $this->convertToClassMetadata([$product, $attributes], []);
|
||||
|
||||
@@ -42,14 +42,14 @@ class DDC832Test extends OrmFunctionalTestCase
|
||||
$platform = $this->_em->getConnection()->getDatabasePlatform();
|
||||
|
||||
$sm = $this->createSchemaManager();
|
||||
$sm->dropTable($platform->quoteIdentifier('TREE_INDEX'));
|
||||
$sm->dropTable($platform->quoteIdentifier('INDEX'));
|
||||
$sm->dropTable($platform->quoteIdentifier('LIKE'));
|
||||
$sm->dropTable($platform->quoteSingleIdentifier('TREE_INDEX'));
|
||||
$sm->dropTable($platform->quoteSingleIdentifier('INDEX'));
|
||||
$sm->dropTable($platform->quoteSingleIdentifier('LIKE'));
|
||||
|
||||
// DBAL 3
|
||||
if ($platform instanceof PostgreSQLPlatform && method_exists($platform, 'getIdentitySequenceName')) {
|
||||
$sm->dropSequence($platform->quoteIdentifier('INDEX_id_seq'));
|
||||
$sm->dropSequence($platform->quoteIdentifier('LIKE_id_seq'));
|
||||
$sm->dropSequence($platform->quoteSingleIdentifier('INDEX_id_seq'));
|
||||
$sm->dropSequence($platform->quoteSingleIdentifier('LIKE_id_seq'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,15 @@ class GH10450Test extends OrmTestCase
|
||||
yield 'Entity class that redeclares a protected field inherited from a base entity' => [GH10450EntityChildProtected::class];
|
||||
yield 'Entity class that redeclares a protected field inherited from a mapped superclass' => [GH10450MappedSuperclassChildProtected::class];
|
||||
}
|
||||
|
||||
public function testFieldsOfTransientClassesAreNotConsideredDuplicate(): void
|
||||
{
|
||||
$em = $this->getTestEntityManager();
|
||||
|
||||
$metadata = $em->getClassMetadata(GH10450Cat::class);
|
||||
|
||||
self::assertArrayHasKey('id', $metadata->fieldMappings);
|
||||
}
|
||||
}
|
||||
|
||||
#[ORM\Entity]
|
||||
@@ -113,3 +122,26 @@ class GH10450MappedSuperclassChildProtected extends GH10450BaseMappedSuperclassP
|
||||
#[ORM\Column(type: 'text', name: 'child')]
|
||||
protected string $field;
|
||||
}
|
||||
|
||||
abstract class GH10450AbstractEntity
|
||||
{
|
||||
#[ORM\Column(type: 'integer')]
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
protected int $id;
|
||||
}
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\InheritanceType('SINGLE_TABLE')]
|
||||
#[ORM\DiscriminatorMap(['cat' => GH10450Cat::class])]
|
||||
#[ORM\DiscriminatorColumn(name: 'type')]
|
||||
abstract class GH10450Animal extends GH10450AbstractEntity
|
||||
{
|
||||
#[ORM\Column(type: 'text', name: 'base')]
|
||||
private string $field;
|
||||
}
|
||||
|
||||
#[ORM\Entity]
|
||||
class GH10450Cat extends GH10450Animal
|
||||
{
|
||||
}
|
||||
|
||||
49
tests/Tests/ORM/Functional/Ticket/GH11524Test.php
Normal file
49
tests/Tests/ORM/Functional/Ticket/GH11524Test.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\ORM\Events;
|
||||
use Doctrine\Tests\Models\GH11524\GH11524Entity;
|
||||
use Doctrine\Tests\Models\GH11524\GH11524Listener;
|
||||
use Doctrine\Tests\Models\GH11524\GH11524Relation;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
|
||||
class GH11524Test extends OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->createSchemaForModels(
|
||||
GH11524Entity::class,
|
||||
GH11524Relation::class,
|
||||
);
|
||||
|
||||
$this->_em->getEventManager()->addEventListener(Events::postLoad, new GH11524Listener());
|
||||
}
|
||||
|
||||
public function testPostLoadCalledOnProxy(): void
|
||||
{
|
||||
$relation = new GH11524Relation();
|
||||
$relation->name = 'test';
|
||||
$this->_em->persist($relation);
|
||||
|
||||
$entity = new GH11524Entity();
|
||||
$entity->relation = $relation;
|
||||
|
||||
$this->_em->persist($entity);
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$reloadedEntity = $this->_em->find(GH11524Entity::class, $entity->id);
|
||||
|
||||
$reloadedRelation = $reloadedEntity->relation;
|
||||
|
||||
$this->assertTrue($this->isUninitializedObject($reloadedRelation));
|
||||
|
||||
$this->assertSame('fake', $reloadedRelation->getTranslation(), 'The property set by the postLoad listener must get initialized on usage.');
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
use Doctrine\DBAL\Schema\Name\Identifier;
|
||||
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
|
||||
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Doctrine\Tests\ORM\Functional\DatabaseDriverTestCase;
|
||||
|
||||
use function class_exists;
|
||||
|
||||
/**
|
||||
* Verifies that associations/columns with an inline '_id' get named properly
|
||||
*
|
||||
@@ -18,12 +23,23 @@ class GH7684Test extends DatabaseDriverTestCase
|
||||
{
|
||||
$table1 = new Table('GH7684_identity_test_table');
|
||||
$table1->addColumn('id', 'integer');
|
||||
$table1->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$table1->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$table1->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$table2 = new Table('GH7684_identity_test_assoc_table');
|
||||
$table2->addColumn('id', 'integer');
|
||||
$table2->addColumn('gh7684_identity_test_id', 'integer');
|
||||
$table2->setPrimaryKey(['id']);
|
||||
|
||||
if (class_exists(PrimaryKeyConstraint::class)) {
|
||||
$table2->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted('id'))], true));
|
||||
} else {
|
||||
$table2->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
$table2->addForeignKeyConstraint('GH7684_identity_test', ['gh7684_identity_test_id'], ['id']);
|
||||
|
||||
$metadatas = $this->convertToClassMetadata([$table1, $table2]);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilterAndIndexedRelation;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: 'Category_Master')]
|
||||
class Category
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
public int $id;
|
||||
|
||||
#[ORM\Column(type: 'string')]
|
||||
public string $name;
|
||||
|
||||
#[ORM\Column(type: 'string')]
|
||||
public string $type;
|
||||
|
||||
public function __construct(string $name, string $type)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilterAndIndexedRelation;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Query\Filter\SQLFilter;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
class CategoryTypeSQLFilter extends SQLFilter
|
||||
{
|
||||
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias): string
|
||||
{
|
||||
if ($targetEntity->getName() === Category::class) {
|
||||
return sprintf('%s.%s = %s', $targetTableAlias, $targetEntity->fieldMappings['type']->fieldName, $this->getParameter('type'));
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilterAndIndexedRelation;
|
||||
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
|
||||
final class ChangeFiltersTest extends OrmFunctionalTestCase
|
||||
{
|
||||
private const COMPANY_A = 'A';
|
||||
private const CAT_BAR = 'bar';
|
||||
private const CAT_FOO = 'foo';
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->setUpEntitySchema([
|
||||
Company::class,
|
||||
Category::class,
|
||||
]);
|
||||
}
|
||||
|
||||
private function prepareData(): void
|
||||
{
|
||||
$cat1 = new Category('cat1', self::CAT_FOO);
|
||||
$cat2 = new Category('cat2', self::CAT_BAR);
|
||||
$companyA = new Company(self::COMPANY_A, [$cat1, $cat2]);
|
||||
|
||||
$this->_em->persist($cat1);
|
||||
$this->_em->persist($cat2);
|
||||
$this->_em->persist($companyA);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
}
|
||||
|
||||
public function testIndexAliasUpdatedWithUpdatedFilter(): void
|
||||
{
|
||||
$this->prepareData();
|
||||
|
||||
$company = $this->_em->getRepository(Company::class)->findOneBy([]);
|
||||
|
||||
self::assertCount(2, $company->categories);
|
||||
self::assertEquals([self::CAT_FOO, self::CAT_BAR], $company->categories->map(static function (Category $c): string {
|
||||
return $c->type;
|
||||
})->getValues());
|
||||
|
||||
$this->_em->clear();
|
||||
$this->_em->getConfiguration()->addFilter(CategoryTypeSQLFilter::class, CategoryTypeSQLFilter::class);
|
||||
$this->_em->getFilters()->enable(CategoryTypeSQLFilter::class)->setParameter('type', self::CAT_FOO);
|
||||
|
||||
$company = $this->_em->getRepository(Company::class)->findOneBy([]);
|
||||
|
||||
self::assertCount(1, $company->categories);
|
||||
self::assertEquals([self::CAT_FOO], $company->categories->map(static function (Category $c): string {
|
||||
return $c->type;
|
||||
})->getValues());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket\SwitchContextWithFilterAndIndexedRelation;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: 'Company_Master')]
|
||||
class Company
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
#[ORM\GeneratedValue(strategy: 'AUTO')]
|
||||
public int $id;
|
||||
|
||||
#[ORM\Column(type: 'string')]
|
||||
public string $name;
|
||||
|
||||
/** @var Collection<int, Category> */
|
||||
#[ORM\ManyToMany(targetEntity: Category::class, fetch: 'EAGER', indexBy: 'type')]
|
||||
public Collection $categories;
|
||||
|
||||
/** @param Category[] $categories */
|
||||
public function __construct(string $name, array $categories)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->categories = new ArrayCollection($categories);
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,15 @@ namespace Doctrine\Tests\ORM\Hydration;
|
||||
use Doctrine\DBAL\Types\Type as DBALType;
|
||||
use Doctrine\ORM\Internal\Hydration\HydrationException;
|
||||
use Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator;
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\Tests\DbalTypes\GH8565EmployeePayloadType;
|
||||
use Doctrine\Tests\DbalTypes\GH8565ManagerPayloadType;
|
||||
use Doctrine\Tests\Mocks\ArrayResultFactory;
|
||||
use Doctrine\Tests\Models\CMS\CmsAddress;
|
||||
use Doctrine\Tests\Models\Company\CompanyPerson;
|
||||
use Doctrine\Tests\Models\Enums\Scale;
|
||||
use Doctrine\Tests\Models\Enums\Unit;
|
||||
use Doctrine\Tests\Models\GH8565\GH8565Employee;
|
||||
use Doctrine\Tests\Models\GH8565\GH8565Manager;
|
||||
use Doctrine\Tests\Models\GH8565\GH8565Person;
|
||||
@@ -155,4 +159,25 @@ class SimpleObjectHydratorTest extends HydrationTestCase
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
self::assertEquals($result[0], $expectedEntity);
|
||||
}
|
||||
|
||||
public function testNotListedValueInEnumArray(): void
|
||||
{
|
||||
$this->expectException(MappingException::class);
|
||||
$this->expectExceptionMessage('Case "unknown_case" is not listed in enum "Doctrine\Tests\Models\Enums\Unit"');
|
||||
$rsm = new ResultSetMapping();
|
||||
$rsm->addEntityResult(Scale::class, 's');
|
||||
$rsm->addFieldResult('s', 's__id', 'id');
|
||||
$rsm->addFieldResult('s', 's__supported_units', 'supportedUnits');
|
||||
$rsm->addEnumResult('s__supported_units', Unit::class);
|
||||
$resultSet = [
|
||||
[
|
||||
's__id' => 1,
|
||||
's__supported_units' => 'g,m,unknown_case',
|
||||
],
|
||||
];
|
||||
|
||||
$stmt = ArrayResultFactory::createWrapperResultFromArray($resultSet);
|
||||
$hydrator = new SimpleObjectHydrator($this->entityManager);
|
||||
$hydrator->hydrateAll($stmt, $rsm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ use Doctrine\Tests\OrmTestCase;
|
||||
use DoctrineGlobalArticle;
|
||||
use LogicException;
|
||||
use PHPUnit\Framework\Attributes\Group as TestGroup;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use ReflectionClass;
|
||||
use stdClass;
|
||||
|
||||
@@ -1074,6 +1075,7 @@ class ClassMetadataTest extends OrmTestCase
|
||||
$metadata->addLifecycleCallback('foo', 'bar');
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
public function testGettingAnFQCNForNullIsDeprecated(): void
|
||||
{
|
||||
$metadata = new ClassMetadata(self::class);
|
||||
@@ -1112,6 +1114,7 @@ class ClassMetadataTest extends OrmTestCase
|
||||
);
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
public function testDiscriminatorMapWithSameClassMultipleTimesDeprecated(): void
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/3519');
|
||||
|
||||
@@ -5,12 +5,14 @@ declare(strict_types=1);
|
||||
namespace Doctrine\Tests\ORM\Mapping;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\ORM\Mapping\DefaultQuoteStrategy;
|
||||
use Doctrine\Tests\Models\NonPublicSchemaJoins\User as NonPublicSchemaUser;
|
||||
use Doctrine\Tests\OrmTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function assert;
|
||||
use function enum_exists;
|
||||
|
||||
/**
|
||||
* Doctrine\Tests\ORM\Mapping\DefaultQuoteStrategyTest
|
||||
@@ -24,7 +26,7 @@ class DefaultQuoteStrategyTest extends OrmTestCase
|
||||
$em = $this->getTestEntityManager();
|
||||
$metadata = $em->getClassMetadata(NonPublicSchemaUser::class);
|
||||
$strategy = new DefaultQuoteStrategy();
|
||||
$platform = $this->getMockForAbstractClass(AbstractPlatform::class);
|
||||
$platform = $this->getMockForAbstractClass(AbstractPlatform::class, enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : []);
|
||||
assert($platform instanceof AbstractPlatform);
|
||||
|
||||
self::assertSame(
|
||||
|
||||
@@ -6,12 +6,14 @@ namespace Doctrine\Tests\ORM\Mapping;
|
||||
|
||||
use Doctrine\Deprecations\PHPUnit\VerifyDeprecations;
|
||||
use Doctrine\ORM\Mapping\Table;
|
||||
use PHPUnit\Framework\Attributes\WithoutErrorHandler;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class TableMappingTest extends TestCase
|
||||
{
|
||||
use VerifyDeprecations;
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
public function testDeprecationOnIndexesPropertyIsTriggered(): void
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/pull/11357');
|
||||
@@ -19,6 +21,7 @@ final class TableMappingTest extends TestCase
|
||||
new Table(indexes: []);
|
||||
}
|
||||
|
||||
#[WithoutErrorHandler]
|
||||
public function testDeprecationOnUniqueConstraintsPropertyIsTriggered(): void
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/pull/11357');
|
||||
|
||||
@@ -75,7 +75,7 @@ class ORMInvalidArgumentExceptionTest extends TestCase
|
||||
. 'persist operations for entity: stdClass@' . spl_object_id($entity1)
|
||||
. '. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity '
|
||||
. 'or configure cascade persist this association in the mapping for example '
|
||||
. '@ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem '
|
||||
. '#[ORM\ManyToOne(..., cascade: [\'persist\'])]. If you cannot find out which entity causes the problem '
|
||||
. 'implement \'baz1#__toString()\' to get a clue.',
|
||||
],
|
||||
'two entities found' => [
|
||||
@@ -94,13 +94,13 @@ class ORMInvalidArgumentExceptionTest extends TestCase
|
||||
. 'cascade persist operations for entity: stdClass@' . spl_object_id($entity1) . '. '
|
||||
. 'To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity '
|
||||
. 'or configure cascade persist this association in the mapping for example '
|
||||
. '@ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem '
|
||||
. '#[ORM\ManyToOne(..., cascade: [\'persist\'])]. If you cannot find out which entity causes the problem '
|
||||
. 'implement \'baz1#__toString()\' to get a clue.' . "\n"
|
||||
. ' * A new entity was found through the relationship \'foo2#bar2\' that was not configured to '
|
||||
. 'cascade persist operations for entity: stdClass@' . spl_object_id($entity2) . '. To solve '
|
||||
. 'this issue: Either explicitly call EntityManager#persist() on this unknown entity or '
|
||||
. 'configure cascade persist this association in the mapping for example '
|
||||
. '@ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem '
|
||||
. '#[ORM\ManyToOne(..., cascade: [\'persist\'])]. If you cannot find out which entity causes the problem '
|
||||
. 'implement \'baz2#__toString()\' to get a clue.',
|
||||
],
|
||||
'two entities found, one is stringable' => [
|
||||
@@ -114,7 +114,7 @@ class ORMInvalidArgumentExceptionTest extends TestCase
|
||||
. 'persist operations for entity: ThisIsAStringRepresentationOfEntity3'
|
||||
. '. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity '
|
||||
. 'or configure cascade persist this association in the mapping for example '
|
||||
. '@ManyToOne(..,cascade={"persist"}).',
|
||||
. '#[ORM\ManyToOne(..., cascade: [\'persist\'])].',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use Doctrine\Common\Collections\Expr\Comparison;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Driver;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\DBAL\Types\Type as DBALType;
|
||||
use Doctrine\ORM\Mapping\OneToManyAssociationMapping;
|
||||
use Doctrine\ORM\Persisters\Entity\BasicEntityPersister;
|
||||
@@ -23,6 +24,7 @@ use PHPUnit\Framework\Attributes\Group;
|
||||
use ReflectionMethod;
|
||||
|
||||
use function array_slice;
|
||||
use function enum_exists;
|
||||
|
||||
class BasicEntityPersisterTypeValueSqlTest extends OrmTestCase
|
||||
{
|
||||
@@ -65,6 +67,7 @@ class BasicEntityPersisterTypeValueSqlTest extends OrmTestCase
|
||||
->willReturn($this->createMock(Driver\Connection::class));
|
||||
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns'])
|
||||
->getMockForAbstractClass();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Doctrine\Tests\ORM\Persisters;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Driver;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\ORM\Persisters\Collection\ManyToManyPersister;
|
||||
use Doctrine\Tests\Models\ManyToManyPersister\ChildClass;
|
||||
use Doctrine\Tests\Models\ManyToManyPersister\OtherParentClass;
|
||||
@@ -15,6 +16,8 @@ use Doctrine\Tests\OrmTestCase;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function enum_exists;
|
||||
|
||||
#[CoversClass(ManyToManyPersister::class)]
|
||||
final class ManyToManyPersisterTest extends OrmTestCase
|
||||
{
|
||||
@@ -31,7 +34,7 @@ final class ManyToManyPersisterTest extends OrmTestCase
|
||||
->onlyMethods(['executeStatement', 'getDatabasePlatform'])
|
||||
->getMock();
|
||||
$connection->method('getDatabasePlatform')
|
||||
->willReturn($this->getMockForAbstractClass(AbstractPlatform::class));
|
||||
->willReturn($this->getMockForAbstractClass(AbstractPlatform::class, enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : []));
|
||||
|
||||
$parent = new ParentClass(1);
|
||||
$otherParent = new OtherParentClass(42);
|
||||
|
||||
@@ -14,6 +14,7 @@ use Doctrine\DBAL\Driver\Result;
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\DBAL\ParameterType;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Query;
|
||||
@@ -39,6 +40,7 @@ use Psr\Cache\CacheItemPoolInterface;
|
||||
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||
|
||||
use function array_map;
|
||||
use function enum_exists;
|
||||
|
||||
class QueryTest extends OrmTestCase
|
||||
{
|
||||
@@ -597,6 +599,7 @@ class QueryTest extends OrmTestCase
|
||||
->will($this->onConsecutiveCalls(...$results));
|
||||
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns'])
|
||||
->getMockForAbstractClass();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
|
||||
@@ -14,6 +14,24 @@ use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||
|
||||
final class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
{
|
||||
public function testSubqueryClonedCompletely(): void
|
||||
{
|
||||
$query = $this->createQuery('SELECT p FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p');
|
||||
$query->setParameter('dummy-param', 123);
|
||||
$query->setHint('dummy-hint', 'dummy-value');
|
||||
$query->setCacheable(true);
|
||||
|
||||
$walker = new LimitSubqueryOutputWalker($query, new Query\ParserResult(), []);
|
||||
|
||||
self::assertNotSame($query, $walker->getQuery());
|
||||
self::assertTrue($walker->getQuery()->hasHint('dummy-hint'));
|
||||
self::assertSame('dummy-value', $walker->getQuery()->getHint('dummy-hint'));
|
||||
self::assertNotSame($query->getParameters(), $walker->getQuery()->getParameters());
|
||||
self::assertInstanceOf(Query\Parameter::class, $param = $walker->getQuery()->getParameter('dummy-param'));
|
||||
self::assertSame(123, $param->getValue());
|
||||
self::assertFalse($walker->getQuery()->isCacheable());
|
||||
}
|
||||
|
||||
public function testLimitSubquery(): void
|
||||
{
|
||||
$this->assertQuerySql(
|
||||
|
||||
@@ -8,6 +8,7 @@ use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Driver;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Result;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\ORM\Decorator\EntityManagerDecorator;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
|
||||
@@ -17,6 +18,8 @@ use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||
use Doctrine\Tests\OrmTestCase;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
use function enum_exists;
|
||||
|
||||
class PaginatorTest extends OrmTestCase
|
||||
{
|
||||
private Connection&MockObject $connection;
|
||||
@@ -26,6 +29,7 @@ class PaginatorTest extends OrmTestCase
|
||||
protected function setUp(): void
|
||||
{
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns'])
|
||||
->getMockForAbstractClass();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
|
||||
@@ -5,6 +5,13 @@ declare(strict_types=1);
|
||||
namespace Doctrine\Tests\ORM\Tools;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Schema\ForeignKeyConstraintEditor;
|
||||
use Doctrine\DBAL\Schema\Index as DbalIndex;
|
||||
use Doctrine\DBAL\Schema\Index\IndexedColumn;
|
||||
use Doctrine\DBAL\Schema\Index\IndexType;
|
||||
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
|
||||
use Doctrine\DBAL\Schema\PrimaryKeyConstraintEditor;
|
||||
use Doctrine\DBAL\Schema\Table as DbalTable;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
@@ -42,8 +49,12 @@ use Doctrine\Tests\Models\NullDefault\NullDefaultColumn;
|
||||
use Doctrine\Tests\OrmTestCase;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
|
||||
use function array_map;
|
||||
use function class_exists;
|
||||
use function count;
|
||||
use function current;
|
||||
use function enum_exists;
|
||||
use function method_exists;
|
||||
|
||||
class SchemaToolTest extends OrmTestCase
|
||||
{
|
||||
@@ -65,7 +76,7 @@ class SchemaToolTest extends OrmTestCase
|
||||
$schema = $schemaTool->getSchemaFromMetadata($classes);
|
||||
|
||||
self::assertTrue($schema->hasTable('cms_users'), 'Table cms_users should exist.');
|
||||
self::assertTrue($schema->getTable('cms_users')->columnsAreIndexed(['username']), 'username column should be indexed.');
|
||||
self::assertTrue(self::columnIsIndexed($schema->getTable('cms_users'), 'username'), 'username column should be indexed.');
|
||||
}
|
||||
|
||||
public function testAttributeOptionsArgument(): void
|
||||
@@ -229,10 +240,15 @@ class SchemaToolTest extends OrmTestCase
|
||||
|
||||
self::assertTrue($schema->hasTable('first_entity'), 'Table first_entity should exist.');
|
||||
|
||||
$indexes = $schema->getTable('first_entity')->getIndexes();
|
||||
$table = $schema->getTable('first_entity');
|
||||
|
||||
self::assertTrue($table->hasIndex('primary'), 'Table should have a primary key.');
|
||||
|
||||
$primaryKey = $table->getIndex('primary');
|
||||
$indexes = $table->getIndexes();
|
||||
|
||||
self::assertCount(1, $indexes, 'there should be only one index');
|
||||
self::assertTrue(current($indexes)->isPrimary(), 'index should be primary');
|
||||
self::assertSame($primaryKey, current($indexes), 'index should be primary');
|
||||
}
|
||||
|
||||
public function testSetDiscriminatorColumnWithoutLength(): void
|
||||
@@ -272,13 +288,23 @@ class SchemaToolTest extends OrmTestCase
|
||||
self::assertTrue($schema->hasTable('joined_derived_root'));
|
||||
self::assertTrue($schema->hasTable('joined_derived_child'));
|
||||
|
||||
$rootTable = $schema->getTable('joined_derived_root');
|
||||
self::assertNotNull($rootTable->getPrimaryKey());
|
||||
self::assertSame(['keyPart1_id', 'keyPart2'], $rootTable->getPrimaryKey()->getColumns());
|
||||
if (class_exists(PrimaryKeyConstraintEditor::class)) {
|
||||
$rootTable = $schema->getTable('joined_derived_root');
|
||||
self::assertNotNull($rootTable->getPrimaryKeyConstraint());
|
||||
self::assertSame(['keyPart1_id', 'keyPart2'], array_map(static fn (UnqualifiedName $name) => $name->toString(), $rootTable->getPrimaryKeyConstraint()->getColumnNames()));
|
||||
|
||||
$childTable = $schema->getTable('joined_derived_child');
|
||||
self::assertNotNull($childTable->getPrimaryKey());
|
||||
self::assertSame(['keyPart1_id', 'keyPart2'], $childTable->getPrimaryKey()->getColumns());
|
||||
$childTable = $schema->getTable('joined_derived_child');
|
||||
self::assertNotNull($childTable->getPrimaryKeyConstraint());
|
||||
self::assertSame(['keyPart1_id', 'keyPart2'], array_map(static fn (UnqualifiedName $name) => $name->toString(), $childTable->getPrimaryKeyConstraint()->getColumnNames()));
|
||||
} else {
|
||||
$rootTable = $schema->getTable('joined_derived_root');
|
||||
self::assertNotNull($rootTable->getPrimaryKey());
|
||||
self::assertSame(['keyPart1_id', 'keyPart2'], self::getIndexedColumns($rootTable->getPrimaryKey()));
|
||||
|
||||
$childTable = $schema->getTable('joined_derived_child');
|
||||
self::assertNotNull($childTable->getPrimaryKey());
|
||||
self::assertSame(['keyPart1_id', 'keyPart2'], self::getIndexedColumns($childTable->getPrimaryKey()));
|
||||
}
|
||||
|
||||
$childTableForeignKeys = $childTable->getForeignKeys();
|
||||
|
||||
@@ -290,12 +316,21 @@ class SchemaToolTest extends OrmTestCase
|
||||
];
|
||||
|
||||
foreach ($childTableForeignKeys as $foreignKey) {
|
||||
self::assertArrayHasKey($foreignKey->getForeignTableName(), $expectedColumns);
|
||||
if (class_exists(ForeignKeyConstraintEditor::class)) {
|
||||
self::assertArrayHasKey($foreignKey->getReferencedTableName()->toString(), $expectedColumns);
|
||||
|
||||
[$localColumns, $foreignColumns] = $expectedColumns[$foreignKey->getForeignTableName()];
|
||||
[$localColumns, $foreignColumns] = $expectedColumns[$foreignKey->getReferencedTableName()->toString()];
|
||||
|
||||
self::assertSame($localColumns, $foreignKey->getLocalColumns());
|
||||
self::assertSame($foreignColumns, $foreignKey->getForeignColumns());
|
||||
self::assertSame($localColumns, array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencingColumnNames()));
|
||||
self::assertSame($foreignColumns, array_map(static fn (UnqualifiedName $name) => $name->toString(), $foreignKey->getReferencedColumnNames()));
|
||||
} else {
|
||||
self::assertArrayHasKey($foreignKey->getForeignTableName(), $expectedColumns);
|
||||
|
||||
[$localColumns, $foreignColumns] = $expectedColumns[$foreignKey->getForeignTableName()];
|
||||
|
||||
self::assertSame($localColumns, $foreignKey->getLocalColumns());
|
||||
self::assertSame($foreignColumns, $foreignKey->getForeignColumns());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,8 +344,8 @@ class SchemaToolTest extends OrmTestCase
|
||||
$schema = $schemaTool->getSchemaFromMetadata([$metadata]);
|
||||
$table = $schema->getTable('field_index');
|
||||
|
||||
self::assertEquals(['index', 'field_name'], $table->getIndex('index')->getColumns());
|
||||
self::assertEquals(['index', 'table'], $table->getIndex('uniq')->getColumns());
|
||||
self::assertEquals(['index', 'field_name'], self::getIndexedColumns($table->getIndex('index')));
|
||||
self::assertEquals(['index', 'table'], self::getIndexedColumns($table->getIndex('uniq')));
|
||||
}
|
||||
|
||||
public function testIncorrectIndexesBasedOnFields(): void
|
||||
@@ -388,8 +423,34 @@ class SchemaToolTest extends OrmTestCase
|
||||
|
||||
$tableIndex = $tableEntity->getIndex('uniq_2d81a3ed5bf54558875f7fd5');
|
||||
|
||||
self::assertTrue($tableIndex->isUnique());
|
||||
self::assertSame(['field', 'anotherField'], $tableIndex->getColumns());
|
||||
if (enum_exists(IndexType::class)) {
|
||||
self::assertSame(IndexType::UNIQUE, $tableIndex->getType());
|
||||
} else {
|
||||
self::assertTrue($tableIndex->isUnique());
|
||||
}
|
||||
|
||||
self::assertSame(['field', 'anotherField'], self::getIndexedColumns($tableIndex));
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
private static function getIndexedColumns(DbalIndex $index): array
|
||||
{
|
||||
if (method_exists(DbalIndex::class, 'getIndexedColumns')) {
|
||||
return array_map(static fn (IndexedColumn $indexedColumn) => $indexedColumn->getColumnName()->toString(), $index->getIndexedColumns());
|
||||
}
|
||||
|
||||
return $index->getColumns();
|
||||
}
|
||||
|
||||
private static function columnIsIndexed(DbalTable $table, string $column): bool
|
||||
{
|
||||
foreach ($table->getIndexes() as $index) {
|
||||
if ($index->spansColumns([$column])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use Doctrine\DBAL\Driver;
|
||||
use Doctrine\DBAL\Driver\Statement;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\ORM\EntityNotFoundException;
|
||||
use Doctrine\ORM\Exception\EntityIdentityCollisionException;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
@@ -38,6 +39,7 @@ use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use stdClass;
|
||||
|
||||
use function enum_exists;
|
||||
use function random_int;
|
||||
use function uniqid;
|
||||
|
||||
@@ -533,6 +535,7 @@ class UnitOfWorkTest extends OrmTestCase
|
||||
public function testCommitThrowOptimisticLockExceptionWhenConnectionCommitFails(): void
|
||||
{
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns'])
|
||||
->getMockForAbstractClass();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
|
||||
@@ -10,6 +10,7 @@ use Doctrine\DBAL\Platforms\MySQLPlatform;
|
||||
use Doctrine\DBAL\Platforms\OraclePlatform;
|
||||
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
|
||||
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||
use Doctrine\DBAL\Schema\NamedObject;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\DBAL\Schema\Table;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
@@ -614,7 +615,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
}
|
||||
|
||||
if (isset($this->_usedModelSets['directorytree'])) {
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteIdentifier('file'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteSingleIdentifier('file'));
|
||||
// MySQL doesn't know deferred deletions therefore only executing the second query gives errors.
|
||||
$conn->executeStatement('DELETE FROM Directory WHERE parentDirectory_id IS NOT NULL');
|
||||
$conn->executeStatement('DELETE FROM Directory');
|
||||
@@ -707,17 +708,17 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
$conn->executeStatement(
|
||||
sprintf(
|
||||
'UPDATE %s SET %s = NULL',
|
||||
$platform->quoteIdentifier('quote-address'),
|
||||
$platform->quoteIdentifier('user-id'),
|
||||
$platform->quoteSingleIdentifier('quote-address'),
|
||||
$platform->quoteSingleIdentifier('user-id'),
|
||||
),
|
||||
);
|
||||
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteIdentifier('quote-users-groups'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteIdentifier('quote-group'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteIdentifier('quote-phone'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteIdentifier('quote-user'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteIdentifier('quote-address'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteIdentifier('quote-city'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteSingleIdentifier('quote-users-groups'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteSingleIdentifier('quote-group'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteSingleIdentifier('quote-phone'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteSingleIdentifier('quote-user'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteSingleIdentifier('quote-address'));
|
||||
$conn->executeStatement('DELETE FROM ' . $platform->quoteSingleIdentifier('quote-city'));
|
||||
}
|
||||
|
||||
if (isset($this->_usedModelSets['vct_onetoone'])) {
|
||||
@@ -815,11 +816,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
$this->_em->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classNames
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
/** @throws RuntimeException */
|
||||
protected function setUpEntitySchema(array $classNames): void
|
||||
{
|
||||
if ($this->_em === null) {
|
||||
@@ -1108,7 +1105,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
{
|
||||
$schemaManager = $this->createSchemaManager();
|
||||
$platform = $this->_em->getConnection()->getDatabasePlatform();
|
||||
$tableName = $table->getQuotedName($platform);
|
||||
|
||||
if ($table instanceof NamedObject) {
|
||||
$tableName = $table->getObjectName()->toSQL($platform);
|
||||
} else {
|
||||
$tableName = $table->getQuotedName($platform);
|
||||
}
|
||||
|
||||
$this->dropTableIfExists($tableName);
|
||||
$schemaManager->createTable($table);
|
||||
|
||||
@@ -9,6 +9,7 @@ use Doctrine\DBAL\Driver;
|
||||
use Doctrine\DBAL\Driver\Result;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
|
||||
use Doctrine\DBAL\Schema\SchemaConfig;
|
||||
use Doctrine\ORM\Cache\CacheConfiguration;
|
||||
use Doctrine\ORM\Cache\CacheFactory;
|
||||
@@ -21,6 +22,7 @@ use PHPUnit\Framework\TestCase;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||
|
||||
use function enum_exists;
|
||||
use function method_exists;
|
||||
use function realpath;
|
||||
use function sprintf;
|
||||
@@ -158,6 +160,7 @@ abstract class OrmTestCase extends TestCase
|
||||
->willReturn(new SchemaConfig());
|
||||
|
||||
$platform = $this->getMockBuilder(AbstractPlatform::class)
|
||||
->setConstructorArgs(enum_exists(UnquotedIdentifierFolding::class) ? [UnquotedIdentifierFolding::UPPER] : [])
|
||||
->onlyMethods(['supportsIdentityColumns', 'createSchemaManager'])
|
||||
->getMockForAbstractClass();
|
||||
$platform->method('supportsIdentityColumns')
|
||||
|
||||
Reference in New Issue
Block a user