mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 15:02:22 +01:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17d28b5c4c | ||
|
|
a2d510c6f4 | ||
|
|
2a4ebca90e | ||
|
|
cc29ae0d36 | ||
|
|
bd4a053d29 | ||
|
|
52fbfb3785 | ||
|
|
c259371e5f | ||
|
|
dcdd58b642 | ||
|
|
7b9c53854f | ||
|
|
cdc5fe11dd | ||
|
|
69ece00564 | ||
|
|
c679d1b007 | ||
|
|
1e15b22dcb | ||
|
|
44057b4683 | ||
|
|
013df03795 | ||
|
|
2d2a34407c | ||
|
|
3303cd3b5d | ||
|
|
afcf91e839 | ||
|
|
c61a9b3b6d | ||
|
|
3aed6912a3 | ||
|
|
158605bf24 | ||
|
|
2c2ef65817 | ||
|
|
1c33a86983 | ||
|
|
310fe1cccb | ||
|
|
a67f677747 | ||
|
|
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.2.1"
|
||||
uses: "doctrine/.github/.github/workflows/coding-standards.yml@7.2.2"
|
||||
|
||||
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.2.1"
|
||||
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.2.1"
|
||||
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 }}
|
||||
|
||||
@@ -41,14 +41,14 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1.13 || ^2",
|
||||
"doctrine/coding-standard": "^9.0.2 || ^12.0",
|
||||
"doctrine/coding-standard": "^9.0.2 || ^13.0",
|
||||
"phpbench/phpbench": "^0.16.10 || ^1.0",
|
||||
"phpstan/extension-installer": "~1.1.0 || ^1.4",
|
||||
"phpstan/phpstan": "~1.4.10 || 2.0.3",
|
||||
"phpstan/phpstan-deprecation-rules": "^1 || ^2",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6",
|
||||
"psr/log": "^1 || ^2 || ^3",
|
||||
"squizlabs/php_codesniffer": "3.7.2",
|
||||
"squizlabs/php_codesniffer": "3.12.0",
|
||||
"symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0",
|
||||
"symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0",
|
||||
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -144,8 +144,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
|
||||
|
||||
@@ -166,8 +166,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
|
||||
|
||||
@@ -189,8 +189,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
|
||||
|
||||
@@ -202,8 +202,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
|
||||
@@ -446,7 +446,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.
|
||||
@@ -461,7 +461,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.
|
||||
|
||||
@@ -1426,7 +1426,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>
|
||||
|
||||
@@ -299,7 +299,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">
|
||||
|
||||
@@ -323,7 +323,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">
|
||||
@@ -431,7 +431,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.
|
||||
|
||||
@@ -17,7 +17,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">
|
||||
|
||||
@@ -103,7 +103,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">
|
||||
|
||||
|
||||
@@ -86,7 +86,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">
|
||||
|
||||
@@ -127,11 +127,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``
|
||||
@@ -268,7 +269,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">
|
||||
|
||||
|
||||
@@ -87,7 +87,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">
|
||||
|
||||
|
||||
@@ -558,7 +558,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">
|
||||
|
||||
@@ -1139,7 +1139,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">
|
||||
|
||||
@@ -1294,7 +1294,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">
|
||||
|
||||
@@ -1818,7 +1818,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">
|
||||
|
||||
|
||||
@@ -128,7 +128,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">
|
||||
|
||||
|
||||
@@ -1278,7 +1278,6 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
|
||||
/**
|
||||
* @param string $fieldName
|
||||
* @param array $cache
|
||||
* @phpstan-param array{usage?: int|null, region?: string|null} $cache
|
||||
*
|
||||
* @return int[]|string[]
|
||||
|
||||
@@ -309,7 +309,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\'])].'
|
||||
. (method_exists($entity, '__toString')
|
||||
? ''
|
||||
: ' If you cannot find out which entity causes the problem implement \''
|
||||
|
||||
@@ -1374,6 +1374,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 ';
|
||||
|
||||
@@ -378,7 +378,7 @@ EOPHP;
|
||||
$class = $entityPersister->getClassMetadata();
|
||||
|
||||
foreach ($class->getReflectionProperties() as $property) {
|
||||
if (isset($identifier[$property->name]) || ! $class->hasField($property->name) && ! $class->hasAssociation($property->name)) {
|
||||
if (isset($identifier[$property->name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -448,7 +448,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,17 +105,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,6 +49,7 @@ use Doctrine\Persistence\PropertyChangedListener;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\VarExporter\Hydrator;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function array_chunk;
|
||||
@@ -2944,6 +2945,11 @@ EXCEPTION
|
||||
|
||||
if ($this->isUninitializedObject($entity)) {
|
||||
$entity->__setInitialized(true);
|
||||
|
||||
if ($this->em->getConfiguration()->isLazyGhostObjectEnabled()) {
|
||||
// Initialize properties that have default values to their default value (similar to what
|
||||
Hydrator::hydrate($entity, (array) $class->reflClass->newInstanceWithoutConstructor());
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
! isset($hints[Query::HINT_REFRESH])
|
||||
|
||||
@@ -118,13 +118,11 @@ class ConnectionMock extends Connection
|
||||
$this->_platformMock = $platform;
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
public function getExecuteStatements(): array
|
||||
{
|
||||
return $this->_executeStatements;
|
||||
}
|
||||
|
||||
/** @return array */
|
||||
public function getDeletes(): array
|
||||
{
|
||||
return $this->_deletes;
|
||||
|
||||
31
tests/Tests/Models/GH11524/GH11524Entity.php
Normal file
31
tests/Tests/Models/GH11524/GH11524Entity.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
public $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="GH11524Relation")
|
||||
* @ORM\JoinColumn(name="relation_id", referencedColumnName="id", nullable=true)
|
||||
*
|
||||
* @var GH11524Relation|null
|
||||
*/
|
||||
public $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');
|
||||
}
|
||||
}
|
||||
50
tests/Tests/Models/GH11524/GH11524Relation.php
Normal file
50
tests/Tests/Models/GH11524/GH11524Relation.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $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';
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,11 @@ namespace Doctrine\Tests\ORM\Functional;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
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
|
||||
{
|
||||
@@ -96,6 +98,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 */
|
||||
@@ -197,6 +201,7 @@ class LifecycleCallbackTest extends OrmFunctionalTestCase
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
|
||||
$dql = <<<'DQL'
|
||||
SELECT
|
||||
@@ -214,9 +219,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);
|
||||
}
|
||||
|
||||
@@ -239,6 +244,8 @@ DQL;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
LifecycleCallbackCascader::$postLoadCallbackInvoked = false;
|
||||
|
||||
$dql = <<<'DQL'
|
||||
SELECT
|
||||
@@ -256,7 +263,7 @@ DQL;
|
||||
$result = iterator_to_array($query->iterate());
|
||||
|
||||
foreach ($result as $entity) {
|
||||
self::assertTrue($entity[0]->postLoadCallbackInvoked);
|
||||
self::assertTrue($entity[0]::$postLoadCallbackInvoked);
|
||||
self::assertFalse($entity[0]->postLoadCascaderNotNull);
|
||||
|
||||
break;
|
||||
@@ -265,7 +272,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;
|
||||
@@ -283,6 +290,7 @@ DQL;
|
||||
|
||||
$this->_em->flush();
|
||||
$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 AS e'
|
||||
@@ -291,7 +299,7 @@ DQL;
|
||||
$result = iterator_to_array($query->iterate(null, Query::HYDRATE_SIMPLEOBJECT));
|
||||
|
||||
foreach ($result as $entity) {
|
||||
self::assertTrue($entity[0]->postLoadCallbackInvoked);
|
||||
self::assertTrue($entity[0]::$postLoadCallbackInvoked);
|
||||
self::assertFalse($entity[0]->postLoadCascaderNotNull);
|
||||
|
||||
break;
|
||||
@@ -300,7 +308,7 @@ DQL;
|
||||
$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;
|
||||
@@ -325,6 +333,8 @@ DQL;
|
||||
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
LifecycleCallbackTestEntity::$postLoadCallbackInvoked = false; // Reset the tracking of the postLoad invocation
|
||||
LifecycleCallbackCascader::$postLoadCallbackInvoked = false;
|
||||
|
||||
$dql = <<<'DQL'
|
||||
SELECT
|
||||
@@ -342,9 +352,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,7 +502,7 @@ class LifecycleCallbackTestEntity
|
||||
public $postPersistCallbackInvoked = false;
|
||||
|
||||
/** @var bool */
|
||||
public $postLoadCallbackInvoked = false;
|
||||
public static $postLoadCallbackInvoked = false;
|
||||
|
||||
/** @var bool */
|
||||
public $postLoadCascaderNotNull = false;
|
||||
@@ -546,7 +556,7 @@ class LifecycleCallbackTestEntity
|
||||
/** @PostLoad */
|
||||
public function doStuffOnPostLoad(): void
|
||||
{
|
||||
$this->postLoadCallbackInvoked = true;
|
||||
self::$postLoadCallbackInvoked = true;
|
||||
$this->postLoadCascaderNotNull = isset($this->cascader);
|
||||
}
|
||||
|
||||
@@ -572,7 +582,7 @@ class LifecycleCallbackCascader
|
||||
{
|
||||
/* test stuff */
|
||||
/** @var bool */
|
||||
public $postLoadCallbackInvoked = false;
|
||||
public static $postLoadCallbackInvoked = false;
|
||||
|
||||
/** @var int */
|
||||
public $postLoadEntitiesCount = 0;
|
||||
@@ -599,7 +609,7 @@ class LifecycleCallbackCascader
|
||||
/** @PostLoad */
|
||||
public function doStuffOnPostLoad(): void
|
||||
{
|
||||
$this->postLoadCallbackInvoked = true;
|
||||
self::$postLoadCallbackInvoked = true;
|
||||
$this->postLoadEntitiesCount = count($this->entities);
|
||||
}
|
||||
|
||||
|
||||
@@ -558,7 +558,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();
|
||||
@@ -567,7 +569,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();
|
||||
@@ -576,7 +578,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();
|
||||
|
||||
@@ -537,6 +537,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();
|
||||
|
||||
@@ -51,15 +51,20 @@ class DDC1690Test extends OrmFunctionalTestCase
|
||||
$parentId = $parent->getId();
|
||||
$childId = $child->getId();
|
||||
unset($parent, $child);
|
||||
DDC1690Parent::$addPropertyChangedListenerInvoked = false;
|
||||
DDC1690Child::$addPropertyChangedListenerInvoked = false;
|
||||
|
||||
$parent = $this->_em->find(DDC1690Parent::class, $parentId);
|
||||
$child = $this->_em->find(DDC1690Child::class, $childId);
|
||||
|
||||
self::assertTrue($parent::$addPropertyChangedListenerInvoked);
|
||||
self::assertEquals(1, count($parent->listeners));
|
||||
self::assertCount(0, $child->listeners);
|
||||
$this->assertTrue($this->isUninitializedObject($child));
|
||||
self::assertFalse($child::$addPropertyChangedListenerInvoked);
|
||||
|
||||
$this->_em->getUnitOfWork()->initializeObject($child);
|
||||
|
||||
self::assertTrue($child::$addPropertyChangedListenerInvoked);
|
||||
self::assertCount(1, $child->listeners);
|
||||
unset($parent, $child);
|
||||
|
||||
@@ -106,6 +111,11 @@ class NotifyBaseEntity implements NotifyPropertyChanged
|
||||
*/
|
||||
class DDC1690Parent extends NotifyBaseEntity
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public static $addPropertyChangedListenerInvoked = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @Id
|
||||
@@ -151,11 +161,23 @@ class DDC1690Parent extends NotifyBaseEntity
|
||||
{
|
||||
return $this->child;
|
||||
}
|
||||
|
||||
public function addPropertyChangedListener(PropertyChangedListener $listener): void
|
||||
{
|
||||
self::$addPropertyChangedListenerInvoked = true;
|
||||
|
||||
parent::addPropertyChangedListener($listener);
|
||||
}
|
||||
}
|
||||
|
||||
/** @Entity */
|
||||
class DDC1690Child extends NotifyBaseEntity
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public static $addPropertyChangedListenerInvoked = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @Id
|
||||
@@ -201,4 +223,11 @@ class DDC1690Child extends NotifyBaseEntity
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
public function addPropertyChangedListener(PropertyChangedListener $listener): void
|
||||
{
|
||||
self::$addPropertyChangedListenerInvoked = true;
|
||||
|
||||
parent::addPropertyChangedListener($listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,16 +57,17 @@ class DDC2230Test extends OrmFunctionalTestCase
|
||||
$this->_em->persist($insertedAddress);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
DDC2230Address::$listener = null; // Reset the tracking state
|
||||
|
||||
$addressProxy = $this->_em->getReference(DDC2230Address::class, $insertedAddress->id);
|
||||
assert($addressProxy instanceof DDC2230Address);
|
||||
|
||||
self::assertTrue($this->isUninitializedObject($addressProxy));
|
||||
self::assertNull($addressProxy->listener);
|
||||
self::assertNull($addressProxy::$listener);
|
||||
|
||||
$this->_em->getUnitOfWork()->initializeObject($addressProxy);
|
||||
|
||||
self::assertSame($this->_em->getUnitOfWork(), $addressProxy->listener);
|
||||
self::assertSame($this->_em->getUnitOfWork(), $addressProxy::$listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,12 +103,12 @@ class DDC2230Address implements NotifyPropertyChanged
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/** @var \Doctrine\Common\PropertyChangedListener */
|
||||
public $listener;
|
||||
/** @var \Doctrine\Common\PropertyChangedListener|null */
|
||||
public static $listener;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function addPropertyChangedListener(PropertyChangedListener $listener)
|
||||
{
|
||||
$this->listener = $listener;
|
||||
self::$listener = $listener;
|
||||
}
|
||||
}
|
||||
|
||||
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.');
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ class ReflectionPropertiesGetterTest extends TestCase
|
||||
|
||||
public function testPropertyGetterIsIdempotent(): void
|
||||
{
|
||||
$getter = (new ReflectionPropertiesGetter(new RuntimeReflectionService()));
|
||||
$getter = new ReflectionPropertiesGetter(new RuntimeReflectionService());
|
||||
|
||||
self::assertSame(
|
||||
$getter->getProperties(ClassWithMixedProperties::class),
|
||||
@@ -110,7 +110,7 @@ class ReflectionPropertiesGetterTest extends TestCase
|
||||
->expects(self::atLeastOnce())
|
||||
->method('getAccessibleProperty');
|
||||
|
||||
$getter = (new ReflectionPropertiesGetter($reflectionService));
|
||||
$getter = new ReflectionPropertiesGetter($reflectionService);
|
||||
|
||||
self::assertEmpty($getter->getProperties(ClassWithMixedProperties::class));
|
||||
}
|
||||
@@ -127,7 +127,7 @@ class ReflectionPropertiesGetterTest extends TestCase
|
||||
|
||||
$reflectionService->expects(self::never())->method('getAccessibleProperty');
|
||||
|
||||
$getter = (new ReflectionPropertiesGetter($reflectionService));
|
||||
$getter = new ReflectionPropertiesGetter($reflectionService);
|
||||
|
||||
self::assertEmpty($getter->getProperties(ClassWithMixedProperties::class));
|
||||
}
|
||||
|
||||
@@ -85,7 +85,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' => [
|
||||
@@ -104,13 +104,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' => [
|
||||
@@ -124,7 +124,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\'])].',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -46,6 +46,24 @@ final class LimitSubqueryOutputWalkerTest extends PaginationTestCase
|
||||
$this->entityManager->getConnection()->setDatabasePlatform($platform);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
$query = $this->createQuery('SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a');
|
||||
|
||||
@@ -679,8 +679,6 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classNames
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function setUpEntitySchema(array $classNames): void
|
||||
|
||||
Reference in New Issue
Block a user