Compare commits

...

1348 Commits

Author SHA1 Message Date
Alexander M. Turek
dbfe47b07b Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Psalm 5.24.0 (#11467)
  PHPStan 1.11.1 (#11466)
2024-05-21 14:24:20 +02:00
Alexander M. Turek
d31aabb40c Psalm 5.24.0 (#11467) 2024-05-21 14:21:50 +02:00
Alexander M. Turek
d66884403f PHPStan 1.11.1 (#11466) 2024-05-21 13:32:25 +02:00
Alexander M. Turek
a90ee5c495 Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Test with actual lock modes (#11465)
  Backport test for Query::setLockMode() (#11463)
2024-05-21 12:52:03 +02:00
Alexander M. Turek
11270425e5 Fix failed merge (#11464) 2024-05-21 12:30:56 +02:00
Alexander M. Turek
552eae37a3 Test with actual lock modes (#11465) 2024-05-21 12:30:36 +02:00
Alexander M. Turek
ee4b03aa78 Backport test for Query::setLockMode() (#11463) 2024-05-21 12:30:16 +02:00
Alexander M. Turek
f1246d57c2 Fix return type of Query::getLockMode() (#11462)
… for DBAL 4
2024-05-21 12:30:01 +02:00
Alexander M. Turek
54c29140fa Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Bump ramsey/composer-install from 2 to 3 (#11442)
  Bump doctrine/.github from 3.0.0 to 5.0.1
  Upgrade codecov/codecov-action
2024-05-21 08:42:11 +02:00
Grégoire Paris
daa99f197b Merge pull request #11456 from prohalexey/IntegerDescriminatorInInstanceOf
Using an integer as discriminator value with ORM v3
2024-05-17 08:19:34 +02:00
Alexey Prohorov
2b04cc2e3f Using an integer as discriminator value with ORM v3
This fixes a bug that occurred when configuring integers as discriminator values and using DQL instanceOf function in the queries. Doctrine throws a type error whenever the application generates these queries.
2024-05-16 11:53:29 +03:00
Grégoire Paris
3d9af3187f Merge pull request #11425 from prohalexey/FixForIntegerDescriminatorValue
Discriminator value could be an integer
2024-05-15 11:31:09 +02:00
Alexey Prohorov
e83d8a80ba Using an integer as discriminator value with ORM v3
This fixes a bug that occurred when configuring integers as discriminator values. Doctrine throws a type error whenever the application generates queries.
2024-05-15 10:42:04 +03:00
dependabot[bot]
c5291b4de8 Bump ramsey/composer-install from 2 to 3 (#11442)
Bumps [ramsey/composer-install](https://github.com/ramsey/composer-install) from 2 to 3.
- [Release notes](https://github.com/ramsey/composer-install/releases)
- [Commits](https://github.com/ramsey/composer-install/compare/v2...v3)

---
updated-dependencies:
- dependency-name: ramsey/composer-install
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-05 23:47:43 +02:00
Grégoire Paris
029ca611f0 Use ramsey/composer-install in PHPBench workflow (#11444)
It will handle caching for us.
2024-05-05 23:38:41 +02:00
Grégoire Paris
831d86548c Merge pull request #11441 from doctrine/dependabot/github_actions/2.19.x/doctrine/dot-github-5.0.1
Bump doctrine/.github from 3.0.0 to 5.0.1
2024-05-05 23:23:39 +02:00
dependabot[bot]
f26b3b9cf9 Bump doctrine/.github from 3.0.0 to 5.0.1
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 3.0.0 to 5.0.1.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/3.0.0...5.0.1)

---
updated-dependencies:
- dependency-name: doctrine/.github
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-05 21:17:24 +00:00
Grégoire Paris
9e7715f678 Merge pull request #11439 from greg0ire/setup-dependabot
Setup Dependabot
2024-05-05 23:16:51 +02:00
Grégoire Paris
9ab84f7478 Merge pull request #11440 from greg0ire/update-codecov
Upgrade codecov/codecov-action
2024-05-05 22:56:55 +02:00
Grégoire Paris
e6bb4ef20e Upgrade codecov/codecov-action 2024-05-05 22:43:51 +02:00
Grégoire Paris
0e26e3ed50 Setup Dependabot
Targeting 2.19.x, since we want the updates to bubble up. Since
Dependabot has had no effect on doctrine/dbal yet, I suppose that means
that "dependabot.yml" must be present on the default branch.
2024-05-05 22:41:40 +02:00
Grégoire Paris
8ca99fdfdc Merge pull request #11433 from greg0ire/3.1.x
Merge 3.0.x up into 3.1.x
2024-04-30 09:14:13 +02:00
Grégoire Paris
2d8e466636 Merge remote-tracking branch 'origin/2.19.x' into 3.1.x 2024-04-30 09:00:59 +02:00
Grégoire Paris
94986af284 Merge pull request #11430 from W0rma/fix-deprecation-layer-orm-exception
Fix deprecation layer of Doctrine\ORM\ORMException
2024-04-30 08:49:54 +02:00
W0rma
ad5c8e4bdc Make test compatible with PHP 7.1 2024-04-30 08:35:06 +02:00
W0rma
c363f55ad1 Fix deprecation layer 2024-04-29 14:48:36 +02:00
Grégoire Paris
c973a62272 Merge pull request #11429 from SenseException/unused-test-group
Remove unused test group
2024-04-27 11:42:05 +02:00
Grégoire Paris
8d3446015a Merge pull request #11428 from xificurk/keep-removed-entity-in-identity-map
Prevent creation of new MANAGED entity instance by reloading REMOVED entity from database
2024-04-27 11:40:56 +02:00
Claudio Zizza
4e335f4044 Remove unused test group 2024-04-27 10:46:19 +02:00
Petr Morávek
bb36d49b38 Keep entities in identity map until the scheduled deletions are executed.
If the entity gets reloaded from database before the deletions are
executed UnitOfWork needs to be able to return the original instance in
REMOVED state.
2024-04-26 21:54:02 +02:00
Grégoire Paris
2b81a8e260 Merge pull request #11426 from nasimic/patch-1
Update association-mapping.rst
2024-04-26 21:27:07 +02:00
Nasimi Mammadov
7d3b3f28e9 Update association-mapping.rst
Changed capitalized column names to lowercase for consistency. Other occurances of column names mentioned as lowercase several times at this same page.
2024-04-26 21:24:28 +02:00
Simon Podlipsky
cbec236e8b fix: always cleanup in AbstractHydrator::toIterable() (#11101)
Previously it didn't cleanup anything as long as the iteration hasn't reached the final row.

Co-authored-by: Oleg Andreyev <oleg.andreyev@lampa.lv>
2024-04-25 10:32:40 +02:00
Grégoire Paris
306963fe79 Merge pull request #11422 from tomasz-ryba/bugfix/fetch-eager-order-by
Bugfix: respect orderBy for fetch EAGER mode
2024-04-25 00:09:43 +02:00
Tomasz Ryba
fb4578406f Respect orderBy for EAGER fetch mode
EAGER fetch mode ignores orderBy as of changes introduced with #8391

Fixes #11163
Fixes #11381
2024-04-24 22:44:16 +02:00
Grégoire Paris
bdc41e2b5e Merge pull request #11420 from tyteen4a03/patch-1
fix(docs): typo
2024-04-22 15:40:39 +02:00
Timothy Choi
90376a6431 fix(docs): typo 2024-04-22 15:30:56 +02:00
Alexander M. Turek
f79d166a4e Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Fix BIGINT validation (#11414)
  Fix templated phpdoc return type (#11407)
  [Documentation] Merging "Query Result Formats" with "Hydration Modes"
  Fix psalm errors: remove override of template type
  Update dql-doctrine-query-language.rst
  Adding `NonUniqueResultException`
  [Documentation] Query Result Formats
2024-04-15 16:20:40 +02:00
Alexander M. Turek
9c22814cfa Revert "Merge pull request #11399 from ThomasLandauer/issue-11377" (#11415)
This reverts commit cbb6c897de, reversing
changes made to 9c56071392.
2024-04-15 16:03:33 +02:00
Alexander M. Turek
b274893486 Fix BIGINT validation (#11414) 2024-04-15 15:11:10 +02:00
Grégoire Paris
e0e55dc9c5 Merge pull request #11413 from Nayte91/doc/php-version
docs: update PHP version in doc
2024-04-15 14:32:58 +02:00
Nayte
010b1e0886 docs: update PHP version in doc 2024-04-15 09:46:56 +02:00
Grégoire Paris
93eb8a1bcb Merge pull request #11408 from VincentLanglet/fix/fromMappingArray
Fix fromMappingArray definition
2024-04-04 00:20:16 +02:00
Vincent Langlet
1464827220 Fix fromMappingArray definition 2024-04-03 19:54:16 +02:00
Vincent Langlet
8709fb38b0 Fix templated phpdoc return type (#11407)
* Improve getClassMetadata phpdoc

* Update baseline
2024-04-01 12:44:58 +02:00
Grégoire Paris
cbb6c897de Merge pull request #11399 from ThomasLandauer/issue-11377
SchemaValidator: Changing mapping of BIGINT to string|int
2024-03-28 21:37:07 +01:00
Grégoire Paris
e9e60f2fbc Merge pull request #11403 from ThomasLandauer/patch-10
[Documentation] Merging "Query Result Formats" with "Hydration Modes"
2024-03-28 07:51:53 +01:00
Thomas Landauer
5f3c1dbab8 [Documentation] Merging "Query Result Formats" with "Hydration Modes"
Page: https://www.doctrine-project.org/projects/doctrine-orm/en/2.19/reference/dql-doctrine-query-language.html#query-result-formats

As announced in https://github.com/doctrine/orm/pull/11372#issue-2190613801, I merged the (mostly) identical sections.

* I changed the `const`s from `Query` to `AbstractQuery`
* I deleted this - mainly cause I didn't find a nice place for it:
    > In parentheses are the constants of the ``Query`` class which you can use with the
general-purpose method ``Query::execute(array $params = [], $hydrationMode = Query::HYDRATE_OBJECT)``.
2024-03-27 13:52:50 +01:00
Thomas Landauer
753bc16c0b SchemaValidator: Changing mapping of BIGINT to string|int 2024-03-23 14:49:02 +01:00
Grégoire Paris
6090141e0b Merge pull request #11389 from tantegerda1/2.19.x
Fix psalm errors: remove override of template type
2024-03-23 11:13:39 +01:00
Grégoire Paris
e4a6c041b5 Merge pull request #11372 from ThomasLandauer/patch-12
[Documentation] Query Result Formats
2024-03-23 10:07:42 +01:00
Ludwig Rafelsberger
c54c557e02 Fix psalm errors: remove override of template type
See https://github.com/doctrine/collections/issues/368 for the same
issue in doctrine/collections which has been fixed there.

The issue happens when using ->contains(). Running psalm emits

  > InvalidArgument - Argument 1 of Doctrine\ORM\PersistentCollection::contains
  > expects
  > TMaybeContained:fn-doctrine\common\collections\readablecollection::contains
  > as mixed, but … provided.

Solution: we should either not define @template TMaybeContained or
re-define the complete psalm docblock from ReadableCollection.

Repairing the docblock necessitates an update to the psalm baseline:
one "known issue" is no longer an issue and thus removed.
2024-03-22 11:05:00 +01:00
Thomas Landauer
46d0865339 Update dql-doctrine-query-language.rst 2024-03-21 17:55:39 +01:00
Alexander M. Turek
9c56071392 Adjust PHPBench mocks 2024-03-21 12:37:52 +01:00
Alexander M. Turek
0a1988b349 Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Set column length explicitly (#11393)
  Add missing import
  Remove unused variable (#11391)
  [Documentation] Removing "Doctrine Mapping Types" ... (#11384)
  [GH-11185] Bugfix: do not use collection batch loading for indexBy assocations. (#11380)
  Improve lazy ghost performance by avoiding self-referencing closure. (#11376)
2024-03-21 12:05:05 +01:00
Alexander M. Turek
1a5a4c674a Set column length explicitly (#11393) 2024-03-21 12:01:42 +01:00
Alexander M. Turek
95795c87a8 Add missing import 2024-03-21 10:38:59 +01:00
Alexander M. Turek
db6e702088 Remove unused variable (#11391) 2024-03-21 10:32:55 +01:00
Grégoire Paris
4175edf311 Merge pull request #11387 from valkars/enum-reflection
Fixed proxy initialization for EnumReflectionProperty
2024-03-21 10:20:42 +01:00
Valentin Karnauhov
67ac5a82da Fixed proxy initialization for EnumReflectionProperty 2024-03-21 10:54:26 +02:00
Claudio Zizza
e384978e0b Remove older versions from the docs (#11383)
To reduce Algolia operations and indexes older versions get removed
2024-03-20 23:35:25 +01:00
Thomas Landauer
5ccbc201bf [Documentation] Removing "Doctrine Mapping Types" ... (#11384)
... in favor of https://www.doctrine-project.org/projects/doctrine-dbal/en/3.8/reference/types.html#reference

Page: https://www.doctrine-project.org/projects/doctrine-orm/en/2.19/reference/basic-mapping.html#doctrine-mapping-types

As announced in https://github.com/doctrine/dbal/pull/6336#issuecomment-2003720361 , the goal is to remove this duplicated type information from ORM and replace it with a link to DBAL.

In https://github.com/doctrine/dbal/pull/6341 , I'm adding any detail which I'm deleting here to the DBAL.
2024-03-20 23:34:10 +01:00
Benjamin Eberlei
d15624f72f [GH-11185] Bugfix: do not use collection batch loading for indexBy assocations. (#11380) 2024-03-20 15:45:47 +01:00
Benjamin Eberlei
9d1a4973ae Improve lazy ghost performance by avoiding self-referencing closure. (#11376)
* Improve lazy ghost performance by avoiding self-referencing closure.

Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>

* update baselien

---------

Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
2024-03-19 09:19:25 +01:00
Grégoire Paris
55c4845d57 Merge pull request #11379 from greg0ire/3.1.x
Merge 2.19.x up into 3.1.x
2024-03-18 21:07:12 +01:00
Grégoire Paris
a38f473a92 Merge remote-tracking branch 'origin/2.19.x' into 3.1.x 2024-03-18 20:57:55 +01:00
Grégoire Paris
40a0964f06 Merge pull request #11289 from themasch/reproduce-issue-11154-composite-key-eager-fetch-one
Do not use batch loading for collections with composite identifier
2024-03-18 20:12:56 +01:00
Grégoire Paris
08a9e60ed0 Remove outdated git metadata files (#11362)
Some of it seems related to the previous documentation build system,
some of it seems related to IntelliJ.
2024-03-17 23:06:30 +01:00
Benjamin Eberlei
3e3c023c95 Switch join columns around, otherwise index doesnt match 2024-03-17 19:50:56 +01:00
Benjamin Eberlei
5e6d5c06a9 Key on fk 2024-03-17 19:43:26 +01:00
Benjamin Eberlei
1622b7877d Fix entities and mapping. 2024-03-17 18:02:11 +01:00
Benjamin Eberlei
80aae2796d Merge pull request #11373 from kaznovac/patch-3
Minor code style fix in AbstractRemoteControl
2024-03-17 17:20:01 +01:00
Marko Kaznovac
528ef40fc4 Minor code style fix in AbstractRemoteControl 2024-03-17 15:55:54 +01:00
Thomas Landauer
4b4b9b7b6f Adding NonUniqueResultException 2024-03-17 12:25:05 +01:00
Thomas Landauer
ae842259f5 [Documentation] Query Result Formats
Page: https://www.doctrine-project.org/projects/doctrine-orm/en/2.19/reference/dql-doctrine-query-language.html#query-result-formats

Follow-up of https://github.com/doctrine/orm/pull/11359

The table I suggested is probably not working, since the text for each method is too long. And what I really wanted is to make it more *scanable*. So I tried boldfacing - if this doesn't work, I'll try something else.

Questions:

1. This section here is basically the same as https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/dql-doctrine-query-language.html#hydration-modes ! So I'll try to merge them (in another PR), OK? I think the list is a better format (more scanable) - since those methods all work the same, there's no need for a full-blown code sample for each, IMO.

2. `getSingleColumnResult()` is missing.
2024-03-17 12:24:10 +01:00
Grégoire Paris
7178b9d6b7 Merge pull request #11370 from greg0ire/forgotten-array-access
Avoid another occurrence of ArrayAccess
2024-03-17 10:42:16 +01:00
Grégoire Paris
8a14eee67a Avoid another occurrence of ArrayAccess 2024-03-17 09:38:54 +01:00
Grégoire Paris
c5315f86fb Merge pull request #11368 from greg0ire/address-deprecation
Avoid array access
2024-03-17 09:02:38 +01:00
Grégoire Paris
5820bb8f49 Avoid array access
It is deprecated.
2024-03-16 23:37:00 +01:00
Benjamin Eberlei
820a0da4c1 Do not schedule batch loading for target classes with composite identifier. 2024-03-16 23:05:28 +01:00
Benjamin Eberlei
fcd02b1ee2 Cleanup tests not to use model sets. 2024-03-16 23:04:57 +01:00
Grégoire Paris
b0d07ffaba Merge pull request #11363 from greg0ire/3.1.x
Merge 2.19.x up into 3.1.x
2024-03-16 21:48:21 +01:00
Grégoire Paris
196d3a6996 Merge remote-tracking branch 'origin/2.19.x' into 3.1.x 2024-03-16 21:38:16 +01:00
Grégoire Paris
abcad6fa45 Merge pull request #11090 from dbannik/2.17.x-failed-getting-entity-with-fetch-eager
[2.17.x] Failed getting entity with fetch eager property
2024-03-16 21:23:13 +01:00
Benjamin Eberlei
1b6cf58a1a Rename tables to avoid pg related illegal table name 2024-03-16 21:08:30 +01:00
Benjamin Eberlei
6501890ab5 Static analysis enforces the extra isset() even though that just masks no sense. 2024-03-16 20:48:15 +01:00
Benjamin Eberlei
e399d21fb3 Simplify condition, improve comment on this edge case. 2024-03-16 20:41:24 +01:00
Benjamin Eberlei
16f355f0cc Remove tests for already working case as they add no value other than exploration, and we only need the regression test. 2024-03-16 20:31:09 +01:00
Grégoire Paris
94d45a036f Merge pull request #11347 from greg0ire/remove-orphan
Remove guides-specific markup
2024-03-11 21:08:16 +01:00
Grégoire Paris
9acca2252f Remove guides-specific markup
doctrine/rst-parser does not appear to support orphan metadata yet, and
renders it verbatim on the website.

Let's move this to the CI job.
2024-03-11 20:31:22 +01:00
Alexander M. Turek
716fc97b70 Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Prepare releases 2.19 and 3.1 (#11335)
2024-03-03 18:45:20 +01:00
Alexander M. Turek
a809a71aa6 Prepare releases 2.19 and 3.1 (#11335) 2024-03-03 18:43:41 +01:00
Alexander M. Turek
4617a5e310 Merge branch '2.19.x' into 3.1.x
* 2.19.x:
2024-03-03 18:03:42 +01:00
Alexander M. Turek
e77c5a3a5e Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Fix annotation
  Bump CI workflows (#11336)
  Fix SchemaTool::getSchemaFromMetadata() uniqueConstraint without a predefined name (#11314)
2024-03-03 18:03:17 +01:00
Alexander M. Turek
c3cc0fdd8c Merge branch '2.18.x' into 3.0.x
* 2.18.x:
  Fix annotation
  Bump CI workflows (#11336)
  Fix SchemaTool::getSchemaFromMetadata() uniqueConstraint without a predefined name (#11314)
2024-03-03 17:13:16 +01:00
Alexander M. Turek
bd4449c462 Merge branch '2.18.x' into 2.19.x
* 2.18.x:
  Fix annotation
2024-03-03 16:49:22 +01:00
Alexander M. Turek
e3e96745cc Fix annotation 2024-03-03 16:49:00 +01:00
Alexander M. Turek
12e0cefba1 Merge branch '2.18.x' into 2.19.x
* 2.18.x:
  Bump CI workflows (#11336)
  Fix SchemaTool::getSchemaFromMetadata() uniqueConstraint without a predefined name (#11314)
2024-03-03 16:46:50 +01:00
Alexander M. Turek
21221f73cc Bump CI workflows (#11336) 2024-03-03 16:46:12 +01:00
Rok Motaln
ab5e9e393b Fix SchemaTool::getSchemaFromMetadata() uniqueConstraint without a predefined name (#11314)
* Fix loading SchemaTool::getSchemaFromMetadata() uniqueConstraint without a name

Fixes a type miss-match exception when reading a UniqueConstraint defined on an Entity which doesn't have a predefined name.

* Fix deprecation on DBAL 3

---------

Co-authored-by: Alexander M. Turek <me@derrabus.de>
2024-03-03 16:02:48 +01:00
Alexander M. Turek
507c73c073 Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Refator array_map into simple loop for performance. (#11332)
2024-03-03 14:21:12 +01:00
Grégoire Paris
ba0ea8953b Use class from persistence package (#11330)
* Use class from persistence package

It is meant to remove duplication between the ORM and the ODM.

* Update UPGRADE.md

Co-authored-by: Steve Todd <stodd@mashbo.com>

---------

Co-authored-by: Alexander M. Turek <me@derrabus.de>
Co-authored-by: Steve Todd <stodd@mashbo.com>
2024-03-03 13:08:37 +01:00
Benjamin Eberlei
e62571c8f4 Refator array_map into simple loop for performance. (#11332) 2024-03-02 23:11:11 +01:00
Alexander M. Turek
53763d432b Merge branch '2.19.x' into 3.1.x
* 2.19.x:
2024-03-01 10:57:47 +01:00
Alexander M. Turek
154920a0b3 Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Psalm 5.22.2 (#11326)
2024-03-01 10:56:28 +01:00
Alexander M. Turek
b8d0a85017 Merge branch '2.18.x' into 3.0.x
* 2.18.x:
  Psalm 5.22.2 (#11326)
2024-03-01 10:51:50 +01:00
Alexander M. Turek
98f9de2af6 Merge branch '2.18.x' into 2.19.x
* 2.18.x:
  Psalm 5.22.2 (#11326)
2024-03-01 10:48:12 +01:00
Alexander M. Turek
52a6a21387 Psalm 5.22.2 (#11326) 2024-03-01 10:47:18 +01:00
Alexander M. Turek
cb497826be Bump Doctrine Collections to 2.2 (#11325) 2024-03-01 09:27:30 +01:00
Alexander M. Turek
ba0d3842a9 Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Use enum_exists() for enums
2024-03-01 08:56:20 +01:00
Alexander M. Turek
bf49055a1f Use enum_exists() for enums 2024-03-01 08:56:07 +01:00
Alexander M. Turek
29e1935c65 Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Remove PHP 7 workarounds (#11324)
2024-03-01 08:51:50 +01:00
Alexander M. Turek
694413a888 Remove PHP 7 workarounds (#11324) 2024-03-01 08:51:21 +01:00
Alexander M. Turek
33e02b2796 Merge branch '2.19.x' into 3.1.x
* 2.19.x:
2024-02-29 17:17:59 +01:00
Alexander M. Turek
26f7588479 Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  PHPStan 1.10.59 (#11320)
  Address deprecations from Collection 2.2 (#11315)
  Fix sql walker phpdoc
2024-02-29 17:17:42 +01:00
Alexander M. Turek
20a6efdff6 Merge branch '2.18.x' into 3.0.x
* 2.18.x:
  PHPStan 1.10.59 (#11320)
2024-02-29 16:52:42 +01:00
Alexander M. Turek
83c81f6c41 Merge branch '2.18.x' into 2.19.x
* 2.18.x:
  PHPStan 1.10.59 (#11320)
2024-02-29 16:48:49 +01:00
Alexander M. Turek
4fc8629414 PHPStan 1.10.59 (#11320) 2024-02-29 16:47:35 +01:00
Grégoire Paris
791667a9e4 Merge pull request #11317 from doctrine/2.18.x
Merge 2.18.x up into 2.19.x
2024-02-28 23:05:01 +01:00
Grégoire Paris
95da667862 Merge remote-tracking branch 'origin/2.18.x' into 3.0.x 2024-02-28 22:57:35 +01:00
Alexander M. Turek
feb27f00c1 Address deprecations from Collection 2.2 (#11315) 2024-02-27 17:37:52 +01:00
Grégoire Paris
c02ddd692f Merge pull request #11312 from greg0ire/3.1.x
Merge 3.0.x up into 3.1.x
2024-02-26 20:53:44 +01:00
Grégoire Paris
151a3fba9d Merge remote-tracking branch 'origin/3.0.x' into 3.1.x 2024-02-26 20:39:59 +01:00
Grégoire Paris
b187bc8588 Merge pull request #11308 from greg0ire/throw-instead-of-assert
Throw a full-fledged exception on invalid call
2024-02-26 20:38:49 +01:00
Grégoire Paris
1e056842fe Merge pull request #11310 from greg0ire/3.1.x
Merge 2.19.x up into 3.1.x
2024-02-26 20:38:36 +01:00
Grégoire Paris
ebb0c67ecc Merge remote-tracking branch 'origin/2.19.x' into 3.1.x 2024-02-26 08:48:34 +01:00
Grégoire Paris
abd9186d00 Merge pull request #11309 from greg0ire/deprecate-invalid-call
Deprecate invalid method call
2024-02-26 08:45:50 +01:00
Grégoire Paris
719d007a81 Merge pull request #11298 from VincentLanglet/sqlWalkerPhpdoc
Fix sqlWalker::walkSimpleArithmeticExpression phpdoc
2024-02-26 08:21:47 +01:00
Grégoire Paris
08d3f72755 Deprecate invalid method call
`getAssociationMappedByTargetField()` returns `null` when called with
the owning side of an association.
This is undocumented and wrong because the phpdoc advertises a string as
a return type.

Instead, callers should ensure they are calling that method with an
inverse side.

Closes #11250
2024-02-25 22:09:47 +01:00
Grégoire Paris
3f7a3333ad Throw a full-fledged exception on invalid call
In 2.x, getAssociationMappedByTargetField() used to return null when
called with the owning side of an association.
That was undocumented and wrong because the phpdoc advertises a string
as a return type.

In 6ce0cf4a3d, I wrongly assumed that
nobody would be calling this method with the owning side of an
association.

Let us throw a full fledged exception and advertise the proper way of
avoiding this situation.

Closes #11250
2024-02-25 21:49:03 +01:00
Grégoire Paris
2a8802af12 Merge pull request #11305 from doctrine/typo
Remove extra word
2024-02-25 13:20:55 +01:00
Grégoire Paris
9cc11d2541 Remove extra word 2024-02-25 11:20:44 +01:00
Grégoire Paris
ee5b2ce5b0 Merge pull request #11294 from greg0ire/sa-fqcn
Translate comment into code and annotations
2024-02-25 10:01:27 +01:00
Grégoire Paris
d54c9678d0 Deprecate passing null to ClassMetadata::fullyQualifiedClassName()
It can easily be avoided by the only caller.
2024-02-25 09:31:02 +01:00
Grégoire Paris
859e6af972 Translate comment into code and annotations
The phpdoc comment for the return type of
ClassMetadata::fullyQualifiedClassName() says that the return type will
be null if the input value is null. I have made it more precise by
using "if and only if", made the null check more strict and translated
that into template annotations. Also, since we say we return a
class-string, I've asserted that.
2024-02-24 22:13:13 +01:00
Grégoire Paris
8c3c9f115d Merge pull request #11303 from doctrine/3.0.x
Merge 3.0.x up into 3.1.x
2024-02-24 21:21:41 +01:00
Grégoire Paris
3907872046 Merge pull request #11302 from greg0ire/3.0.x
Merge 2.18.x up into 3.0.x
2024-02-24 21:03:34 +01:00
Grégoire Paris
779781173a Merge pull request #11301 from doctrine/2.18.x
Merge 2.18.x up into 2.19.x
2024-02-24 20:51:45 +01:00
Grégoire Paris
54cd70002c Merge remote-tracking branch 'origin/2.18.x' into 3.0.x 2024-02-24 20:47:36 +01:00
Grégoire Paris
76c4539ffa Merge pull request #11293 from greg0ire/wrong-type
Remove wrong annotation about return type
2024-02-24 13:05:08 +01:00
Vincent Langlet
0f8d193512 Fix sql walker phpdoc 2024-02-23 15:11:15 +01:00
Grégoire Paris
cc314d0fb7 Remove wrong annotation about return type
Although this method is guaranteed to return either null or something
that can be used as a fully qualified class name, it never actually
checks that the class actually exists. Adding such a check breaks
several tests, including some that expect a exceptions at some later
points in the execution.
2024-02-22 23:14:52 +01:00
Alexander M. Turek
2df4d75565 Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Test different ways of settings query parameters
  Be less restrictive in DiscriminatorColumnMapping phpdoc (#11226)
  Allow (Array)ParameterType in QueryBuilder
2024-02-22 13:26:11 +01:00
Alexander M. Turek
dc21ab63ac Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Backport QueryParameterTest (#11288)
2024-02-22 13:25:30 +01:00
Alexander M. Turek
2a250b5814 Merge branch '2.18.x' into 3.0.x
* 2.18.x:
  Backport QueryParameterTest (#11288)
2024-02-22 13:23:53 +01:00
Alexander M. Turek
c9c493b2fe Merge branch '2.18.x' into 2.19.x
* 2.18.x:
  Backport QueryParameterTest (#11288)
2024-02-22 13:23:21 +01:00
Alexander M. Turek
e6eef1a97d Backport QueryParameterTest (#11288) 2024-02-22 13:22:44 +01:00
Mark Schmale
8d4718f875 provides a test case for github issue 11154
After 2.17 (some?) EAGER fetched OneToMany associations stopped working, if they have multiple join columns. Loads for these associations will trigger a `MessingPositionalParameter` exception "Positional parameter at index 1 does not have a bound value".

This test case should reproduce this issue, so it can be fixed.
2024-02-22 10:58:50 +01:00
Alexander M. Turek
44fa5d340a Merge pull request #11287 from derrabus/bugfix/parameter-types
Allow (Array)ParameterType in QueryBuilder
2024-02-22 09:31:34 +01:00
Alexander M. Turek
708146bbbc Test different ways of settings query parameters 2024-02-22 09:19:39 +01:00
Vincent Langlet
a5bf9bb96a Be less restrictive in DiscriminatorColumnMapping phpdoc (#11226)
* Be less restrictive in params

* Allow null options

* Simplify expression

* Fix ci

* Add support for null
2024-02-22 09:12:39 +01:00
Hanish Singla
3eace16e85 Allow (Array)ParameterType in QueryBuilder 2024-02-22 00:01:05 +01:00
Grégoire Paris
e4c27092cd Merge pull request #11276 from greg0ire/no-cast-filelock
Remove implicit casts in FileLock.php
2024-02-21 22:59:47 +01:00
Grégoire Paris
adadf1fb90 Do not implicitly cast glob's return type
The comment above mentions that on some platforms, it might return
false, and this is why there is a check in the first place. Let us do
exactly what is mentioned in the comment.
2024-02-21 22:36:01 +01:00
Grégoire Paris
380b5b62ef Do not cast file_put_contents's return type
If $lock->value was an empty string, this would fix a bug, but it never
is, it is a uniqid-generated string.
2024-02-21 22:35:38 +01:00
Grégoire Paris
a0e7a59572 Do not implicitly cast getLockTime()'s return type
This fixes a bug for files last modified on 1970-01-01 00:00:00, so… not
worth backporting IMO.
2024-02-21 22:35:38 +01:00
Grégoire Paris
fb6c0c1d8b Do not implicitly cast getLockContent()'s return value
Lock files are supposed to contain uniqid()-generated values, so they
cannot be falsy strings, but if they did, this would fix a bug.
2024-02-21 22:35:36 +01:00
Alexander M. Turek
fcf1116e33 Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Remove broken assertion from DateAddFunction and DateSubFunction (#11243)
  Remove unused trait
  [Documentation] Adding link to Postgres upgrade article (#11257)
  fix: support array-type arg in QB variadic calls (#11242)
2024-02-21 19:28:15 +01:00
Alexander M. Turek
78dc63df27 Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Fix Static Analysis folder reference (#11281)
  docs: recommend safer way to disable logging (#11269)
  Remove unused baseline entries
  Treat '0' as a legitimate trim char
  Add type field mapper documentation to the sidebar
  Mark document as orphan
  Use correction sectionauthor syntax
  Make docs valid according to guides 0.3.3 (#11252)
2024-02-21 19:28:06 +01:00
Alexander M. Turek
bc5efd4bfe Merge branch '2.18.x' into 3.0.x
* 2.18.x:
  Fix Static Analysis folder reference (#11281)
  docs: recommend safer way to disable logging (#11269)
  Remove unused baseline entries
  Treat '0' as a legitimate trim char
2024-02-21 18:54:21 +01:00
Alexander M. Turek
c0dfba2ef3 Merge branch '2.18.x' into 2.19.x
* 2.18.x:
  Fix Static Analysis folder reference (#11281)
  docs: recommend safer way to disable logging (#11269)
  Remove unused baseline entries
  Treat '0' as a legitimate trim char
2024-02-21 18:52:54 +01:00
Karoly Gossler
0efac09141 Fix Static Analysis folder reference (#11281) 2024-02-21 18:51:21 +01:00
Ondřej Mirtes
b6b4cbcb93 Remove broken assertion from DateAddFunction and DateSubFunction (#11243)
* Remove wrong asserts in DATE_ADD and DATE_SUB query AST function handlers

* Require DBAL 3.8.2
2024-02-20 20:29:56 +01:00
Grégoire Paris
b1f553eba3 Merge pull request #11272 from greg0ire/sa-attach-entity-listener
Improve static analysis on AttachEntityListenersListener
2024-02-20 08:14:13 +01:00
Grégoire Paris
0c4aac5a35 Merge pull request #11275 from greg0ire/sa-inversed-by
Account for inversedBy being a non-falsy-string or null
2024-02-20 08:13:34 +01:00
Grégoire Paris
e0081b59be Account for inversedBy being a non-falsy-string or null
It is supposed to hold the name of a PHP property, and those cannot be
falsy strings.
2024-02-20 07:54:19 +01:00
Grégoire Paris
4bd574daee Improve static analysis on AttachEntityListenersListener
$listenerCallback is supposed to be a method name, so it is safe to
require it is not a falsy string.
2024-02-19 09:36:41 +01:00
Grégoire Paris
efb6cebd41 Merge pull request #11270 from greg0ire/fix-trim-bug
Treat '0' as a legitimate trim char
2024-02-18 23:53:25 +01:00
Grégoire Paris
e4769d3191 docs: recommend safer way to disable logging (#11269)
* Remove trailing newlines

* Recommend safer way to disable logging

Resetting the middlewares on the configuration object will only work if
the connection object hasn't been built from that configuration object
yet. Instead, people should find the logger bound to the logging
middleware and disable it.
2024-02-18 15:51:05 +01:00
Grégoire Paris
cf408ad9ae Remove unused baseline entries 2024-02-18 12:26:18 +01:00
Grégoire Paris
7c29078051 Treat '0' as a legitimate trim char
Because of a loose comparison, it was not.
2024-02-18 11:34:10 +01:00
Grégoire Paris
d5ba106803 Merge pull request #11268 from greg0ire/3.0.x
Merge 2.18.x up into 3.0.x
2024-02-17 21:37:33 +01:00
Grégoire Paris
b59189ab48 Merge pull request #11267 from doctrine/2.18.x
Merge 2.18.x up into 2.19.x
2024-02-17 20:00:05 +01:00
Grégoire Paris
f9a4adc8ab Merge remote-tracking branch 'origin/2.18.x' into 3.0.x 2024-02-17 19:59:26 +01:00
Grégoire Paris
401a0c4fe9 Merge pull request #11266 from greg0ire/more-valid-docs
More valid docs
2024-02-17 19:57:34 +01:00
Grégoire Paris
dba9d72b2d Add type field mapper documentation to the sidebar 2024-02-17 15:10:28 +01:00
Grégoire Paris
fe0647053a Mark document as orphan
It is here for backward compatibilty reasons.
2024-02-17 15:06:46 +01:00
Grégoire Paris
7b3db4a037 Use correction sectionauthor syntax 2024-02-17 14:59:24 +01:00
Grégoire Paris
6672aaf165 Merge pull request #11265 from greg0ire/remove-unneeded-verify-depr
Remove unused trait
2024-02-17 14:55:10 +01:00
Grégoire Paris
aa3b331cae Remove unused trait 2024-02-17 11:14:47 +01:00
Dmitry Bannik
e5e3166747 #11090 - Fix obtaining an identifier in cases where the hydration has not yet fully completed on eagerLoadCollections 2024-02-16 12:57:23 +03:00
Thomas Landauer
3918dcfb42 [Documentation] Adding link to Postgres upgrade article (#11257)
* [Documentation] Adding link to Postgres upgrade article

* Update UPGRADE.md

* Update UPGRADE.md
2024-02-15 22:12:57 +01:00
Alexander M. Turek
6290747bf9 Validate more variadic parameters (#11261) 2024-02-14 00:33:12 +01:00
Alexander M. Turek
b6f4220493 Throw if a variadic parameter contains unexpected named arguments (#11260) 2024-02-13 18:28:17 +01:00
Grégoire Paris
bfb033fe3c Merge pull request #11256 from greg0ire/3.0.x
Merge 2.18.x up into 3.0.x
2024-02-13 12:07:29 +01:00
Grégoire Paris
afbf293c94 Merge pull request #11255 from doctrine/2.18.x
Merge 2.18.x up into 2.19.x
2024-02-13 12:07:19 +01:00
Grégoire Paris
bf86155dc2 Merge remote-tracking branch 'origin/2.18.x' into 3.0.x 2024-02-13 11:29:26 +01:00
Grégoire Paris
1d218bae30 Make docs valid according to guides 0.3.3 (#11252) 2024-02-12 23:46:09 +01:00
Simon Podlipsky
9acc70d5b8 fix: support array-type arg in QB variadic calls (#11242) 2024-02-09 15:23:22 +01:00
Alexander M. Turek
b7860c782b Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Remove references to deprecated constants from Lexer (#11234)
2024-02-07 15:43:24 +01:00
Alexander M. Turek
7baef1e120 Remove references to deprecated constants from Lexer (#11234) 2024-02-07 15:39:20 +01:00
Alexander M. Turek
9a24ce5fad Merge branch '2.19.x' into 3.1.x
* 2.19.x:
  Add TokenType class (#11228)
2024-02-07 14:21:22 +01:00
Alexander M. Turek
9fcb8f1305 Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Revert "Merge pull request #11229 from greg0ire/add-columns"
  Add columns for 3.1.x and 4.0x
  Update version ORM from 2 to 3 in docs (#11221)
  Clean up outdated sentence (#11224)
  Update README.md
  Point link to correct upgrade guide (#11220)
  Ignore subclasses without discriminatorValue when generating discriminator column condition SQL (#11200)
  Update branches in README
2024-02-07 13:48:24 +01:00
Alexander M. Turek
5a40b99e11 Merge branch '2.18.x' into 3.0.x
* 2.18.x:
  Point link to correct upgrade guide (#11220)
  Ignore subclasses without discriminatorValue when generating discriminator column condition SQL (#11200)
  Update branches in README
2024-02-07 13:44:56 +01:00
Karoly Gossler
5049b615c5 Add TokenType class (#11228)
* Add TokenType class
Co-authored-by: Alexander M. Turek <me@derrabus.de>

* Deprecated Lexer constants in favour of TokenType

* Replace all Lexer::T_ occurrences with TokenType::T_

* Add upgrade note

* Fixed import Lexer => TokenType

* Fixed deprecation phpdoc

* Replaced int value with matching constant of TokenType

* Update src/Query/Lexer.php

---------

Co-authored-by: Alexander M. Turek <me@derrabus.de>
2024-02-07 13:31:08 +01:00
Alexander M. Turek
94144e1227 Revert "Merge pull request #11229 from greg0ire/add-columns"
This reverts commit 599dd58fe1, reversing
changes made to 1854ce2d32.
2024-02-07 09:36:32 +01:00
Grégoire Paris
599dd58fe1 Merge pull request #11229 from greg0ire/add-columns
Add columns for 3.1.x and 4.0x
2024-02-07 07:56:20 +01:00
Grégoire Paris
aff543a4ff Add columns for 3.1.x and 4.0x 2024-02-06 23:12:13 +01:00
Andrey Bolonin
1854ce2d32 Update version ORM from 2 to 3 in docs (#11221) 2024-02-06 07:09:30 +01:00
Benjamin Morel
b00f0c258e Clean up outdated sentence (#11224)
The static create() method is gone in version 3
2024-02-05 22:58:19 +01:00
Grégoire Paris
13a79b068c Merge pull request #11222 from andreybolonin/patch-3
Update README.md
2024-02-05 08:36:56 +01:00
Andrey Bolonin
27c9e9cab3 Update README.md 2024-02-05 09:31:22 +03:00
Alexander M. Turek
1051817d92 Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Bump dependencies in the "getting started" docs page (#11219)
  DoctrineSetup was renamed to ORMSetup (#11218)
2024-02-04 17:45:24 +01:00
Grégoire Paris
40fbbf4429 Point link to correct upgrade guide (#11220) 2024-02-04 17:41:45 +01:00
Alexander M. Turek
00ed2ca991 Bump dependencies in the "getting started" docs page (#11219) 2024-02-04 17:40:24 +01:00
Alexander M. Turek
54b7ad2073 DoctrineSetup was renamed to ORMSetup (#11218) 2024-02-04 17:40:04 +01:00
Alexander M. Turek
517d038e5b Merge branch '3.0.x' into 3.1.x
* 3.0.x:
  Switch back to stable dependencies (#11210)
  Update branch metadata
2024-02-04 11:49:25 +01:00
Grégoire Paris
3db79ebbf3 Merge pull request #11214 from greg0ire/followup-array-access
Replace more occurrences of array access
2024-02-04 00:16:01 +01:00
Michael Skvortsov
6f98147d09 Ignore subclasses without discriminatorValue when generating discriminator column condition SQL (#11200)
After commit 4e8e3ef30b when `\Doctrine\ORM\Query\SqlWalker` generates dicsriminator column condition SQL (method `\Doctrine\ORM\Query\SqlWalker::generateDiscriminatorColumnConditionSQL`) it adds an empty string to the list of possible values if the inheritance hierarchy contains a non-root abstract class. 

When the discriminator column is implemented with a custom type in PostgreSQL (equivalent of Enum) the query fails because the type cannot have a value of an empty string. It boils down to the fact that `\Doctrine\ORM\Mapping\ClassMetadataInfo::$subClasses` contains an abstract class and in its Metadata the value of `\Doctrine\ORM\Mapping\ClassMetadataInfo::$discriminatorValue` is `null`.

#### Previous behavior

In version 2.14.1 `\Doctrine\ORM\Mapping\ClassMetadataInfo::$subClasses` does not contain an abstract class.

Fixes #11199, fixes #11177, fixes #10846.
---------

Co-authored-by: Michael Skvortsov <michael.skvortsov@eleving.com>
Co-authored-by: Matthias Pigulla <mp@webfactory.de>
2024-02-04 00:11:40 +01:00
Grégoire Paris
a2faeb9a26 Replace more occurrences of array access
Not sure how I missed those.
2024-02-03 23:56:59 +01:00
Grégoire Paris
3764ebf7a3 Merge pull request #11212 from greg0ire/fix-grammar
Follow up on array access deprecation
2024-02-03 23:50:27 +01:00
Grégoire Paris
a7d5adb3ce Migrate more occurrences of array access 2024-02-03 23:07:27 +01:00
Grégoire Paris
6f507c322a Fix grammar issue in upgrade guide 2024-02-03 23:01:56 +01:00
Grégoire Paris
54013671a7 Merge pull request #11211 from greg0ire/deprecate-array-access
Deprecate array access
2024-02-03 22:50:38 +01:00
Grégoire Paris
f5dea25b6c Deprecate array access
We now have proper value objects with properties for everything we need.
2024-02-03 22:26:56 +01:00
Alexander M. Turek
7527b788de Switch back to stable dependencies (#11210) 2024-02-03 21:24:40 +01:00
Grégoire Paris
cfadb5499d Merge pull request #11207 from derrabus/chore/readme
Update branches in README
2024-02-03 20:06:12 +01:00
Grégoire Paris
e52bc846f0 Merge pull request #11209 from greg0ire/update-branch-metdata
Update branch metadata
2024-02-03 20:00:29 +01:00
Alexander M. Turek
9ce9ae2818 Update branches in README 2024-02-03 19:43:49 +01:00
Grégoire Paris
f259754b7c Update branch metadata 2024-02-03 19:40:21 +01:00
Alexander M. Turek
3bc2cb6b15 Merge branch '2.19.x' into 3.0.x
* 2.19.x:
  Update branch metadata
2024-02-03 18:45:55 +01:00
Grégoire Paris
fdb9d44538 Merge pull request #11206 from greg0ire/update-branch-metdata
Update branch metadata
2024-02-03 18:37:27 +01:00
Grégoire Paris
a9fcaf1d18 Update branch metadata 2024-02-03 18:35:43 +01:00
Grégoire Paris
5b8b5f28f5 Run Rector on the source code (#11205) 2024-02-03 17:50:09 +01:00
Grégoire Paris
2e155e98a7 Merge pull request #11202 from mpdude/mergeup-2.18.x-3.0.x
Merge 2.18.x up into 3.0.x
2024-02-01 17:18:17 +01:00
Matthias Pigulla
c7a91a459c Fix Psalm complaints after merge-up 2024-02-01 09:50:15 +01:00
Matthias Pigulla
1df03f21e6 Write LimitSubqueryOutputWalkerTest in a way that is portable between DBAL 3 and 4 2024-02-01 09:40:04 +01:00
Matthias Pigulla
09f0966ad6 Fix CS after merge-up 2024-01-31 22:34:35 +01:00
Matthias Pigulla
da6c6f7045 Merge remote-tracking branch 'origin/2.18.x' into 3.0.x
Conflicts:
	phpstan-dbal2.neon
	phpstan-persistence2.neon
	phpstan.neon
	psalm-baseline.xml
	psalm.xml
	src/Persisters/Entity/BasicEntityPersister.php
	src/Query/Exec/MultiTableUpdateExecutor.php
	src/Utility/LockSqlHelper.php
	tests/Tests/ORM/Functional/Locking/LockTest.php
	tests/Tests/ORM/Tools/Pagination/LimitSubqueryOutputWalkerTest.php
2024-01-31 22:28:40 +01:00
Grégoire Paris
f2176a9ce5 Merge pull request #11201 from mpdude/merge-up-217-218
Merge 2.17.x up into 2.18.x
2024-01-31 16:53:12 +01:00
Matthias Pigulla
9a6ff66c5e Merge remote-tracking branch 'origin/2.17.x' into 2.18.x 2024-01-31 15:41:59 +01:00
Grégoire Paris
f58984c43f Merge pull request #11198 from jwage/port-lock-sql-changes
Fix calls to removed lock methods (#11061)
2024-01-31 08:50:41 +01:00
Alexander M. Turek
79c7c5087e Fix calls to removed lock methods (#11061) 2024-01-30 15:39:35 -06:00
Grégoire Paris
12c4560f1d Merge pull request #11197 from mpdude/update-limit-subquery-output-walker-test
Cover limit/offset values in `LimitSubqueryOutputWalkerTest`
2024-01-30 11:26:54 +01:00
Matthias Pigulla
152ebd756c Cover limit/offset values in LimitSubqueryOutputWalkerTest
This will help to make sure we don't lose those parts of the SQL when working on #11188.
2024-01-30 09:02:43 +01:00
Grégoire Paris
8845b6de0f Merge pull request #11195 from greg0ire/more-specific-type
Use a more specific type for getSqlStatements()
2024-01-30 08:58:52 +01:00
Grégoire Paris
e110941f9d Use a more specific type for getSqlStatements()
It is strictly beneficial for the Psalm baseline.
2024-01-29 21:07:12 +01:00
Grégoire Paris
fd8d981f30 Merge pull request #11193 from greg0ire/3.0.x
Merge 2.18.x up into 3.0.x
2024-01-28 17:34:45 +01:00
Grégoire Paris
db4d00a58f Merge remote-tracking branch 'origin/2.18.x' into 3.0.x 2024-01-28 16:59:59 +01:00
Grégoire Paris
5b5b56d83a Merge pull request #11190 from doctrine/2.17.x-merge-up-into-2.18.x_5AQ0zJbx
Merge release 2.17.4 into 2.18.x
2024-01-28 16:54:18 +01:00
Grégoire Paris
a9c45a37ff Merge remote-tracking branch 'origin/2.17.x' into 2.17.x-merge-up-into-2.18.x_5AQ0zJbx 2024-01-28 16:41:34 +01:00
Grégoire Paris
82533af893 Merge pull request #11191 from greg0ire/ignore-depr
Ignore deprecations handled in next major
2024-01-28 16:40:46 +01:00
Grégoire Paris
b988137378 Ignore deprecations handled in next major
These deprecations have been handled on 4.0.x in
https://github.com/doctrine/orm/pull/11061, it is safe to ignore them.
2024-01-28 16:30:02 +01:00
Grégoire Paris
ccfc97c32f Merge pull request #11187 from jwage/remove-xml-validation-disabling-deprecation
Remove XML validation disabling deprecation.
2024-01-26 20:41:16 +01:00
Grégoire Paris
1a5942a4d9 Merge pull request #11165 from jwage/allow-xml-validation-disable
Allow XML validation to be disabled but keep it enabled by default.
2024-01-26 20:39:27 +01:00
Jonathan H. Wage
282b8fbfe8 Move expectException call before line that triggers exception (best practice) 2024-01-26 10:00:16 -06:00
Jonathan H. Wage
d386b43be3 Remove XML validation disabling deprecation. 2024-01-26 09:59:03 -06:00
Jonathan H. Wage
537a27d277 Add test verifying that xml validation disabling/enabling works as expected. 2024-01-26 09:48:08 -06:00
Jonathan H. Wage
cf7757e090 Add back check that was reverted. 2024-01-26 09:33:17 -06:00
Grégoire Paris
0970ce7072 Merge pull request #11186 from derrabus/chore/readme-versions
Update branches in README
2024-01-26 08:34:24 +01:00
Alexander M. Turek
624c56be72 Update branches in README 2024-01-26 00:52:35 +01:00
Grégoire Paris
020d31efba Remove remaining submodules (#11183)
We are no longer relying on either piece of software.
2024-01-23 19:51:48 +01:00
Grégoire Paris
fbc8e6741e Merge pull request #11176 from thePanz/fix-11173-get-name-on-null-non-backed-enum
Throw exception when trying to use non-backed enum types
2024-01-23 07:50:20 +01:00
Grégoire Paris
2d65bc265b Merge pull request #11180 from greg0ire/allow-lexer-3
Allow doctrine/lexer 3
2024-01-22 19:51:10 +01:00
thePanz
7151db3cb8 Throw exception when trying to use non-backed enum types 2024-01-22 13:04:58 +01:00
Grégoire Paris
c23524259c Merge pull request #11181 from greg0ire/followup-rename
Look for lib remnants in hidden files
2024-01-21 23:52:34 +01:00
Grégoire Paris
4bddab9e09 Look for lib remnants in hidden files 2024-01-21 23:40:35 +01:00
Grégoire Paris
df730d69b8 Allow doctrine/lexer 3 2024-01-21 19:25:40 +01:00
Grégoire Paris
ac24c11808 Modernize code in documentation (#11179)
Somehow, there still were code samples relying on annotations.
2024-01-20 21:53:48 +01:00
Grégoire Paris
dd478d8662 Merge pull request #11178 from greg0ire/remove-ref-jira
Remove references to JIRA
2024-01-20 14:06:15 +01:00
Grégoire Paris
0b3cd72609 Remove references to JIRA 2024-01-20 13:45:04 +01:00
Grégoire Paris
85034699cb Merge pull request #11171 from greg0ire/extract-class
Make Doctrine\Tests\ORM\Internal\Node autoloadable
2024-01-18 21:33:06 +01:00
Grégoire Paris
d98186e2c4 Make Doctrine\Tests\ORM\Internal\Node autoloadable
It is used in several tests.
2024-01-18 21:19:28 +01:00
Grégoire Paris
69cc78c259 Merge remote-tracking branch 'fork/2.18.x' into 3.0.x 2024-01-18 21:07:35 +01:00
Grégoire Paris
2b8d6f87b2 Merge remote-tracking branch 'origin/2.17.x' into 2.18.x 2024-01-18 16:49:56 +01:00
Grégoire Paris
a0ed37954b Merge pull request #11167 from bobvandevijver/fix-eager-iterable-loading-test
Use foreach on iterable to prevent table locks during tests
2024-01-18 16:47:11 +01:00
Bob van de Vijver
4875f4c878 Use foreach on iterable to prevent table locks during tests 2024-01-18 10:24:40 +01:00
Grégoire Paris
b648bea2af Merge pull request #11164 from doctrine/2.17.x-merge-up-into-2.18.x_slYTN7ur
Merge release 2.17.3 into 2.18.x
2024-01-17 20:44:06 +01:00
Jonathan H. Wage
2893394673 Allow XML validation to be disabled but keep it enabled by default. 2024-01-17 13:13:39 -06:00
Grégoire Paris
f16594e89c Merge remote-tracking branch 'origin/2.17.x' into 2.17.x-merge-up-into-2.18.x_slYTN7ur 2024-01-17 20:10:52 +01:00
Grégoire Paris
398ab0547a Merge pull request #11162 from greg0ire/fix-libxml-compat
Remove redundant tags
2024-01-16 22:32:04 +01:00
Grégoire Paris
8f15337b03 Remove redundant tags
The "any" tags inside the definition for mapped superclasses and
embeddables duplicate what is already done for entities.

The other removed "any" tags are also redundant, as they duplicate
what's already done inside the grandparent "choice" tag.

Starting with version libxml 2.12, such redundant tags cause errors
about the content model not being "determinist".

Fixes #11117
2024-01-16 22:01:16 +01:00
Matthias Pigulla
a8632aca8f Keep the declared mapping information when using attribute overrides (#11135)
When using `AttributeOverride` to override mapping information inherited from a parent class (a mapped superclass), make sure to keep information about where the field was originally declared.

This is important for `private` fields: Without the correct `declared` information, it will lead to errors when cached mapping information is loaded, reflection wakes up and looks for the private field in the wrong class.
2024-01-13 00:06:34 +01:00
Matthias Pigulla
3dd3d38857 Fix @SequenceGeneratorDefinition inheritance, take 1 (#11050)
#10927 reported that #10455 broke the way how the default `@SequenceGeneratorDefinition` is created and inherited by subclasses for ID columns using `@GeneratedValue(strategy="SEQUENCE")`.

First, I had to understand how `@SequenceGeneratorDefinition` has been handled before #10455 when entity inheritance comes into play:

* Entity and mapped superclasses inherit the ID generator type (as given by `@GeneratedValue`) from their parent classes
* `@SequenceGeneratorDefinition`, however, is not generally inherited
* ... instead, a default sequence generator definition is created for every class when no explicit configuration is given. In this case, sequence names are based on the current class' table name.
* Once a root entity has been identified, all subclasses inherit its sequence generator definition unchanged.

#### Why did #10455 break this?

When I implemented #10455, I was mislead by two tests `BasicInheritanceMappingTest::testGeneratedValueFromMappedSuperclass` and `BasicInheritanceMappingTest::testMultipleMappedSuperclasses`.

These tests check the sequence generator definition that is inherited by an entity class from a mapped superclass, either directly or through an additional (intermediate) mapped superclass.

The tests expect the sequence generator definition on the entity _to be the same_ as on the base mapped superclass.

The reason why the tests worked before was the quirky behaviour of the annotation and attribute drivers that #10455 was aiming at: The drivers did not report the `@SequenceGeneratorDefinition` on the base mapped superclass where it was actually defined. Instead, they reported this `@SequenceGeneratorDefinition` for the entity class only.

This means the inheritance rules stated above did not take effect, since the ID field with the sequence generator was virtually pushed down to the entity class.

In #10455, I did not realize that these failing tests had to do with the quirky and changed mapping driver behaviour. Instead, I tried to "fix" the inheritance rules by passing along the sequence generator definition unchanged once the ID column had been defined.

#### Consequences of the change suggested here

This PR reverts the changes made to `@SequenceGeneratorDefinition` inheritance behaviour that were done in #10455.

This means that with the new "report fields where declared" driver mode (which is active in our functional tests) we can not expect the sequence generator definition to be inherited from mapped superclasses. The two test cases from `BasicInheritanceMappingTest` are removed.

I will leave a notice in #10455 to indicate that the new driver mode also affects sequence generator definitions.

The `GH10927Test` test case validates the sequence names generated in a few cases. In fact, I wrote this test against the `2.15.x` branch to make sure we get results that are consistent with the previous behaviour.

This also means `@SequenceGeneratorDefinition` on mapped superclasses is pointless: The mapped superclass does not make use of the definition itself (it has no table), and the setting is never inherited to child classes.
 
Fixes #10927. There is another implementation with slightly different inheritance semantics in #11052, in case the fix is not good enough and we'd need to review the topic later on.
2024-01-12 22:59:14 +01:00
Matthias Pigulla
c6b3509aa9 Include ON DELETE CASCADE associations in the delete order computation (#10913)
In order to resolve #10348, some changes were included in #10547 to improve the computed _delete_ order for entities. 

One assumption was that foreign key references with `ON DELETE SET NULL` or `... CASCADE` need not need to be taken into consideration when planning the deletion order, since the RDBMS would unset or cascade-delete such associations by itself when necessary. Only associations that do _not_ use RDBMS-level cascade handling would be sequenced, to make sure the referring entity is deleted before the referred-to one.

This assumption is wrong for `ON DELETE CASCADE`. The following examples give reasons why we need to also consider such associations, and in addition, we need to be able to deal with cycles formed by them.

In the following diagrams, `odc` means `ON DELETE CASCADE`, and `ref` is a regular foreign key with no extra `ON DELETE` semantics.

```mermaid
graph LR;
C-->|ref| B;
B-->|odc| A;
```

In this example, C must be removed before B and A. If we ignore the B->A dependency in the delete order computation, the result may not to be correct. ACB is not a working solution.

```mermaid
graph LR;
A-->|odc| B;
B-->|odc| A;
C-->|ref| B;
```

This is the situation in #10912. We have to deal with a cycle in the graph. C must be removed before A as well as B. If we ignore the B->A dependency (e.g. because we set it to "optional" to get away with the cycle), we might end up with an incorrect order ACB.

```mermaid
graph LR;
A-->|odc| B;
B-->|odc| A;
A-->|ref| C;
C-->|ref| B;
```

This example has no possible remove order. But, if we treat `odc` edges as optional, A -> C -> B would wrongly be deemed suitable.

```mermaid
graph LR;
A-->|ref| B;
B-->|odc| C;
C-->|odc| B;
D-->|ref| C;
```

Here, we must first remove A and D in any order; then, B and C in any order. If we treat one of the `odc` edges as optional, we might find the invalid solutions ABDC or DCAB.

#### Solution implemented in this PR

First, build a graph with a node for every to-be-removed entity, and edges for `ON DELETE CASCADE` associations between those entities. Then, use [Tarjan's algorithm](https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm) to find strongly connected components (SCCs) in this graph. The significance of SCCs is that whenever we remove one of the entities in a SCC from the database (no matter which one), the DBMS will immediately remove _all_ the other entities of that group as well.

For every SCC, pick one (arbitrary) entity from the group to represent all entities of that group. 

Then, build a second graph. Again we have nodes for all entities that are to be removed. This time, we insert edges for all regular (foreign key) associations and those with `ON DELETE CASCADE`. `ON DELETE SET NULL` can be left out. The edges are not added between the entities themselves, but between the entities representing the respective SCCs.

Also, for all non-trivial SCCs (those containing more than a single entity), add dependency edges to indicate that all entities of the SCC shall be processed _after_ the entity representing the group. This is to make sure we do not remove a SCC inadvertedly by removing one of its entities too early.

Run a topological sort on the second graph to get the actual delete order. Cycles in this second graph are a problem, there is no delete order.

Fixes #10912.
2024-01-12 22:44:07 +01:00
Grégoire Paris
a32578b7ea Merge pull request #11082 from bobvandevijver/eager-collection-iterable
Do not defer eager collection loading when in iteration context
2024-01-10 10:03:40 +01:00
Grégoire Paris
8aa6a5f401 Merge remote-tracking branch 'origin/2.18.x' into 3.0.x 2024-01-02 21:55:11 +01:00
Grégoire Paris
588d29d789 Merge pull request #11140 from greg0ire/psr-4
Flatten directory tree on 3.0
2024-01-02 21:54:38 +01:00
Grégoire Paris
d6989297c5 Merge pull request #11148 from greg0ire/flatten
Flatten directory tree on 2.18
2024-01-02 21:54:30 +01:00
Matthias Pigulla
e585a92763 Mention that `postRemove` may still see removed entities in in-memory collections (#11146)
... plus minor tweaks.
2024-01-02 21:31:28 +01:00
Grégoire Paris
0a3fbac8af Flatten directory tree
It will make fuzzy matchers more efficient, and configuration files more
readable.
2024-01-02 20:28:37 +01:00
Grégoire Paris
1556a1ff7a Merge pull request #11147 from greg0ire/remove-php-version-id
Remove irrelevant PHP version checks
2024-01-02 20:28:24 +01:00
Grégoire Paris
073f2aa891 Flatten directory tree
It will make fuzzy matchers more efficient, and configuration files more readable.

- lib/Doctrine/ORM becomes just src
- tests/Doctrine/ becomes just tests
2024-01-02 19:52:06 +01:00
Grégoire Paris
64e4a2129c Remove irrelevant PHP version checks 2024-01-02 09:00:22 +01:00
Grégoire Paris
7361d3e57d Merge remote-tracking branch 'origin/2.18.x' into 3.0.x 2024-01-02 08:57:41 +01:00
Grégoire Paris
a98e306335 Merge pull request #11144 from doctrine/2.17.x
Merge 2.17.x up into 2.18.x
2024-01-02 08:31:34 +01:00
Grégoire Paris
26f47cb8d3 Merge pull request #11142 from greg0ire/remove-inheritance
Remove inheritance
2024-01-02 08:24:50 +01:00
Grégoire Paris
ebb101009c Remove inheritance
Spotted while trying to merge https://github.com/doctrine/orm/pull/11076
(among other things) up into 3.0.x. On that branch, it is no longer
possible for an entity to extend another entity without specifying an
inheritance mapping type.

I think the goal of that inheritance was just to reuse the identifier
anyway, so let's just duplicate the identifier declaration instead.
2023-12-28 19:59:02 +01:00
Grégoire Paris
091e43eb9d Merge pull request #11141 from doctrine/2.17.x
Merge 2.17.x up into 2.18.x
2023-12-28 19:38:08 +01:00
Grégoire Paris
f80ef66ffb Merge pull request #11134 from doctrine/no-private-fields-duplicate
Mention in the limitations that private field names cannot be reused
2023-12-22 17:35:27 +01:00
Matthias Pigulla
85d78f8b0d Mention in the limitations that private field names cannot be reused 2023-12-22 17:13:11 +01:00
Grégoire Paris
c2886478e8 Merge pull request #11086 from mpdude/11058-revisited
Avoid an inconsistency in topological sort result order
2023-12-21 22:51:39 +01:00
Matthias Pigulla
108fa30db2 Improve topological sort result order
This PR changes a detail in the commit order computation for depended-upon entities.

We have a parent-child relationship between two entity classes. The association is parent one-to-many children, with the child entities containing the (owning side) back-reference.

Cascade-persist is not used, so all entities have to be passed to `EntityManager::persist()`.

Before v2.16.0, two child entities C1 and C2 will be inserted in the same order in which they are passed to `persist()`, and that is regardless of whether the parent entity was passed to `persist()` before or after the child entities.

As of v2.16.0, passing the parent entity to `persist()` _after_ the child entities will lead to an insert order that is _reversed_ compared to the order of `persist()` calls.

This PR makes the order consistent in both cases, as it was before v2.16.0.

 #### Cause

When the parent is passed to `persist()` after the children, commit order computation has to re-arrange the entities. The parent must be inserted first since it is referred to by the children.

The implementation of the topological sort from #10547 processed entities in reverse `persist()` order and unshifted finished nodes to an array to obtain the final result. That leads to dependencies (parent → before c1, parent → before c2) showing up in the result in the reverse order of which they were added.

This PR changes the topological sort to produce a result in the opposite order ("all edges pointing left"), which helps to avoid the duplicate array order reversal.

 #### Discussion

* This PR _does not_ change semantics of the `persist()` so that entities would (under all ciscumstances) be inserted in the order of `persist()` calls.
* It fixes an unnecessary inconsistency between versions before 2.16.0 and after. In particular, it may be surprising that the insert order for the child entities depends on whether another referred-to entity (the parent) was added before or after them.
* _Both_ orders (c1 before or after c2) are technically and logically correct with regard to the agreement that `commit()` is free to arrange entities in a way that allows for efficient insertion into the database.

Fixes #11058.
2023-12-21 16:26:20 +01:00
Alexander M. Turek
9785cb84c6 Merge release 2.17.2 into 2.18.x (#11131) 2023-12-20 23:16:21 +01:00
Alexander M. Turek
393679a479 Allow to skip property type validation (#11130) 2023-12-20 22:47:52 +01:00
Grégoire Paris
e50ae06fe7 Merge pull request #11122 from yceruto/enum_with_interface
Fix enum mapping validation
2023-12-15 08:12:07 +01:00
Yonel Ceruto
05ef1f4f96 Fixed enum mapping validation 2023-12-14 16:53:12 -05:00
Grégoire Paris
2b91edc525 Merge pull request #11115 from localheinz/fix/typo
Fix: Typo
2023-12-12 16:42:52 +01:00
Andreas Möller
6af7f9f7bf Fix: Typo 2023-12-12 16:33:54 +01:00
flaushi
46cb9a980b Added a note parameter type for the INSTANCE OF DQL expression (#7963)
Co-authored-by: flaushi <flaushi@users.noreply.github.com>
2023-12-12 14:51:31 +01:00
Grégoire Paris
c2d29d55ab Merge pull request #11114 from doctrine/2.17.x
Merge 2.17.x up into 2.18.x
2023-12-11 21:10:05 +01:00
flack
ed1df148c2 Fix method name in code example (#11104) 2023-12-04 21:07:27 +01:00
Tomas Norkūnas
44e943e100 Fix JSON mapping linting against subset of builtin types (#11076) 2023-12-02 11:32:08 +01:00
Alexander M. Turek
28d03e41f7 Merge branch '2.18.x' into 3.0.x
* 2.18.x:
  Add compatibility with the Symfony 4.4 VarExporter (#10948)
  PHPStan 5.16.0, Symfony 7.0 (#11095)
2023-12-01 21:58:59 +01:00
Cliff Odijk
23d36c0d52 Add compatibility with the Symfony 4.4 VarExporter (#10948) 2023-12-01 19:23:51 +01:00
Alexander M. Turek
212edaa80b PHPStan 5.16.0, Symfony 7.0 (#11095) 2023-11-29 14:35:05 +01:00
Markus Staab
f8ced51687 XmlDriver: remove dead code (#11085) 2023-11-25 09:16:23 +01:00
Bob van de Vijver
e5ab18ff80 Do not defer eager loading when iterable hint is set 2023-11-23 13:04:13 +01:00
Bob van de Vijver
665ccf1376 Add failing test
This test show that eager collections are broken when used in conjuction
with iterating over a result.
2023-11-23 12:42:38 +01:00
Grégoire Paris
2c06ffa4a7 Merge pull request #11071 from greg0ire/remove-wrong-assertion
Remove wrong assertion
2023-11-20 08:13:06 +01:00
Grégoire Paris
9a281f54de Remove wrong assertion
It is useless in that particular method, and wrong.
2023-11-19 21:29:56 +01:00
Grégoire Paris
b73d44b46b Merge pull request #11066 from doctrine/2.17.x-merge-up-into-3.0.x_45pl9AIy
Merge release 2.17.1 into 3.0.x
2023-11-17 08:19:27 +01:00
Grégoire Paris
b971cbeebb Merge remote-tracking branch 'origin/2.18.x' into 2.17.x-merge-up-into-3.0.x_45pl9AIy 2023-11-17 07:38:22 +01:00
Grégoire Paris
1a4fe6e0bb Merge pull request #11065 from kerbert101/fix-sleep-buhh
AbstractSqlExecutor::__sleep should return property names
2023-11-17 07:25:40 +01:00
Grégoire Paris
0a7b939623 Merge pull request #11039 from yceruto/enum_validation
Adds metadata field type and enumType validation against Entity property type
2023-11-16 23:45:38 +01:00
Albert Bakker
6be65ebc70 fix: return property names in AbstractSqlExecutor::__sleep
Property names as returned by a cast to array are mangled, and that
mangling is not documented. Returning unprefixed produces the same
result, and is more likely to be supported by external tools relying on
the documented possible return values of __sleep.

For instance symfony/var-exporter does not support mangled names, which
leads to issues when caching query parsing results in Symfony
applications.
2023-11-16 19:18:25 +01:00
Alexander M. Turek
fcba06f64c Merge release 2.17.0 into 3.0.x (#11062) 2023-11-16 00:11:38 +01:00
Alexander M. Turek
e8afa9f80c Prepare 2.17.0 (#11059) 2023-11-16 00:04:41 +01:00
Alexander M. Turek
7974a92bf9 Merge remote-tracking branch 'derrabus/3.0.x' into 3.0.x
* derrabus/3.0.x:
  Deprecate annotation classes for named queries
  Fix typos
  Housekeeping: Revert change to AbstractExporter, not needed without subselect fetch.
  Address review comments.
  Explain internals of eager loading in a bit more detail and how its configured.
  1:1 and M:1 associations also use fetch batch size configuration now.
  Add another testcase for DQL based fetch eager of collection.
  last violation hopefully
  Static analysis
  Housekeeping: phpcs
  Directly load many to many collections, batching not supported yet. fix tests.
  Avoid new fetch mode, use this strategy with fetch=EAGER for collections.
  Make sure to many assocatinos are also respecting AbstractQuery::setFetchMode
  Disallow use of fetch=SUBSELECT on to-one associations.
  Go through Persister API instead of indirectly through repository.
  Introduce configuration option for subselect batch size.
  Houskeeping: phpcs
  Disallow WITH keyword on fetch joined associatiosn via subselect.
  [GH-1569] Add new SUBSELECT fetch mode for OneToMany associations.
2023-11-15 23:49:44 +01:00
Alexander M. Turek
124593383b Fix calls to removed lock methods (#11061) 2023-11-15 23:48:59 +01:00
Alexander M. Turek
56df970d8b Merge branch '2.17.x' into 3.0.x
* 2.17.x:
  Deprecate annotation classes for named queries
  Fix typos
  Housekeeping: Revert change to AbstractExporter, not needed without subselect fetch.
  Address review comments.
  Explain internals of eager loading in a bit more detail and how its configured.
  1:1 and M:1 associations also use fetch batch size configuration now.
  Add another testcase for DQL based fetch eager of collection.
  last violation hopefully
  Static analysis
  Housekeeping: phpcs
  Directly load many to many collections, batching not supported yet. fix tests.
  Avoid new fetch mode, use this strategy with fetch=EAGER for collections.
  Make sure to many assocatinos are also respecting AbstractQuery::setFetchMode
  Disallow use of fetch=SUBSELECT on to-one associations.
  Go through Persister API instead of indirectly through repository.
  Introduce configuration option for subselect batch size.
  Houskeeping: phpcs
  Disallow WITH keyword on fetch joined associatiosn via subselect.
  [GH-1569] Add new SUBSELECT fetch mode for OneToMany associations.
2023-11-15 21:37:34 +01:00
Grégoire Paris
1267f482ef Merge pull request #8391 from beberlei/GH-1569-SubselectFetchMode
[GH-1569] Optimize eager fetch for collections to batch query
2023-11-14 08:16:00 +01:00
Grégoire Paris
21466a0524 Merge pull request #10986 from greg0ire/drop-support-for-unserializing-old-format
Drop support for unserializing old serialization formats
2023-11-14 08:15:19 +01:00
Grégoire Paris
010cd948c9 Drop support for unserializing old serialization formats 2023-11-11 18:44:26 +01:00
Grégoire Paris
b41de2a39d Merge pull request #11056 from derrabus/deprecate/named-queries
Deprecate annotation classes for named queries
2023-11-11 12:30:09 +01:00
Alexander M. Turek
6a48b0741b Deprecate annotation classes for named queries 2023-11-09 16:01:17 +01:00
Grégoire Paris
30626ac6bb Merge remote-tracking branch 'origin/2.17.x' into 3.0.x 2023-11-08 09:30:31 +01:00
Grégoire Paris
1f62233bf6 Merge pull request #11045 from greg0ire/dynamic-recommendation
Dynamically resolve AUTO to SEQUENCE or IDENTITY
2023-11-08 08:27:04 +01:00
Grégoire Paris
ffbe56779d Remove unneeded test
There no longer is such a thing as recommended strategies.
2023-11-07 21:10:01 +01:00
Grégoire Paris
bdc039fe31 Dynamically resolve AUTO to SEQUENCE or IDENTITY
With DBAL 3.x, IDENTITY results in SERIAL.
With DBAL 4.x, it results in the standard GENERATED BY DEFAULT AS IDENTITY.
2023-11-07 20:59:44 +01:00
Grégoire Paris
0e95838787 Merge pull request #11044 from greg0ire/identity-on-dbal4
Recommend SEQUENCE until doctrine/dbal 4 is released
2023-11-07 08:14:32 +01:00
Grégoire Paris
be62f72b38 Merge pull request #11048 from greg0ire/restore-bc
Restore backward compatibility with previous format
2023-11-06 20:08:18 +01:00
Yonel Ceruto
7613f25d57 Adds metadata field type and enumType validation against Entity property type 2023-11-06 08:23:58 -05:00
Grégoire Paris
c075154e1e Restore backward compatibility with previous format
When unserializing from a cache entry in the previous format, the
sqlStatements need to be copied from the legacy property to the new
property before the reference is created.
2023-11-06 07:52:27 +01:00
Grégoire Paris
f08159eb87 Merge pull request #11027 from greg0ire/fw-compat-serialization
Make serialized SQL executors forward compatible
2023-11-05 23:27:48 +01:00
Grégoire Paris
300cffb942 Recommend SEQUENCE until doctrine/dbal 4 is released
Using IDENTITY with doctrine/dbal 3 results in SERIAL, which is not
recommended.
2023-11-05 20:59:24 +01:00
Grégoire Paris
2a9390d426 Make serialized SQL executors forward compatible
The idea here is that instead of having a backward compatibility layer
in the next major branch, we can have a forward compatibility layer in
this branch.
2023-11-05 19:56:16 +01:00
Benjamin Eberlei
ec74c83845 Fix typos 2023-11-05 19:26:35 +01:00
Grégoire Paris
73288bc472 Merge pull request #11013 from greg0ire/native-type-decl
Enforce native type declarations
2023-10-22 23:19:37 +02:00
Benjamin Eberlei
4b2b4860fb Housekeeping: Revert change to AbstractExporter, not needed without subselect fetch. 2023-10-22 20:11:36 +02:00
Benjamin Eberlei
609e10df36 Address review comments. 2023-10-22 20:08:18 +02:00
Benjamin Eberlei
d03aed1265 Explain internals of eager loading in a bit more detail and how its configured. 2023-10-22 20:08:06 +02:00
Benjamin Eberlei
6993ad28ed 1:1 and M:1 associations also use fetch batch size configuration now. 2023-10-22 20:07:04 +02:00
Grégoire Paris
8ab0af3d30 Enforce native type declarations
I tried to avoid changes in tests, so as to not unnecessarily widen the
gap between 2.x and 3.x.
2023-10-22 15:45:24 +02:00
Grégoire Paris
82f4a177b2 Use native type hint for ProxyFactory::getProxy
This requires heavily adapting tests, because the proxy instance must:
- be an instance of InternalProxy (easy)
- be a valid entity (hard, especially for PHPUnit)
2023-10-22 15:45:24 +02:00
Grégoire Paris
1fef3196d9 Merge remote-tracking branch 'origin/2.17.x' into 3.0.x 2023-10-21 20:06:57 +02:00
Grégoire Paris
16028e4fd3 Merge pull request #11023 from doctrine/2.16.x
Merge 2.16.x up into 2.17.x
2023-10-21 19:52:04 +02:00
Grégoire Paris
609647a51a Merge pull request #11015 from greg0ire/phase2-optim
Make phpdoc accurate
2023-10-21 19:35:18 +02:00
Grégoire Paris
293299a314 Make phpdoc accurate
When transforming these phpdoc types into native types, things break
down. They are correct according to the EBNF, but in practice, there are
so-called phase 2 optimizations that allow using ConditionalPrimary,
ConditionalFactor and ConditionalTerm instances in places where
ConditionalExpression is used.
2023-10-21 19:15:03 +02:00
Grégoire Paris
0b7fe1862e Merge pull request #11018 from stof/fix_result_set_builder_enum
Fix the support for enum types in the ResultSetMappingBuilder
2023-10-18 22:27:01 +02:00
Christophe Coevoet
866283d1a7 Fix the support for enum types in the ResultSetMappingBuilder 2023-10-18 10:04:20 +02:00
Grégoire Paris
3676e3c571 Merge pull request #11007 from greg0ire/refresh-archi-docs
Address split of doctrine/common
2023-10-17 21:41:52 +02:00
Grégoire Paris
d84f607487 Address split of doctrine/common
doctrine/common has been split in several packages. A lot of what was
true about doctrine/common is true about doctrine/persistence today, so
let us simply reuse the existing paragraphs and mention persistence
instead of common.
2023-10-17 20:02:34 +02:00
Alexander M. Turek
ad519a5c6f Prepare CI for stable DBAL 4 (#11011) 2023-10-16 08:41:34 +02:00
Grégoire Paris
4444065531 Remove dependency on doctrine/common (#10998)
We were only relying on it for functionality related to proxies, which
is very little code.
2023-10-15 21:30:26 +02:00
Grégoire Paris
e280b2df26 Use native return type declarations in Debug class (#11012) 2023-10-15 13:56:52 +02:00
Grégoire Paris
3c34265666 Merge pull request #11010 from greg0ire/3.0.x
Merge 2.17.x up into 3.0.x
2023-10-14 23:26:51 +02:00
Grégoire Paris
8693fa790c Merge remote-tracking branch 'origin/2.17.x' into 3.0.x 2023-10-14 23:12:19 +02:00
Grégoire Paris
edd962e385 Merge pull request #11000 from greg0ire/copy-debug
Copy Debug class from doctrine/common
2023-10-14 23:00:13 +02:00
Grégoire Paris
a33a3813b2 Copy Debug class from doctrine/common
This reduces our dependency to this shared library that now holds very
little code we use.
The class has not been copied verbatim:
- Unused parameters and methods have been removed.
- The class is final and internal.
- Coding standards have been enforced, including enabling strict_types,
  which lead to casting a variable to string before feeding it to
  explode().
- A bug found by static analysis has been addressed, where an INI
  setting obtained with ini_get() was compared with true, which is never
  returned by that function.
- Tests are improved to run on all PHP versions
2023-10-14 21:21:51 +02:00
Grégoire Paris
bf69d0ac4e Implement proxy name resolver (#11009)
It is important to have the same implementation as used in
doctrine/persistence without relying on copy/paste.
2023-10-14 19:48:11 +02:00
Benjamin Eberlei
3f2fa309d4 Add another testcase for DQL based fetch eager of collection. 2023-10-14 15:56:42 +02:00
Benjamin Eberlei
8057b51f85 last violation hopefully 2023-10-14 15:38:26 +02:00
Benjamin Eberlei
c09660ac50 Merge remote-tracking branch 'origin/2.17.x' into GH-1569-SubselectFetchMode 2023-10-14 15:29:11 +02:00
Benjamin Eberlei
8ec599bb17 Static analysis 2023-10-14 15:28:57 +02:00
Benjamin Eberlei
bf74b434b8 Housekeeping: phpcs 2023-10-14 14:23:20 +02:00
Benjamin Eberlei
cd54c56278 Directly load many to many collections, batching not supported yet. fix tests. 2023-10-14 14:21:15 +02:00
Benjamin Eberlei
76fd34f766 Avoid new fetch mode, use this strategy with fetch=EAGER for collections. 2023-10-14 14:04:30 +02:00
David Buchmann
1cec0b82bd Remove useless check (#11006) 2023-10-13 18:57:12 +02:00
Grégoire Paris
0e74a180c4 Merge pull request #10999 from greg0ire/prepare-common-severance 2023-10-13 11:25:16 +02:00
Grégoire Paris
fdfca0f0e7 Undeprecate Autoloader class
We plan to sunset doctrine/common, and should move the Autoloader class
to doctrine/orm
2023-10-13 09:02:36 +02:00
Alexander M. Turek
e997c6688c Remove schema visitors (#11001) 2023-10-12 20:23:35 +02:00
Grégoire Paris
03148b1300 Merge pull request #10964 from soltmar/2.16.x-update-order-of-mapping-attributes
Updated order of mapping attribute parameters
2023-10-11 23:04:43 +02:00
Mariusz Soltys
f47d68c826 Merge branch '3.0.x' into 2.16.x-update-order-of-mapping-attributes 2023-10-11 15:05:50 +01:00
Alexander M. Turek
42af7cabb7 Cover calling AbstractQuery::setParameter() with an array parameter (#10996) 2023-10-11 16:04:47 +02:00
Alexander M. Turek
06eb00d687 Fix array parameters with DBAL 4 (#10995) 2023-10-11 15:27:18 +02:00
Benjamin Eberlei
7827453b94 UPGRADE.md is missing two latest merges. 2023-10-11 13:48:34 +02:00
Benjamin Eberlei
6f3140a09e Merge pull request #10994 from beberlei/3.0.x-g
Merge up 2.17.x to 3.0.x
2023-10-11 13:40:02 +02:00
Benjamin Eberlei
2d31d71961 Adapt tests, upgrade cs and fix static coding violations and baseline 2023-10-11 13:38:10 +02:00
Benjamin Eberlei
2db1f76dee Rework AUTO keyword deafults to be IDENTITY always, except Oracle SEQUENCE. 2023-10-11 12:00:40 +02:00
Benjamin Eberlei
6e61571edc Housekeeping: phpcs 2023-10-11 11:09:21 +02:00
Benjamin Eberlei
22e7c02cf7 Throw exceptions for cases where attributes are illegal on Embeddables. (#10992)
* Throw exceptions for cases where attributes are illegal on Embeddables.

* Embedded is allowed on Embeddable, update SchemaValidator.
2023-10-11 11:05:24 +02:00
Grégoire Paris
4a5f48f7ff Merge remote-tracking branch 'origin/2.17.x' into 3.0.x 2023-10-11 11:00:55 +02:00
Grégoire Paris
5534db1810 Merge commit '07b091750' into 3.0.x 2023-10-11 10:55:09 +02:00
Grégoire Paris
18897fa7d5 Merge pull request #10985 from greg0ire/remove-partial-from-dql 2023-10-11 10:49:29 +02:00
Grégoire Paris
c5137da90e Merge pull request #8931 from greg0ire/gh-8893 2023-10-11 10:38:15 +02:00
Grégoire Paris
689da1f251 Remove unused exception 2023-10-11 10:31:35 +02:00
Grégoire Paris
5c250063b8 Remove EntityManager::getPartialReference() 2023-10-11 10:31:35 +02:00
Grégoire Paris
99fe3b5c5b Remove partial syntax in DQL
It is no longer possible to use the "PARTIAL" keyword in a DQL query, or
to artificially build an AST with a partial object expression. It is
still possible to use the result set mapping API to build partial
objects.
2023-10-11 10:24:02 +02:00
Grégoire Paris
e89b680a28 Deprecate reliance on non-optimal defaults
What was optimal 10 years ago no longer is, and things might change in
the future. Using AUTO is still the best solution in most cases, and it
should be easy to make it mean something else when it is not.
2023-10-11 10:19:39 +02:00
Alexander M. Turek
af5c250cc8 Merge branch '2.17.x' into 3.0.x
* 2.17.x:
  Allow creating mocks of the Query class (#10990)
  Add missing "deprecated" annotation on the annotation driver
  Deprecate EntityManager*::getPartialReference()
2023-10-11 09:59:27 +02:00
Grégoire Paris
07b0917505 Merge pull request #10989 from greg0ire/improve-exceptions
Add method name in exception
2023-10-10 21:22:05 +02:00
Alexander M. Turek
143ee25697 Allow creating mocks of the Query class (#10990) 2023-10-10 17:16:01 +02:00
Grégoire Paris
52853c2e9c Merge pull request #10988 from greg0ire/add-missing-annotation 2023-10-10 16:42:50 +02:00
Benjamin Eberlei
40bfe07172 Make sure to many assocatinos are also respecting AbstractQuery::setFetchMode 2023-10-10 16:29:00 +02:00
Grégoire Paris
1fe0910d6b Merge pull request #10332 from greg0ire/drop-lexer-2 2023-10-10 16:25:37 +02:00
Grégoire Paris
6983f48490 Merge pull request #10987 from greg0ire/deprecate-partialreference 2023-10-10 15:32:11 +02:00
Grégoire Paris
194f5062bb Add method name in exception
When we assert a given exception should be thrown, and get this instead,
it is hard to figure out what went wrong.
2023-10-10 15:19:16 +02:00
Grégoire Paris
922365d2c5 Add missing "deprecated" annotation on the annotation driver 2023-10-10 15:14:11 +02:00
Grégoire Paris
a1e055b608 Deprecate EntityManager*::getPartialReference()
Partial objects have been deprecated, so it makes no sense to still have
this way of getting some.
2023-10-10 14:39:08 +02:00
Alexander M. Turek
2cf0c59f7a Allow VarExporter 7 (#10984) 2023-10-10 12:42:04 +02:00
Mariusz Soltys
7e51a09347 Updated order of mapping attribute parameters 2023-10-10 11:15:33 +01:00
Alexander M. Turek
906e91cbb4 Merge branch '2.17.x' into 3.0.x
* 2.17.x:
  Don't assert that BIGINTs are stored as strings (#10980)
2023-10-10 11:36:17 +02:00
Alexander M. Turek
0e3489b240 Don't assert that BIGINTs are stored as strings (#10980) 2023-10-10 11:35:09 +02:00
Benjamin Eberlei
ff28ba8080 Disallow use of fetch=SUBSELECT on to-one associations. 2023-10-10 08:25:04 +02:00
Benjamin Eberlei
41410e6be1 Go through Persister API instead of indirectly through repository. 2023-10-10 08:17:25 +02:00
Benjamin Eberlei
b9e55bad4d Introduce configuration option for subselect batch size. 2023-10-10 07:59:29 +02:00
Benjamin Eberlei
47952c3228 Houskeeping: phpcs 2023-10-10 07:51:13 +02:00
Benjamin Eberlei
fdceb82454 Disallow WITH keyword on fetch joined associatiosn via subselect. 2023-10-10 07:49:38 +02:00
Benjamin Eberlei
dc899e26cf [GH-1569] Add new SUBSELECT fetch mode for OneToMany associations.
Co-authored-by: Wouter M. van Vliet <wouter@interpotential.com>
2023-10-10 07:26:17 +02:00
Alexander M. Turek
2aaec3a79a Merge branch '2.17.x' into 3.0.x
* 2.17.x:
  document Paginator::HINT_ENABLE_DISTINCT
  allow to disable "DISTINCT" added to the sql query by the limit subquery walker
  Test against php 8.3 (#10963)
  update checkout version to version 4
2023-10-09 17:51:53 +02:00
Alexander M. Turek
48edb33b3f Merge branch '2.16.x' into 2.17.x
* 2.16.x:
  Test against php 8.3 (#10963)
  update checkout version to version 4
2023-10-09 17:30:21 +02:00
Grégoire Paris
9c2e49a665 Merge pull request #10970 from goetas/distinct-limit 2023-10-09 16:43:20 +02:00
Grégoire Paris
4799c418c9 Merge pull request #10975 from greg0ire/void-execute-insert 2023-10-09 16:40:07 +02:00
Grégoire Paris
a1d7de6b66 Merge remote-tracking branch 'origin/2.17.x' into 3.0.x 2023-10-09 16:35:27 +02:00
Grégoire Paris
8ef5c80148 Merge pull request #10974 from beberlei/RemovePartialObjectExpressionUsage 2023-10-09 16:28:45 +02:00
Grégoire Paris
83d46d7cf9 Change EntityPersister return type
Calling UnitOfWork::assignPostInsertId() is now the way to go.
2023-10-09 16:13:29 +02:00
Benjamin Eberlei
083b1f98c1 Housekeeping: phpcs 2023-10-09 15:42:41 +02:00
Matthias Pigulla
3ff67c3e2f Merge pull request #10967 from greg0ire/remove-commit-order-calculator-from-2
Remove CommitOrderCalculator and related classes
2023-10-09 15:37:05 +02:00
Benjamin Eberlei
84a762e12e Adjust tests for new sql generation 2023-10-09 15:35:48 +02:00
Benjamin Eberlei
ef2123bd0f Remove use of PartialObjectExyxpression for LimitSubqueryOutputWalker to prepare for removal. 2023-10-09 15:30:10 +02:00
Asmir Mustafic
55699a9129 document Paginator::HINT_ENABLE_DISTINCT 2023-10-09 14:05:01 +02:00
Asmir Mustafic
68fc3b6458 allow to disable "DISTINCT" added to the sql query by the limit subquery walker 2023-10-09 14:05:01 +02:00
Serhii Petrov
32192c7b01 Test against php 8.3 (#10963) 2023-10-09 12:43:52 +02:00
Grégoire Paris
f3b6c4b356 Use lazy ghosts unconditionally (#10969)
* Use lazy ghosts unconditionally

* Stop extending proxy factory from doctrine/common

Extending it no longer serves any purpose.

* Transform annotation into actual method
2023-10-08 23:18:35 +02:00
Grégoire Paris
77843e45f3 Merge pull request #10972 from salehhashemi1992/ci/update-checkout-to-v4
update actions/checkout to v4
2023-10-08 18:44:13 +02:00
Grégoire Paris
343afda275 Merge pull request #10971 from greg0ire/restore-prefer-lowest
Restore job with --prefer-lowest
2023-10-08 18:43:53 +02:00
Grégoire Paris
27009986d7 Restore job with --prefer-lowest
It is useful to catch misconfigured dependency constraints. It was
removed in 413c33274d.
This implies configuring mocks so as to support psr/cache 1
psr/cache 1 does not use native return types, and phpdoc is not enough
to obtain a mock that has typed methods.
2023-10-08 13:08:16 +02:00
salehhashemi1992
1919eea0a9 update checkout version to version 4 2023-10-08 11:04:22 +03:30
Grégoire Paris
e71868fe8b Merge pull request #10968 from greg0ire/reject-id-collisions-unconditionally
Reject ID collisions in identity map unconditionally
2023-10-07 21:39:56 +02:00
Grégoire Paris
795e7735d8 Reject ID collisions in identity map unconditionally 2023-10-07 20:54:04 +02:00
Grégoire Paris
925631878f Remove CommitOrderCalculator and related classes
They are unused, and since they are internal, it should be fine to
remove them without a deprecation.
2023-10-07 11:57:26 +02:00
Grégoire Paris
46ef989f38 Update reference 2023-10-06 23:55:34 +02:00
Grégoire Paris
8a4d35d5e7 Merge origin/2.17.x into 3.0.x (using imerge) 2023-10-06 23:50:53 +02:00
Grégoire Paris
faec95fed2 Merge pull request #10909 from greg0ire/imerge/continue-merge-up
Continue merge up
2023-10-06 21:06:54 +02:00
Grégoire Paris
c69044bc9b Implement InternalProxy as well 2023-10-03 12:22:17 +02:00
Alexander M. Turek
db2791001c Merge branch '2.16.x' into 2.17.x
* 2.16.x:
  PHPStan 1.10.35, Psalm 5.15.0 (#10958)
  docs: in text, refer to attributes when talking about metadata (#10956)
  Fix bullet list layout (#10951)
  docs[query-builder]: fix rendering of `Doctrine\DBAL\ParameterType::*` (#10945)
  tests[ORMSetupTest]: testCacheNamespaceShouldBeGeneratedForApcu requires enabled apc (#10940)
  docs: use modern named arguments syntax
  Ignore "Unknown directive" error
  Use a stable release
  Remove output directory argument
  tutorials[getting-started]: example fix bug id type definition
  Verify UnitOfWork::HINT_DEFEREAGERLOAD exists and is true
2023-09-29 08:57:56 +02:00
Alexander M. Turek
62ed63bbbe PHPStan 1.10.35, Psalm 5.15.0 (#10958) 2023-09-29 08:56:45 +02:00
Danny van Kooten
081ec2ad26 docs: in text, refer to attributes when talking about metadata (#10956)
Co-authored-by: Danny van Kooten <dannyvankooten@users.noreply.github.com>
2023-09-28 21:49:15 +02:00
Grégoire Paris
9a1085d72f Merge pull request #10954 from dannyvankooten/3.0.x 2023-09-28 11:54:33 +02:00
Danny van Kooten
501226b90b remove reference to removed yaml configuration option 2023-09-28 11:02:28 +02:00
Grégoire Paris
633ce41460 Merge pull request #10946 from greg0ire/improved-validation
Adds metadata field type validation against Entity property type
2023-09-23 12:12:18 +02:00
Adrien Crivelli
e9537f4cde Fix bullet list layout (#10951) 2023-09-19 21:01:37 +02:00
DavideBicego
0f67ba2176 Adds metadata field type validation against Entity property type
This avoid situations where you might map a decimal to a float, when it
should really be mapped to a string. This is a big pitfall because in
that situation, the ORM will consider the field changed every time.
2023-09-15 11:19:58 +02:00
Marko Kaznovac
38ad3925e2 docs[query-builder]: fix rendering of Doctrine\DBAL\ParameterType::* (#10945) 2023-09-15 00:17:48 +02:00
Marko Kaznovac
858b01f85e tests[ORMSetupTest]: testCacheNamespaceShouldBeGeneratedForApcu requires enabled apc (#10940) 2023-09-10 22:57:36 +02:00
Grégoire Paris
9f555ea8fb Merge pull request #10933 from kaznovac/patch-2
docs: use modern named arguments syntax
2023-09-08 22:02:11 +02:00
Marko Kaznovac
1f8c02f345 docs: use modern named arguments syntax
use official named arguments syntax in example instead of pre php 8 codestyle for 'named' arguments
2023-09-08 13:47:11 +02:00
Grégoire Paris
d81afdb6e3 Merge pull request #10930 from greg0ire/improve-doc-job
Improve doc job
2023-09-02 23:15:56 +02:00
Grégoire Paris
0628204b43 Ignore "Unknown directive" error
We have a lot of errors about "Unknown directive" that we should make
known when implementing guides for Doctrine, but cannot address by
modifying the docs.

The unknown directives are:

- configuration-block
- toc
- tocheader
- sectionauthor
2023-09-02 19:29:05 +02:00
Grégoire Paris
816ecc6d6b Use a stable release
0.1.0 has been published 3 weeks ago. This means we no longer need to
  use dev stability
2023-09-02 19:02:59 +02:00
Grégoire Paris
f66263d859 Remove output directory argument
It is no actually necessary at all.
2023-09-02 19:01:46 +02:00
Grégoire Paris
8aa5aa2f57 Merge pull request #10929 from kaznovac/patch-1
tutorials[getting-started]: example fix bug id type definition
2023-09-02 18:52:43 +02:00
Marko Kaznovac
96e31a3b30 tutorials[getting-started]: example fix bug id type definition 2023-09-02 17:48:29 +02:00
Grégoire Paris
a60a273423 Merge pull request #10808 from oscmarb/verifiy-hint-defer-eager-load-is-true
Verify UnitOfWork::HINT_DEFEREAGERLOAD exists and is true
2023-09-01 07:52:11 +02:00
Alexander M. Turek
a2d2e173c2 Merge release 2.16.2 into 2.17.x (#10924) 2023-08-28 09:50:37 +02:00
Grégoire Paris
17500f56ea Merge pull request #10923 from kaznovac/patch-1
basic-mapping: fix new-line rendered in output
2023-08-27 20:21:56 +02:00
Marko Kaznovac
fc2f724e2d basic-mapping: fix new-line rendered in output 2023-08-27 19:17:04 +02:00
Óscar Martínez
7986fc64dd Verify UnitOfWork::HINT_DEFEREAGERLOAD exists and is true 2023-08-25 09:51:02 +02:00
Grégoire Paris
2f9e98754b Merge pull request #10915 from mpdude/post-events-later
Mitigate problems with `EntityManager::flush()` reentrance since 2.16.0 (Take 2)
2023-08-25 07:47:25 +02:00
Alexander M. Turek
aa333e2f1d Support Symfony 7 by adding return types conditionally (#10919) 2023-08-24 10:36:04 +02:00
Alexander M. Turek
b6441b4f26 Merge branch '2.16.x' into 2.17.x
* 2.16.x:
  Use required classes for Lifecycle Callback examples (#10916)
  Add space before backquote (#10918)
  Add back throws annotation to getSingleScalarResult (#10907)
  Fix link on known issues docs (#10904)
2023-08-23 23:47:29 +02:00
Sergii Dolgushev
bb5524099c Use required classes for Lifecycle Callback examples (#10916)
* Use required classes for Lifecycle Callback examples

* Coding Style fixes

---------

Co-authored-by: Sergii Dolgushev <Sergii.Dolgushev@secondwaveds.com>
2023-08-23 22:47:15 +02:00
Grégoire Paris
3a8cafe228 Add space before backquote (#10918)
According to the RST docs,

> [inline markup] it must be separated from surrounding text by non-word
> characters. Use a backslash escaped space to work around that: thisis\ *one*\ word.

Because we were missing a space before backquotes here, the links were
not rendered. Escaping the space allow not to actually produce a space
in the output.

See https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#inline-markup
2023-08-23 21:42:35 +02:00
Matthias Pigulla
8259a16681 Mitigate problems with EntityManager::flush() reentrance since 2.16.0 (Take 2)
The changes from #10547, which landed in 2.16.0, cause problems for users calling `EntityManager::flush()` from within `postPersist` event listeners.

* When `UnitOfWork::commit()` is re-entered, the "inner" (reentrant) call will start working through all changesets. Eventually, it finishes with all insertions being performed and `UoW::$entityInsertions` being empty. After return, the entity insertion order, an array computed at the beginning of `UnitOfWork::executeInserts()`, still contains entities that now have been processed already. This leads to a strange-looking SQL error where the number of parameters used does not match the number of parameters bound. This has been reported as #10869.

* The fixes made to the commit order computation may lead to a different entity insertion order than previously. `postPersist` listener code may be affected by this when accessing generated IDs for other entities than the one the event has been dispatched for. This ID may not yet be available when the insertion order is different from the one that was used before 2.16. This has been mentioned in https://github.com/doctrine/orm/pull/10906#issuecomment-1682417987.

This PR suggests to address both issues by dispatching the `postPersist` event only after _all_ new entities have their rows inserted into the database. Likewise, dispatch `postRemove` only after _all_ deletions have been executed.

This solves the first issue because the sequence of insertions or deletions has been processed completely _before_ we start calling event listeners. This way, potential changes made by listeners will no longer be relevant.

Regarding the second issue, I think deferring `postPersist` a bit until _all_ entities have been inserted does not violate any promises given, hence is not a BC break. In 2.15, this event was raised after all insertions _for a particular class_ had been processed - so, it was never an "immediate" event for every single entity. #10547 moved the event handling to directly after every single insertion. Now, this PR moves it back a bit to after _all_ insertions.
2023-08-23 07:55:21 +02:00
Grégoire Paris
2c39b3f118 Remove base test case class (#10910)
We are using PHPUnit 10, so none of the polyfills in that class are
needed now.
2023-08-15 15:44:34 +02:00
Grégoire Paris
436f0467ec imerge 'continue-merge-up': manual merge 1-1 2023-08-15 11:42:53 +02:00
David Arenas
5577d51c44 Add back throws annotation to getSingleScalarResult (#10907)
Fix regression introduced in #10870

`$result = $this->execute(null, $hydrationMode);` in `getSingleResult` can still throw NoResultException exception.
2023-08-13 13:01:30 +02:00
Eduardo Rocha
d1922a3065 Fix link on known issues docs (#10904) 2023-08-10 21:41:31 +02:00
Alexander M. Turek
9647d0e2ae Merge release 2.16.1 into 2.17.x (#10896) 2023-08-09 15:17:34 +02:00
Alexander M. Turek
597a63a86c PHPStan 1.10.28, Psalm 5.14.1 (#10895) 2023-08-09 15:05:08 +02:00
Alexander M. Turek
368eb01ac3 Merge 2.16.x into 2.17.x (#10894) 2023-08-09 11:46:12 +02:00
Bei Xiao
6b220e3c90 Fix return type of getSingleScalarResult (#10870) 2023-08-09 11:42:00 +02:00
Matthias Pigulla
6de4b68705 Use a dedicated exception for the check added in #10785 (#10881)
This adds a dedicated exception for the case that objects with colliding identities are to be put into the identity map.

Implements #10872.
2023-08-09 11:38:35 +02:00
Matthias Pigulla
16c0151831 Document more clearly that the insert order is an implementation detail (#10883) 2023-08-09 11:36:05 +02:00
Matthias Pigulla
440b244ebc Fix broken changeset computation for entities loaded through fetch=EAGER + using inheritance (#10884)
#10880 reports a case where the changes from #10785 cause entity updates to be missed.

Upon closer inspection, this change seems to be causing it:

https://github.com/doctrine/orm/pull/10785/files#diff-55a900494fc8033ab498c53929716caf0aa39d6bdd7058e7d256787a24412ee4L2990-L3003

The code was changed to use `registerManaged()` instead, which basically does the same things, but (since #10785) also includes an additional check against duplicate entity instances.

But, one detail slipped through tests and reviews: `registerManaged()` also updates `\Doctrine\ORM\UnitOfWork::$originalEntityData`, which is used to compute entity changesets. An empty array `[]` was passed for $data here.

This will make the changeset computation assume that a partial object was loaded and effectively ignore all field updates here:

a616914887/lib/Doctrine/ORM/UnitOfWork.php (L762-L764)

I think that, effectively, it is sufficient to call `registerManaged()` only in the two cases where a proxy was created.

Calling `registerManaged()` with `[]` as data for a proxy object is consistent with e. g. `\Doctrine\ORM\EntityManager::getReference()`.

In the case that a full entity has to be loaded, we need not call `registerManaged()` at all, since that will already happen inside `EntityManager::find()` (or, more specifically, `UnitOfWork::createEntity()` called inside it).

Note that the test case has to make some provisions so that we actually reach this case:
* Load an entity that uses `fetch="EAGER"` on a to-one association
* That association being against a class that uses inheritance (why's that?)
2023-08-09 11:34:53 +02:00
Alexander M. Turek
394f6fe1b4 Merge pull request #10888 from greg0ire/partial-merge-up
Partial merge up of 2.17.x into 3.0.x
2023-08-08 16:38:30 +02:00
Grégoire Paris
7d9a2c0a71 Merge commit 'e78163981292075c5cc987c1b50ec7a4fad0e20e' into 3.0.x 2023-08-08 14:00:33 +02:00
Nicolas Grekas
47cf50bcd5 Add note about not-enabling lazy-ghosts (#10887) 2023-08-07 15:20:38 +02:00
Alexander M. Turek
58df4078fc Merge branch '2.16.x' into 2.17.x
* 2.16.x:
  Turn identity map collisions from exception to deprecation notice (#10878)
  Add possibility to set reportFieldsWhereDeclared to true in ORMSetup (#10865)
  Fix UnitOfWork->originalEntityData is missing not-modified collections after computeChangeSet  (#9301)
  Add an UPGRADE notice about the potential changes in commit order (#10866)
  Update branch metadata (#10862)
2023-08-07 15:17:36 +02:00
Nicolas Grekas
eda1909c75 Deprecate not-enabling lazy-ghosts and decouple from doctrine/common's proxies (#10837) 2023-08-07 14:43:38 +02:00
Matthias Pigulla
a616914887 Turn identity map collisions from exception to deprecation notice (#10878)
In #10785, a check was added that prevents entity instances from getting into the identity map when another object for the same ID is already being tracked.

This caused regressions for users that work with application-provided IDs and expect this condition to fail with `UniqueConstraintViolationExceptions` when flushing to the database.

Thus, this PR turns the exception into a deprecation notice. Users can opt-in to the new behavior. In 3.0, the exception will be used.

Implements #10871.
2023-08-04 14:06:02 +02:00
Dieter Beck
fd0bdc69b0 Add possibility to set reportFieldsWhereDeclared to true in ORMSetup (#10865)
Otherwise it is impossible to avoid a deprecation warning when using ORMSetup::createAttributeMetadataConfiguration()
2023-08-02 14:34:13 +02:00
Michael Olšavský
f50803ccb9 Fix UnitOfWork->originalEntityData is missing not-modified collections after computeChangeSet (#9301)
* Fix original data incomplete after flush

* Apply suggestions from code review

Co-authored-by: Alexander M. Turek <me@derrabus.de>

---------

Co-authored-by: Alexander M. Turek <me@derrabus.de>
2023-08-02 13:44:15 +02:00
Matthias Pigulla
eeefc6bc0f Add an UPGRADE notice about the potential changes in commit order (#10866) 2023-08-02 13:42:49 +02:00
Grégoire Paris
710dde83aa Update branch metadata (#10862) 2023-08-01 14:56:34 +02:00
Alexander M. Turek
ab542e97df Allow symfony/console 7 (#10724) 2023-08-01 14:25:03 +02:00
Grégoire Paris
495cd06b9a Merge pull request #10727 from derrabus/revert/symfony-7
Revert "Allow symfony/console 7"
2023-08-01 14:07:04 +02:00
Grégoire Paris
fd7a14ad22 Merge pull request #10547 from mpdude/commit-order-entity-level
Compute the commit order (inserts/deletes) on the entity level
2023-08-01 09:21:09 +02:00
Matthias Pigulla
0d3ce5d4f8 Exclude deprecated classes from Psalm checks (until 3.0) 2023-08-01 08:53:56 +02:00
Matthias Pigulla
f01d107edc Fix commit order computation for self-referencing entities with application-provided IDs
This excludes such associations from the commit order computation, since the foreign key constraint will be satisfied when inserting the row.

See https://github.com/doctrine/orm/pull/10735/ for more details about this edge case.
2023-08-01 08:43:16 +02:00
Alexander M. Turek
3cc30c4024 Merge branch '2.15.x' into 2.16.x
* 2.15.x:
  Fix static analysis
  Other solution
  Avoid self deprecation
  fix: use platform options instead of deprecated custom options (#10855)
2023-07-28 16:26:45 +02:00
Alexander M. Turek
d2de4ec03c Revert "Introduce FilterCollection#restore method (#10537)"
This reverts commit 8e20e1598e.
2023-07-28 16:08:17 +02:00
Vincent Langlet
64ee76e94e Introduce FilterCollection#restore method (#10537)
* Introduce FilterCollection#restore method

* Add suspend method instead

* Add more tests
2023-07-28 16:08:06 +02:00
Vincent Langlet
8e20e1598e Introduce FilterCollection#restore method (#10537)
* Introduce FilterCollection#restore method

* Add suspend method instead

* Add more tests
2023-07-28 16:05:51 +02:00
Grégoire Paris
24df74d61d Merge pull request #10856 from VincentLanglet/fixDeprecation
Fix/Self deprecation with getQueryCacheImpl
2023-07-26 23:41:39 +02:00
Vincent Langlet
442f073d25 Fix static analysis 2023-07-26 17:42:20 +02:00
Vincent Langlet
a5161e9485 Other solution 2023-07-26 16:00:37 +02:00
Vincent Langlet
ddc7d953b9 Avoid self deprecation 2023-07-26 12:37:42 +02:00
Kévin Dunglas
db51ed4f4c fix: use platform options instead of deprecated custom options (#10855) 2023-07-25 16:23:46 +02:00
Grégoire Paris
2dc19e6919 Remove outdated comment (#10853)
Since support for persistence 2 has been dropped, this method may no
longer acces an aliased class name.
Besides, providing an FQCN with a leading backslash should work since
removing it is the first thing that happens inside
AbstractClassMetadataFactory::getMetadataFor().
2023-07-25 00:31:57 +02:00
Alexander M. Turek
6d27797b2e Merge release 2.15.4 into 2.16.x (#10850) 2023-07-23 23:49:30 +02:00
Nicolas Grekas
89250b8ca2 Use properties instead of getters to read property/class names via reflection (#10848) 2023-07-20 20:37:52 +02:00
Grégoire Paris
f7e4b61459 Merge pull request #10847 from greg0ire/remove-toc 2023-07-18 09:50:04 +02:00
Grégoire Paris
6b0afdbd58 Avoid triple colons
It confuses the guides, and is ugly.
2023-07-18 08:57:09 +02:00
Grégoire Paris
d3cf17b26d Remove toc
We already have the sidebar for this.
2023-07-18 08:56:24 +02:00
Alexander M. Turek
b68cab1b3d Declare compatibility with DBAL 4 (#10843) 2023-07-17 00:30:09 +02:00
Alexander M. Turek
bc61d7d21e Merge branch '2.15.x' into 2.16.x
* 2.15.x:
  PHPStan 1.10.25, Psalm 5.13.1 (#10842)
2023-07-16 23:40:09 +02:00
Alexander M. Turek
5213228a64 PHPStan 1.10.25, Psalm 5.13.1 (#10842) 2023-07-16 23:38:29 +02:00
Nicolas Grekas
dca7ddf969 Decouple public API from Doctrine\Persistence\Proxy (#10832) 2023-07-15 10:55:35 +02:00
Grégoire Paris
e781639812 Merge pull request #10841 from doctrine/2.15.x 2023-07-12 15:54:17 +02:00
Grégoire Paris
7848417488 Merge pull request #10838 from greg0ire/remove-dummy-title 2023-07-12 11:07:46 +02:00
Grégoire Paris
56e5856ad7 Remove dummy title
This was never meant to be under version control. Did not spot it in the
diff.

Closes #10836
2023-07-12 11:06:06 +02:00
Grégoire Paris
b5987ad29a Merge pull request #10598 from opsway/fix-generated-for-joined-inheritance
Support not Insertable/Updateable columns for entities with `JOINED` inheritance type
2023-07-11 23:48:10 +02:00
Grégoire Paris
385bdd33f1 Merge pull request #10798 from greg0ire/less-partial-load
Resort on Query::HINT_FORCE_PARTIAL_LOAD less
2023-07-11 23:46:17 +02:00
Nicolas Grekas
8c513a6523 Cleanup psalm-type AutogenerateMode (#10833) 2023-07-11 23:01:02 +02:00
Grégoire Paris
1413b496d7 Merge pull request #10824 from greg0ire/fix-build 2023-07-11 12:10:23 +02:00
Alexandr Vronskiy
3b3056f910 mistake on final property 2023-07-11 09:38:34 +03:00
Alexandr Vronskiy
fa5c37e972 Add final to protected
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2023-07-11 09:38:34 +03:00
Yevhen Vilkhovchenko
f3e36debfe Fix persist notInsertable|notUpdatable fields of root entity of joined inheritance type
1. Inherit ClassMetadataInfo::requiresFetchAfterChange flag from root entity when process parent columns mapping (see ClassMetadataInfo::addInheritedFieldMapping(), it uses same condition as ClassMetadataInfo::mapField()) so JoinedSubclassPersister::assignDefaultVersionAndUpsertableValues() to be called in JoinedSubclassPersister::executeInserts().
2. Override JoinedSubclassPersister::fetchVersionAndNotUpsertableValues() to fetch all parent tables (see $this->getJoinSql() call) generated columns. So make protected BasicEntityPersister::identifierFlattener stateless service (use it flattenIdentifier() method) and BasicEntityPersister::extractIdentifierTypes() (to avoid copy-paste).
3. JoinedSubclassPersister::fetchVersionAndNotUpsertableValues() doesnt check empty $columnNames because it would be an error if ClassMetadataInfo::requiresFetchAfterChange is true while no generated columns in inheritance hierarchy.
4. Initialize JoinedInheritanceRoot not-nullable string properties with insertable=false attribute to avoid attempt to insert default null data which cause error:
    PDOException: SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column "rootwritablecontent" of relation "joined_inheritance_root" violates not-null constraint
    DETAIL:  Failing row contains (5, null, dbDefault, dbDefault, , nonUpdatable).
  while $rootTableStmt->executeStatement() because JoinedSubclassPersister::getInsertColumnList() have no $insertData (prepared later) to decide is generated column provided by client code or not (so need to skip column)
2023-07-11 09:38:34 +03:00
Yevhen Vilkhovchenko
ca7abd04a2 Fix persist notInsertable|notUpdatable columns of entity with joined inheritance type
1. Postgres gives error when insert root entity ($rootTableStmt->executeStatement()) in JoinedSubclassPersister::executeInserts():
   PDOException: SQLSTATE[08P01]: <<Unknown error>>: 7 ERROR:  bind message supplies 4 parameters, but prepared statement "" requires 6
  so exclude notInsertable columns from JoinedSubclassPersister::getInsertColumnList() like it done in parent::prepareInsertData() which call BasicEntityPersister::prepareUpdateData(isInsert: true) where we have condition:
    if ($isInsert && isset($fieldMapping['notInsertable']))
2. Try to get generated (notInsertable|notUpdatable) column value on flush() with JoinedSubclassPersister::executeInserts() also fails:
    Unexpected empty result for database query.
  because method it calls $this->assignDefaultVersionAndUpsertableValues() after insert root entity row, while generated columns in child-entity table, so move call just after insert child row
3. Use option['default'] = 'dbDefault' in functional test entities, to emulate generated value on insert, but declare as generated = 'ALWAYS' for tests purpose (correctness of JoinedSubclassPersister::fetchVersionAndNotUpsertableValues() sql-query)
4. Use JoinedInheritanceRoot::rootField to skip JoinedSubclassPersister::update() optimization for empty changeset in updatable:false columns tests
2023-07-11 09:38:34 +03:00
Matthias Pigulla
a555626150 Improve and add test to set to-one and to-many associations with reference objects (#10799) 2023-07-11 00:07:02 +02:00
Grégoire Paris
ec7a8a7a0f Merge pull request #10828 from greg0ire/matching-xml
Match namespace in XML file with namespace in XSD file
2023-07-09 23:02:43 +02:00
Grégoire Paris
e94fa8588d Match namespace in XML file with namespace in XSD file
In 7fa3e6ec7c, a global search and replace
was used for http and https.
This broke the documentation examples in that as soon as you turn on XSD
validation, it will fail because the namespace in the XML file does not
match the ones defined in the XSD file, which do not exhibit the https.

Note that this is not a security concern, because these URIs are
not meant to be actually resolved, but to serve as a unique identifier
for the namespace in which we define our elements.
2023-07-09 21:18:57 +02:00
Matthias Pigulla
f26946b477 Add @deprecated annotations in addition to runtime deprecation notices 2023-07-08 16:22:55 +02:00
Matthias Pigulla
efc83bce8e Make it possible to have non-NULLable self-referencing associations when using application-provided IDs (#10735)
This change improves scheduling of extra updates in the `BasicEntityPersister`.

Extra updates can be avoided when
* the referred-to entity has already been inserted during the current insert batch/transaction
* we have a self-referencing entity with application-provided ID values (the `NONE` generator strategy).

As a corollary, with this change applications that provide their own IDs can define self-referencing associations as not NULLable.

I am considering this a bugfix since the ORM previously executed additional queries that were not strictly necessary, and that required users to work with NULLable columns where conceptually a non-NULLable column would be valid and more expressive.

One caveat, though:

In the absence of entity-level commit ordering (#10547), it is not guaranteed that entities with self-references (at the class level) will be inserted in a suitable order. The order depends on the sequence in which the entities were added with `persist()`.

Fixes #7877, closes #7882.

Co-authored-by: Sylvain Fabre <sylvain.fabre@assoconnect.com>
2023-07-08 15:53:54 +02:00
Grégoire Paris
450cae2caa Add dummy title to the sidebar before checking docs
The way we have our docs, the sidebar is a separate document and as
such, needs a title. Let us prepend a dummy title until the guides-cli
provides a way to ignore that particular error.
2023-07-07 13:59:27 +02:00
Grégoire Paris
81ddeb426c Merge pull request #10823 from nicolas-grekas/mergeup 2023-07-07 13:09:11 +02:00
Nicolas Grekas
42e63bf358 Merge branch 2.15.x into 2.16.x
* 2.15.x: (23 commits)
  Fix cloning entities when using lazy-ghost proxies
  Fixes recomputation of single entity change set when entity contains enum attributes. Due to the fact that originalEntityData contains enum objects and ReflectionEnumProperty::getValue() returns value of enum, comparison of values are always falsy, resulting to update columns value even though it has not changes.
  Fix code style issues
  Use absolute references
  Avoid colon followed by double colon
  Use correct syntax for references
  Fix invalid reference syntax
  Use rst syntax
  Use internal link
  Escape pipes
  Introduce new workflow to test docs
  Remove lone dash (#10812)
  Treat id field proprites same as regular field
  Move three "Ticket/"-style tests to the right namespace
  Follow recommendation about multiline type
  Fix unserialize() errors when running tests on PHP 8.3 (#10803)
  Explain `EntityManager::getReference()` peculiarities (#10800)
  Upgrade to Psalm 5.13
  test: assert `postLoad` has data first
  distinct() updates QueryBuilder state correctly
  ...
2023-07-07 12:55:31 +02:00
Grégoire Paris
4978e0e336 Merge pull request #10819 from nicolas-grekas/fix-proxy-clone 2023-07-06 16:23:53 +02:00
Nicolas Grekas
eee87c376d Fix cloning entities when using lazy-ghost proxies 2023-07-06 15:08:59 +02:00
Grégoire Paris
0b9060c728 Merge pull request #10806 from rmikalkenas/fix-enum-recomputation 2023-07-06 10:23:59 +02:00
Grégoire Paris
514f6b8c28 Merge pull request #10813 from Greg0/fix-primary-id-mapping-xml-driver 2023-07-06 09:12:53 +02:00
Rokas Mikalkėnas
c1018fe299 Fixes recomputation of single entity change set when entity contains enum attributes.
Due to the fact that originalEntityData contains enum objects and
ReflectionEnumProperty::getValue() returns value of enum,
comparison of values are always falsy, resulting to update
columns value even though it has not changes.
2023-07-05 23:57:34 +03:00
Grzegorz Kuźnik
075824f5b5 Fix code style issues 2023-07-05 21:10:48 +02:00
Grégoire Paris
d6f4834476 Merge pull request #10815 from greg0ire/test-docs 2023-07-05 10:01:37 +02:00
Grégoire Paris
9dadffe270 Use absolute references
According to the Sphinx docs, when in reference/architecture.rst, a
reference to reference/inheritance-mapping would resolve to
reference/reference/inheritance-mapping.rst, because it is relative to
the current document
2023-07-04 17:44:44 +02:00
Grégoire Paris
b6e7e6d723 Avoid colon followed by double colon
It seems to confuse the guides-cli, if it is even valid.
2023-07-04 17:31:05 +02:00
Grégoire Paris
710937d6f8 Use correct syntax for references
doc was used when it is clearly a ref, plus there was a leading
underscore preventing the resolution.
2023-07-04 17:26:04 +02:00
Grégoire Paris
5d2d6642c8 Fix invalid reference syntax
Without this change, a hash is displayed for some reason.
2023-07-04 17:14:03 +02:00
Grégoire Paris
4d56711d8c Use rst syntax
Using underscore for emphasis is not an RST thing, in rst the difference
between emphasis and strong emphasis is in the number of asterisks.

Right now these underscores are just ignored and displayed on the
website.

See https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#emphasis
2023-07-04 17:11:46 +02:00
Grégoire Paris
a157bc3fb3 Use internal link 2023-07-04 17:05:47 +02:00
Grégoire Paris
1aeab391c7 Escape pipes
Pipes can be used to define substitutions, it is part of the rst
standard. This explains why some of the links in this document are not
displayed on the website.

See https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#substitution-definitions
2023-07-04 16:48:14 +02:00
Grégoire Paris
a4ecd02349 Introduce new workflow to test docs
This allows to check compatibility with phpDocumentor/guides, but also
should allow to spot embarassing mistakes in our existing docs.
2023-07-04 16:45:18 +02:00
Matthias Pigulla
bb21865cba Deprecate classes related to old commit order computation 2023-07-04 14:30:29 +02:00
Matthias Pigulla
606da9280d Un-prefix simple generics like list<> and array<>
... as suggested in GH review.
2023-07-04 14:17:14 +02:00
Grégoire Paris
21708e43c4 Merge pull request #10785 from mpdude/guard-duplicate-identity-map-entries 2023-07-04 10:03:04 +02:00
Grégoire Paris
8c59828f6c Remove lone dash (#10812) 2023-07-03 21:46:12 +02:00
Grzegorz K
0877ecbe56 Treat id field proprites same as regular field 2023-07-03 15:15:08 +02:00
Grégoire Paris
8eb69922e6 Merge pull request #10809 from mpdude/show-trouble-delete-before-insert
Add test to show why delete-before-insert may be challenging
2023-06-30 08:08:57 +02:00
Matthias Pigulla
e9b6fd89a4 Add test to show why delete-before-insert may be challenging
There are a few requests (#5742, #5368, #5109, #6776) that ask to change the order of operations in the UnitOfWork to perform "deletes before inserts", or where such a switch appears to solve a reported problem.

I don't want to say that this is not doable. But this PR at least adds two tricky examples where INSERTs need to be done before an UPDATE can refer to new database rows; and where the UPDATE needs to happen to release foreign key references to other entities before those can be DELETEd.

So, at least as long as all operations of a certain type are to be executed in blocks, this example allows no other order of operations than the current one.
2023-06-29 14:32:08 +02:00
Matthias Pigulla
01a14327d2 Add a safeguard against multiple objects competing for the same identity map entry
While trying to understand #3037, I found that it may happen that we have more entries in `\Doctrine\ORM\UnitOfWork::$entityIdentifiers` than in `\Doctrine\ORM\UnitOfWork::$identityMap`.

The former is a mapping from `spl_object_id` values to ID hashes, the latter an array first of entity class names and then from ID hash to entity object instances.

(Basically, "ID hash" is a concatenation of all field values making up the `@Id` for a given entity.)

This means that at some point, we must have _different_ objects representing the same entity, or at least over time different objects are used for the same entity without the UoW properly updating its `::$entityIdentifiers` structure.

I don't think it makes sense to overwrite an entity in the identity map, since that means a currently `MANAGED` entity is replaced with something else.

If it makes sense at all to _replace_ an entity, that should happen through dedicated management methods to first detach the old entity before persisting, merging or otherwise adding the new one. This way we could make sure the internal structures remain consistent.
2023-06-28 22:50:17 +02:00
Grégoire Paris
4887359827 Merge pull request #10807 from mpdude/move-tests
Move three "Ticket/"-style tests to the right namespace
2023-06-28 20:54:43 +02:00
Matthias Pigulla
2df1071e7a Remove references to the temporary branch in workflow definitions 2023-06-28 17:10:20 +02:00
Matthias Pigulla
5afe9b80a8 Move three "Ticket/"-style tests to the right namespace 2023-06-28 16:39:47 +02:00
Matthias Pigulla
7fc359c2bb Avoid unnecessarily passing entity lists into executeDeletions/executeInserts 2023-06-28 14:46:22 +02:00
Matthias Pigulla
853b9f75ae Merge remote-tracking branch 'origin/2.16.x' into commit-order-entity-level 2023-06-28 14:43:54 +02:00
Grégoire Paris
584c4aeed1 Merge pull request #10804 from greg0ire/parenthesized 2023-06-28 14:11:41 +02:00
Grégoire Paris
44d2a83e09 Merge pull request #10532 from mpdude/entity-persister-must-not-batch 2023-06-28 11:45:39 +02:00
Grégoire Paris
c9c5157fda Follow recommendation about multiline type
Apparently, there is consensus about multiline types between:

- PHPStan
- Psalm
- Slevomat Coding Standard

See https://github.com/slevomat/coding-standard/issues/1586#issuecomment-1610195706

Using parenthesis is less ambiguous, it makes it clear to the parser
where the type begins and where it ends.

The change has a positive impact on the Psalm baseline, showing
that psalm-return annotation was not really understood previously.
2023-06-28 07:46:35 +02:00
Grégoire Paris
dba90c1a91 Merge pull request #10786 from vuongxuongminh/fix-attach-entity-listener-when-reset-class-metadata-factory
Fix attach entity listener when reset class metadata factory
2023-06-27 23:53:01 +02:00
Grégoire Paris
5f079c2061 Merge pull request #10531 from mpdude/commit-order-must-be-entity-level
Add test: Commit order calculation must happen on the entity level
2023-06-27 23:52:33 +02:00
Grégoire Paris
476b68cd1f Merge pull request #10805 from greg0ire/valid-phpunit-xml
Validate phpunit.xml against PHPUnit 10 schema
2023-06-27 23:52:14 +02:00
Grégoire Paris
3ffd3f6509 Validate phpunit.xml against PHPUnit 10 schema
The previous syntax was a PHPUnit 9 syntax.
2023-06-27 23:13:06 +02:00
Nicolas Grekas
55d477dc50 Fix unserialize() errors when running tests on PHP 8.3 (#10803) 2023-06-27 17:47:09 +02:00
Matthias Pigulla
1733bf8678 Remove remaining references to the merge() operation (#10793)
`EntityManager::merge()` has been deprecated in #8461 and removed in #9488.

This PR removes a few remaining references and artefacts that - to my understanding - refer to it.
2023-06-27 10:27:39 +02:00
Grégoire Paris
4da8d3be96 Resort on Query::HINT_FORCE_PARTIAL_LOAD less
A lot of our tests mention it, but I do not think it is important to the
test. Maybe it was a way to have more efficient tests? Most times,
removing the hint does not affect the test outcome.
2023-06-27 08:37:05 +02:00
Matthias Pigulla
4aadba65ce Explain EntityManager::getReference() peculiarities (#10800)
* Explain `EntityManager::getReference()` peculiarities

As one takeaway from https://github.com/doctrine/orm/issues/3037#issuecomment-1605657003 and #843, we should look into better explaining the `EntityManager::getReference()` method, it’s semantics, caveats and potential responsibilities placed on the user.

This PR tries to do that, so it fixes #10797.

* Update docs/en/reference/advanced-configuration.rst

Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>

---------

Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2023-06-27 00:16:55 +02:00
Grégoire Paris
814d8d4d39 Merge pull request #10802 from greg0ire/psalm-5-13
Upgrade to Psalm 5.13
2023-06-27 00:05:00 +02:00
Grégoire Paris
dc411954ad Upgrade to Psalm 5.13
This is a nice release as far as the ORM is concerned:
- a small baseline reduction;
- lots of useless calls to sprintf spotted.
2023-06-26 19:12:02 +02:00
Minh Vuong
da29eb675c test: assert postLoad has data first 2023-06-26 09:29:00 +07:00
Grégoire Paris
b17e52ba6b Merge pull request #10791 from mpdude/understand-3037
Avoid creating unmanaged proxy instances for referred-to entities during `merge()`
2023-06-25 23:52:53 +02:00
Grégoire Paris
7ef4afc688 Merge pull request #10743 from mpdude/post-insert-id-early
Make EntityPersisters tell the UoW about post insert IDs early
2023-06-25 23:51:15 +02:00
Grégoire Paris
4e138903d0 Merge pull request #10789 from macroparts/distinct-updates-state-correctly
distinct() updates QueryBuilder state correctly
2023-06-25 18:11:37 +02:00
Daniel Jurkovic
efb50b9bdd distinct() updates QueryBuilder state correctly
Previously calling distinct() when the QueryBuilder was in clean state would cause subsequent getDQL() calls to ignore the distinct queryPart

Fixes #10784
2023-06-25 17:53:24 +02:00
Grégoire Paris
84a87a6ac8 Merge remote-tracking branch 'origin/2.16.x' into 3.0.x 2023-06-24 11:15:42 +02:00
Grégoire Paris
70bcff7410 Merge pull request #10794 from doctrine/2.15.x
Merge 2.15.x up into 2.16.x
2023-06-23 23:22:31 +02:00
Matthias Pigulla
1989531d4f Update tests/Doctrine/Tests/ORM/Functional/Ticket/GH7407Test.php
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2023-06-23 22:47:34 +02:00
Grégoire Paris
f778d8cf98 Merge pull request #10792 from greg0ire/entity-level-commit-order
Entity level commit order
2023-06-23 22:37:10 +02:00
Grégoire Paris
18b32ab9db Merge remote-tracking branch 'origin/2.15.x' into entity-level-commit-order 2023-06-23 22:21:53 +02:00
Matthias Pigulla
d738ecfcfe Avoid creating unmanaged proxy instances for referred-to entities during merge()
This PR tries to improve the situation/problem explained in #3037:

Under certain conditions – there may be multiple and not all are known/well-understood – we may get inconsistencies between the `\Doctrine\ORM\UnitOfWork::$entityIdentifiers` and `\Doctrine\ORM\UnitOfWork::$identityMap` arrays.

Since the `::$identityMap` is a plain array holding object references, objects contained in it cannot be garbage-collected.
`::$entityIdentifiers`, however, is indexed by `spl_object_id` values. When those objects are destructed and/or garbage-collected, the OID may be reused and reassigned to other objects later on.

When the OID re-assignment happens to be for another entity, the UoW may assume incorrect entity states and, for example, miss INSERT or UPDATE operations.

One cause for such inconsistencies is _replacing_ identity map entries with other object instances: This makes it possible that the old object becomes GC'd, while its OID is not cleaned up. Since that is not a use case we need to support (IMHO), #10785 is about adding a safeguard against it.

In this test shown here, the `merge()` operation is currently too eager in creating a proxy object for another referred-to entity. This proxy represents an entity already present in the identity map at that time, potentially leading to this problem later on.
2023-06-23 22:19:06 +02:00
Matthias Pigulla
aa3ff458c7 Add test: Commit order calculation must happen on the entity level
Add tests for entity insertion and deletion that require the commit order calculation to happen on the entity level. This demonstrates the necessity for the changes in #10547.

This PR contains two tests with carefully constructed entity relationships, where we have a non-nullable `parent` foreign key relationships between entities stored in the same table.

Class diagram:

```mermaid
classDiagram
    direction LR
    class A
    class B
    A --> B : parent
    B --|> A
```

Object graph:

```mermaid
graph LR;
    b1 --> b2;
    b2 --> a;
    b3 --> b2;
```

 #### Situation before #10547

The commit order is computed by looking at the associations at the _table_ (= _class_) level. Once the ordering of _tables_ has been found, entities being mapped to the same table will be processed in the order they were given to `persist()` or `remove()`.

That means only a particular ordering of `persist()` or `remove()` calls (see comment in the test) works:

For inserts, the order must be `$a, $b2, $b1, $b3` (or `... $b3, $b1`), for deletions `$b1, $b3, $b2, $a`.

 #### Situation with entity-level commit order computation (as in #10547)

The ORM computes the commit order by considering associations at the _entity_ level. It will be able to find a working order by itself.
2023-06-23 22:14:04 +02:00
Grégoire Paris
f76bab2b73 Merge pull request #10790 from greg0ire/slevomat-cs-upgrade
Work around slevomat/coding-standard issues
2023-06-23 22:13:30 +02:00
Grégoire Paris
0e06d6b67d Apply latest coding standard rules 2023-06-23 18:11:22 +02:00
Grégoire Paris
5114dcee0b Work around slevomat/coding-standard issues
I tweaked the code so that it would not fall victim to
https://github.com/slevomat/coding-standard/issues/1585 or
https://github.com/slevomat/coding-standard/issues/1586, thus fixing the
phpcs job without losing information or breaking other jobs.
2023-06-23 18:11:07 +02:00
Matthias Pigulla
8bc74c624a Make EntityPersisters tell the UoW about post insert IDs early
This refactoring does two things:

* We can avoid collecting the post insert IDs in a cumbersome array structure that will be returned by the EntityPersisters and processed by the UoW right after. Instead, use a more expressive API: Make the EntityPersisters tell the UoW about the IDs immediately.
* IDs will be available in inserted entities a tad sooner. That may help to resolve #10735, where we can use the IDs to skip extra updates.
2023-06-23 09:08:07 +02:00
Grégoire Paris
6c0a5ecbf9 Merge pull request #10787 from doctrine/2.15.x-merge-up-into-2.16.x_XV3tWpNu 2023-06-22 16:01:49 +02:00
Grégoire Paris
5f6501f842 Merge remote-tracking branch 'origin/2.15.x' into 2.15.x-merge-up-into-2.16.x_XV3tWpNu 2023-06-22 14:44:27 +02:00
Alexander Dmitryuk
4c3bd20801 Fix missing setFilterSchemaAssetsExpression in phpdoc (#10776) 2023-06-22 14:36:06 +02:00
Grégoire Paris
f2abf6143b Merge pull request #10763 from mpdude/defer-collection-entity-removals-to-post-commit 2023-06-22 14:35:20 +02:00
Minh Vuong
338deacb58 fix: attach entity listener when reset metadata factory 2023-06-22 17:02:24 +07:00
Grégoire Paris
6fa95b93df Merge pull request #10778 from greg0ire/lifecycle-embedded-class 2023-06-22 10:04:53 +02:00
Grégoire Paris
829d5fbb9f Merge pull request #10780 from greg0ire/avoid-partial 2023-06-22 10:04:27 +02:00
Matthias Pigulla
d220494edc Improve documentation on exact behaviour of many-to-many deletion operations 2023-06-21 19:14:55 +02:00
Matthias Pigulla
c235901544 Move a check up (continue early) 2023-06-21 19:14:55 +02:00
Matthias Pigulla
ba089e551a Avoid unnecessary changes 2023-06-21 19:14:55 +02:00
Matthias Pigulla
ee0b3f214d Write tests more concisely 2023-06-21 19:14:55 +02:00
Matthias Pigulla
930fa831b2 Test expected query counts in ManyToManyBasicAssociationTest
When collection updates/join table cleanups do not happen through specialized Entity-/CollectionPersister methods but instead as "plain" updates, we may issue a lot more queries than expected.
2023-06-21 19:14:55 +02:00
Matthias Pigulla
98b404875f Defer removing removed entities from to-many collections until after transaction commit 2023-06-21 19:14:55 +02:00
Grégoire Paris
2004761475 Merge pull request #10777 from greg0ire/cleanup-bc-layers
Turn deprecation into an exception
2023-06-21 16:23:06 +02:00
Grégoire Paris
3ad9c43a96 Merge pull request #10782 from andersonamuller/patch-2 2023-06-19 13:25:19 +02:00
Anderson Müller
1bd3066b9f Remove missed note about deprecated drivers 2023-06-19 11:21:17 +02:00
Grégoire Paris
fcc5c106b4 Rely on partial objects less when in tests
Partial objects are deprecated. They were handy to make the generated
SQL more legible, but we should refrain from relying on them.
2023-06-18 18:20:29 +02:00
Grégoire Paris
5132f0deb0 Stop using $message argument
It brings nothing over what PHPUnit now natively does.
2023-06-18 18:16:29 +02:00
Grégoire Paris
663763ab1a Disallow lifecycle callbacks on embedded classes 2023-06-17 16:18:57 +02:00
Grégoire Paris
2a8f22c521 Turn deprecation into an exception 2023-06-17 15:43:12 +02:00
Grégoire Paris
fe8e313731 Merge pull request #10747 from wtfzdotnet/feature/fix-one-to-many-custom-id-orphan-removal 2023-06-16 10:07:29 +02:00
Grégoire Paris
41f704cd96 Merge pull request #10775 from doctrine/2.15.x
Merge 2.15.x up into 2.16.x
2023-06-13 20:10:31 +02:00
Grégoire Paris
1adb5c0c70 Merge pull request #10774 from greg0ire/document-dto-in-rsm 2023-06-12 13:52:10 +02:00
Grégoire Paris
e5174af669 Document how to produce DTOs with a result set mapping 2023-06-11 18:02:18 +02:00
Grégoire Paris
efd429dd24 Merge pull request #10769 from greg0ire/cleanup-bc-layers
Remove Notify change tracking policy
2023-06-10 22:59:33 +02:00
Vaidas
c3106f9fe7 Restore document proxy state to uninitialized on load exception (#10645) 2023-06-09 08:54:22 +02:00
Alexander M. Turek
cbf45dd97e PHPStan 1.10.18, Psalm 5.12.0 (#10771) 2023-06-08 16:57:07 +02:00
Grégoire Paris
716139c168 Remove Notify change tracking policy 2023-06-07 21:16:17 +02:00
Grégoire Paris
492635a8e8 Merge pull request #10768 from greg0ire/cleanup-bc-layers
Enable XML validation unconditionally
2023-06-07 08:19:49 +02:00
Grégoire Paris
0dad2daf2c Enable XML validation unconditionally
Note that this makes ext-dom a hard requirement when using the XML
driver.
2023-06-06 23:29:56 +02:00
Michael Roterman
3c0d140e52 OneToManyPersister does not take custom identifier types into account for orphan removal.
In my case a custom doctrine type of Uuid object is converted to string by simply casting it, resulting in a hex DELETE FROM x WHERE id = ? query,
whilst it should've been converted along the way to it's binary representation. This leads to no deletions being made at all as you would expect making use of doctrine custom type's as an identifier.

This commit fixes usage of ramsey/uuid or symfony/uid as custom id types when making use of orphan removal.
2023-06-06 19:51:41 +02:00
Michael Roterman
33675ff4a9 fix: Update baseline and assertions for OneToManyPersister 2023-06-06 18:18:26 +02:00
Grégoire Paris
e0b72408a1 Merge pull request #10764 from greg0ire/cleanup-bc-layers 2023-06-06 11:42:14 +02:00
Alexander M. Turek
5c74795893 Merge 2.15.x into 2.16.x (#10765) 2023-06-06 11:30:27 +02:00
Nicolas Grekas
3827dd769e Don't call deprecated getSQLResultCasing and usesSequenceEmulatedIdentityColumns when we know the platform (#10759) 2023-06-06 11:27:31 +02:00
Grégoire Paris
575d0c03ee Reject non instances of ORM\ClassMetadata 2023-06-06 08:49:30 +02:00
Grégoire Paris
a2a4f73b30 Enforce reporting fields where declared 2023-06-06 08:49:30 +02:00
Grégoire Paris
f1d6ba8919 Narrow types 2023-06-06 00:05:05 +02:00
Grégoire Paris
0872d1429d Add missing upgrade notes 2023-06-05 23:43:25 +02:00
Grégoire Paris
96f5f84e8b Merge pull request #10741 from greg0ire/cleanup-bc-layers
Cleanup bc layers
2023-06-05 23:26:28 +02:00
Grégoire Paris
0945f60484 Remove backward-compatibility layer
Note that we also remove UpdateCommandTest::testItPrintsTheSql() because
it relied on not passing --complete to work.
2023-06-05 23:08:31 +02:00
Grégoire Paris
f38922944e Remove unneeded DeprecatedProperty rule
That property has been removed from 3.0.x
2023-06-05 23:08:31 +02:00
Grégoire Paris
63e9ad9e9a Remove unneeded ignore rule
The linked issue has been addressed, this rules should have been removed
during a merge up, as it is no longer present on 2.x
2023-06-05 23:08:31 +02:00
Nicolas Grekas
6c9b29f237 Don't call canEmulateSchemas in SchemaTool when possible (#10762) 2023-06-05 21:42:13 +02:00
Grégoire Paris
2afe2dc8af Merge pull request #10758 from Gwemox/partial-revert-enum-id-hash 2023-06-05 11:41:32 +02:00
Thibault Buathier
cc3d872b95 revert: transform backed enum to value 2023-06-05 10:58:32 +02:00
Grégoire Paris
46ff264502 Merge remote-tracking branch 'origin/2.16.x' into 3.0.x 2023-06-05 09:36:36 +02:00
Grégoire Paris
8961bfe90c Merge pull request #10756 from doctrine/2.15.x
Merge 2.15.x up into 2.16.x
2023-06-05 09:11:52 +02:00
Grégoire Paris
15e3a7e861 Merge pull request #10751 from mpdude/7180-fixed
Add test to show #7180 has been fixed
2023-06-05 08:35:40 +02:00
Grégoire Paris
65dc154ce5 Merge pull request #10754 from greg0ire/fix-build
Fix build
2023-06-05 08:35:26 +02:00
Grégoire Paris
1280e005b6 Merge pull request #10755 from mpdude/9192-fixed
Add test to show #9192 has been fixed
2023-06-04 22:08:17 +02:00
Matthias Pigulla
79f53d5dae Add test to show #9192 has been fixed
This test implements the situation described in #9192. The commit order computation will be fixed by #10547.
2023-06-04 19:46:16 +00:00
Grégoire Paris
caaa0d6192 Ignore error about get_class($metadata)
This is the result of the contradiction between the phpdoc
(ClassMetadata), and the condition, which guarantees $metadata is not a
ClassMetadata. Relaxing the phpdoc leads to other phpstan issues, about
properties that exist in ClassMetadata but not in
PersistentClassMetadata. The right way to fix this would be to switch
from a deprecation to an exception, but that is not the path we have
taken, and all this will disappear in 3.0.x anyway, so let's not bother.
2023-06-03 20:59:29 +02:00
Grégoire Paris
68d3a63957 Use class name directly
Static analysis points out $this->getName() may return null. But there
is worse: the message mentions a "command class", and getName() is not a
class.
2023-06-03 20:59:29 +02:00
Matthias Pigulla
bf2937e63a Add test: Entity insertions must not happen table-wise
Add tests for entity insertion and deletion that require writes to different tables in an interleaved fashion, and that have to re-visit a particular table.

 #### Background

In #10531, I've given an example where it is necessary to compute the commit order on the entity (instead of table) level.

Taking a closer look at the UoW to see how this could be achieved, I noticed that the current, table-level commit order manifests itself also in the API between the UoW and `EntityPersister`s.

 #### Current situation

The UoW computes the commit order on the table level. All entity insertions for a particular table are passed through `EntityPersister::addInsert()` and finally written through `EntityPersister::executeInserts()`.

 #### Suggested change

The test in this PR contains a carefully constructed set of four entities. Two of them are of the same class (are written to the same table), but require other entities to be processed first.

In order to be able to insert this set of entities, the ORM must be able to perform inserts for a given table repeatedly, interleaved with writing other entities to their respective tables.
2023-06-03 13:07:41 +00:00
Matthias Pigulla
76b8a215c2 Update docs that name in @Index/@UniqueConstraint is optional (#10748)
Fixes #4283.
2023-06-03 00:14:43 +02:00
Matthias Pigulla
b163cea61c Update the FAQ entry on setting MySQL charset and collation for columns (#10746)
Fixes #2986.
2023-06-03 00:13:07 +02:00
Grégoire Paris
ed212ab924 Merge pull request #10749 from mpdude/6499-fixed
Add tests to show #6499 has been fixed
2023-06-02 23:36:44 +02:00
Matthias Pigulla
dd0e02e912 Add test to show #7180 has been fixed
Tests suggested in https://github.com/doctrine/orm/pull/7180#issuecomment-380841413 and https://github.com/doctrine/orm/pull/7180#issuecomment-381067448 by @arnaud-lb.

Co-authored-by: Arnaud Le Blanc <arnaud.lb@gmail.com>
2023-06-02 21:28:11 +00:00
Matthias Pigulla
aad875eea1 Add tests to show #6499 has been fixed
@frikkle was the first to propose these tests in #6533.
@rvanlaak followed up in #8703, making some adjustments.

Co-authored-by: Gabe van der Weijde <gabe.vanderweijde@triasinformatica.nl>
Co-authored-by: Richard van Laak <rvanlaak@gmail.com>
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2023-06-02 21:14:17 +00:00
Grégoire Paris
84ab535e56 Merge pull request #10750 from mpdude/7006-fixed
Add test to show #7006 has been fixed
2023-06-02 22:07:47 +02:00
Matthias Pigulla
a72a0c3597 Update tests/Doctrine/Tests/ORM/Functional/Ticket/GH7006Test.php
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2023-06-02 22:00:20 +02:00
Matthias Pigulla
6217285544 Add test to show #7006 has been fixed 2023-06-02 17:52:51 +00:00
Grégoire Paris
330c0bc67e Merge pull request #10689 from mpdude/insert-entity-level-topo-sort 2023-06-02 15:21:08 +02:00
Grégoire Paris
b5595ca041 Merge pull request #10732 from mpdude/10348-fixed
Add a test case to show #10348 has been fixed
2023-06-02 07:50:03 +02:00
Grégoire Paris
4dfbe13897 Merge pull request #10740 from greg0ire/remove-ignore-rule
Remove useless ignore rule
2023-06-02 00:14:27 +02:00
Grégoire Paris
b64e1c9b1f Remove useless ignore rule
This is useless since 152f91fa3
2023-06-01 21:03:58 +02:00
Grégoire Paris
b779b112f3 Merge pull request #10738 from doctrine/2.15.x-merge-up-into-2.16.x_PvK1bbO1 2023-06-01 11:45:08 +02:00
Grégoire Paris
bf449bef7d Merge pull request #10737 from nicolas-grekas/lexer-deprec 2023-06-01 11:35:50 +02:00
Nicolas Grekas
152f91fa33 Fix deprecations from doctrine/lexer 2023-06-01 11:22:36 +02:00
Grégoire Paris
14d1eb5340 Document pdo_sqlite requirement for tests (#10734) 2023-06-01 08:57:07 +02:00
Matthias Pigulla
04e08640fb Add a test case to show #10348 has been fixed by #10566
This is part of the series of issues fixed by #10547. In particular, the changes from #10566 were relevant.

See #10348 for the bug description.

Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2023-05-31 21:38:42 +00:00
Matthias Pigulla
aa27b3a35f Remove the now unused UnitOfWork::getCommitOrder() method 2023-05-31 07:31:56 +00:00
Matthias Pigulla
d76fc4ebf6 Compute entity-level commit order for entity insertions
This is the third step to break https://github.com/doctrine/orm/pull/10547 into smaller PRs suitable for reviewing. It uses the new topological sort implementation from #10592 and the refactoring from #10651 to compute the UoW's commit order for entity insertions not on the entity class level, but for single entities and their actual dependencies instead.

 #### Current situation

`UnitOfWork::getCommitOrder()` would compute the entity sequence on the class level with the following code:

70477d81e9/lib/Doctrine/ORM/UnitOfWork.php (L1310-L1325)

 #### Suggested change

* Instead of considering the classes of all entities that need to be inserted, updated or deleted, consider the new (inserted) entities only. We only need to find a sequence in situations where there are foreign key relationships between two _new_ entities.
* In the dependency graph, add edges for all to-one association target entities.
* Make edges "optional" when the association is nullable.

 #### Test changes

I have not tried to fully understand the few changes necessary to fix the tests. My guess is that those are edge cases where the insert order changed and we need to consider this during clean-up.

Keep in mind that many of the functional tests we have assume that entities have IDs assigned in the order that they were added to the EntityManager. That does not change – so the order of entities is generally stable, equal to the previous implementation.
2023-05-31 07:16:16 +00:00
Grégoire Paris
8b1ce48e79 Merge pull request #10730 from greg0ire/join-column-mapping
Migrate to the object API of Join{Column,Table}Mapping
2023-05-31 00:28:12 +02:00
Grégoire Paris
da0998c401 Add missing underscore to RST links (#10731) 2023-05-30 23:00:28 +02:00
Matthias Pigulla
ae60cf005f Commit order for removals has to consider SET NULL, not nullable (#10566)
When computing the commit order for entity removals, we have to look out for `@ORM\JoinColumn(onDelete="SET NULL")` to find places where cyclic associations can be broken.

 #### Background

The UoW computes a "commit order" to find the sequence in which tables shall be processed when inserting entities into the database or performing delete operations.

For the insert case, the ORM is able to schedule _extra updates_ that will be performed after all entities have been inserted. Associations which are configured as `@ORM\JoinColumn(nullable=true, ...)` can be left as `NULL` in the database when performing the initial `INSERT` statements, and will be updated once all new entities have been written to the database. This can be used to break cyclic associations between entity instances.

For removals, the ORM does not currently implement up-front `UPDATE` statements to `NULL` out associations before `DELETE` statements are executed. That means when associations form a cycle, users have to configure `@ORM\JoinColumn(onDelete="SET NULL", ...)` on one of the associations involved. This transfers responsibility to the DBMS to break the cycle at that place.

_But_, we still have to perform the delete statements in an order that makes this happen early enough. This may be a _different_ order than the one required for the insert case. We can find it _only_ by looking at the `onDelete` behaviour. We must ignore the `nullable` property, which is irrelevant, since we do not even try to `NULL` anything.

 #### Example

Assume three entity classes `A`, `B`, `C`. There are unidirectional one-to-one associations `A -> B`, `B -> C`, `C -> A`. All those associations are `nullable= true`.

Three entities `$a`, `$b`, `$c` are created from these respective classes and associations are set up.

All operations `cascade` at the ORM level. So we can test what happens when we start the operations at the three individual entities, but in the end, they will always involve all three of them.

_Any_ insert order will work, so the improvements necessary to solve #10531 or #10532 are not needed here. Since all associations are between different tables, the current table-level computation is good enough.

For the removal case, only the `A -> B` association has `onDelete="SET NULL"`. So, the only possible execution order is `$b`, `$c`, `$a`. We have to find that regardless of where we start the cascade operation.

The DBMS will set the `A -> B` association on `$a` to `NULL` when we remove `$b`. We can then remove `$c` since it is no longer being referred to, then `$a`.

 #### Related cases

These cases ask for the ORM to perform the extra update before the delete by itself, without DBMS-level support:
* #5665
* #10548
2023-05-30 22:58:36 +02:00
Grégoire Paris
07674b1887 Migrate to the object API of Join{Column,Table}Mapping 2023-05-30 08:52:02 +02:00
Grégoire Paris
ec43884612 Merge pull request #10729 from greg0ire/mandatory-table-name
Make the join table name and join column name mandatory
2023-05-30 08:43:21 +02:00
Grégoire Paris
ee62934911 Make the join column name mandatory 2023-05-28 23:28:15 +02:00
Grégoire Paris
8a6dbb4ae2 Make the join table name mandatory
It does not seem to ever be empty
2023-05-26 18:17:25 +02:00
Grégoire Paris
2a8a886bbe Merge pull request #10728 from greg0ire/declare-options
Declare options property
2023-05-25 23:55:06 +02:00
Grégoire Paris
2b03858717 Declare options property
This must have been lost when merging up d7d6b9d2c7
2023-05-25 17:27:17 +02:00
Grégoire Paris
497faffe0b Merge pull request #10723 from greg0ire/association-mapping-object-api 2023-05-25 10:30:19 +02:00
Alexander M. Turek
ddd3066bc4 Revert "Allow symfony/console 7 (#10724)"
This reverts commit 6662195936.
2023-05-25 08:48:53 +02:00
Alexander M. Turek
6662195936 Allow symfony/console 7 (#10724) 2023-05-25 08:47:35 +02:00
Grégoire Paris
cc011d8215 Merge pull request #10725 from doctrine/2.14.x
Merge 2.14.x up into 2.15.x
2023-05-24 14:08:21 +02:00
Grégoire Paris
d831c126c9 Merge pull request #10643 from htto/bugfix/sti-with-abstract-intermediate
Fix single table inheritance with intermediate abstract class(es)
2023-05-24 11:58:11 +02:00
Grégoire Paris
10eae1a7ff Merge pull request #10722 from phansys/query_single_result_exception
Fix and improve functional test cases expecting `NonUniqueResultException` from `AbstractQuery::getSingleScalarResult()`
2023-05-23 22:46:18 +02:00
Grégoire Paris
8a762f04f1 Manually fix remaining issues 2023-05-23 13:34:39 +02:00
Grégoire Paris
bbc56aaec6 Ignore issue about collections 2023-05-23 13:34:39 +02:00
Grégoire Paris
647712649b Add assertions 2023-05-23 13:34:39 +02:00
Grégoire Paris
61f2c4d53b Allow ClassMetadata::FETCH_EXTRA_LAZY as a value for
ClassMetadata->$fetch
2023-05-23 13:34:39 +02:00
Grégoire Paris
ca8ee91467 Leverage ClassMetadataFactory::getOwningSide() 2023-05-23 13:34:38 +02:00
Grégoire Paris
2987e9956f Add assertion 2023-05-23 13:34:38 +02:00
Grégoire Paris
917e0cff39 Move assertion 2023-05-23 13:34:38 +02:00
Grégoire Paris
6ce0cf4a3d Add assertions based on joinColumns access 2023-05-23 13:34:37 +02:00
Grégoire Paris
d4915a8b3d Ignore unfixable error 2023-05-23 13:34:37 +02:00
Grégoire Paris
749947efe7 Clarify things for SA 2023-05-23 13:34:37 +02:00
Grégoire Paris
535d869835 Ignore issue due to Psalm bug 2023-05-23 13:34:37 +02:00
Grégoire Paris
ea23628010 Rectorify 2023-05-23 13:34:37 +02:00
Grégoire Paris
d951aa05b9 Merge pull request #10721 from phansys/query_single_result 2023-05-23 11:33:49 +02:00
Javier Spagnoletti
be297b9fd3 Narrow return types for AbstractQuery::getSingleScalarResult() 2023-05-23 05:47:39 -03:00
Javier Spagnoletti
125e18cf24 Fix and improve functional test cases expecting NonUniqueResultException from AbstractQuery::getSingleScalarResult() 2023-05-23 05:32:38 -03:00
Grégoire Paris
10fa1e07b2 Merge remote-tracking branch 'origin/2.16.x' into 3.0.x 2023-05-16 17:42:44 +02:00
Grégoire Paris
8fba9d6868 Merge pull request #10708 from mbabker/2.15-link-fix 2023-05-16 17:06:17 +02:00
Michael Babker
7f4f1cda71 Correct docs link 2023-05-16 09:38:09 -05:00
Grégoire Paris
c32efc2588 Merge pull request #10699 from greg0ire/narrow-down-param-type-qs
Narrow down parameter types for quote strategies
2023-05-16 08:20:47 +02:00
Grégoire Paris
4e137f77a5 Merge pull request #10704 from greg0ire/drop-useless-block
Remove unreachable piece of code
2023-05-16 08:19:42 +02:00
Grégoire Paris
a33aa15c79 Remove unreachable piece of code
mappedBy is never defined on an inverse relationship.
Bi-directional self-referencing should IMO still result in 2 separate
associations, on 2 separate fields of the same class, like mentor or
mentee.
2023-05-15 14:10:22 +02:00
Grégoire Paris
255ce51526 Merge pull request #10703 from doctrine/2.15.x 2023-05-15 12:05:48 +02:00
Grégoire Paris
1c905b0e0a Merge pull request #10702 from greg0ire/fix-build 2023-05-15 11:53:09 +02:00
Grégoire Paris
7901790b97 Adapt to latest coding standards 2023-05-15 11:42:13 +02:00
Grégoire Paris
6032a2ccf7 Use OneToManyPersister::getMapping() more
Not sure how I forgot these.
2023-05-15 09:27:07 +02:00
Grégoire Paris
1f9d1bf4cb Narrow down parameter type declarations for quote strategies 2023-05-15 09:10:11 +02:00
Grégoire Paris
dff40cf351 Narrow down templated method return type
Maybe we do not know enough about the parameter to determine the type of
the returned relationship, but we can at least narrow it down to 3
possibilites.
2023-05-15 08:57:23 +02:00
Grégoire Paris
a55c72b47d Merge pull request #10701 from greg0ire/convenience
Introduce convenience methods to narrow types
2023-05-15 08:19:05 +02:00
Grégoire Paris
f03db50be1 Merge pull request #10697 from greg0ire/narrow-down-assoc-mapping-type
Narrow down ClassMetadata::associationMappings type
2023-05-14 23:28:38 +02:00
Grégoire Paris
2a77776c91 Merge pull request #10700 from greg0ire/wrong-phpdoc-getdefiningclass
fix wrong phpdoc
2023-05-14 23:22:59 +02:00
Grégoire Paris
c51c84fc47 Introduce convenience methods to narrow types
These methods assert the type of the mapping provided by the collection
according to the name of the class they are in: the one to many
persister only ever deals with one to many associations, and the many to
many persister only ever deals with many to many associations.
2023-05-13 11:33:08 +02:00
Grégoire Paris
00beecce74 fix wrong phpdoc
The keys in the join columns array have no meaning, and are just
sequential integers.
2023-05-13 11:24:01 +02:00
Grégoire Paris
9f60fdc288 Merge pull request #10698 from greg0ire/move-join-column-fieldnames-down
Move joinColumnFieldNames down the class hierarchy
2023-05-12 23:22:40 +02:00
Grégoire Paris
3b88e4844a Move joinColumnFieldNames down the class hierarchy
It has only meaning for ToOneOwningSideMapping
2023-05-12 21:17:20 +02:00
Grégoire Paris
63561fc382 Narrow down ClassMetadata::associationMappings type 2023-05-12 08:24:07 +02:00
Grégoire Paris
cef1d2d740 Merge pull request #10666 from MatTheCat/inherited-readonly-properties
Create `ReflectionReadonlyProperty` from their declaring class so their value can be set
2023-05-12 07:50:03 +02:00
Grégoire Paris
caa8041963 Merge pull request #10696 from greg0ire/templating-getowningside
Add templating for getOwningSide
2023-05-12 07:48:56 +02:00
Grégoire Paris
8126882305 Merge pull request #10486 from mpdude/fix-to-many-update-on-delete
Fix to-many collections left in dirty state after entities are removed by the UoW
2023-05-12 00:11:56 +02:00
Matthias Pigulla
a9513692cb Fix to-many collections left in dirty state after entities are removed by the UoW 2023-05-12 00:02:44 +02:00
Grégoire Paris
52c3d9d82a Merge pull request #10508 from Gwemox/fix-enum-identity
Fix id hash of entity with enum as identifier
2023-05-12 00:00:20 +02:00
Grégoire Paris
1c8b5181b5 Add templating for getOwningSide
It allows to remove many assertions.
2023-05-11 22:08:05 +02:00
MatTheCat
2f46e5a130 Rename test class and method 2023-05-11 09:36:43 +02:00
Mathieu
a3fa1d7faa Replace assertions by @doesNotPerformAssertions 2023-05-11 09:33:12 +02:00
MatTheCat
c7c57be0c2 Create ReflectionReadonlyProperty from their declaring class so their value can be set 2023-05-11 09:33:12 +02:00
MatTheCat
721794fb9c Add test case 2023-05-11 09:33:12 +02:00
Grégoire Paris
e5eaf9b855 Merge pull request #10688 from greg0ire/cmf-getowningassoc
Introduce method to get to the owning side
2023-05-09 07:42:22 +02:00
Grégoire Paris
380f8a42f3 Introduce method to get to the owning side
Throughout the codebase, there is this pattern where we ensure we have
the owning side of an association.
It involves accessing it from the associationMappings array. In the end,
static analysis cannot know that the association is indeed owning.
By introducing this convenience method, we make this clear, and also
delegate the complexity to the class metadata factory.
2023-05-08 17:33:15 +02:00
Grégoire Paris
38e47fdeab Merge pull request #10455 from mpdude/fix-mapping-driver-load
Make Annotations/Attribute mapping drivers report fields for the classes where they are declared
2023-05-08 15:46:54 +02:00
Grégoire Paris
05b5a64cb9 Make indexBy/orderBy easier to understand for SA (#10687)
Interfaces cannot have properties, and we do not have a concept of
sealed classes available to us without installing third party packages.
Interfaces can have methods however, which allows us to simplify calling
code.
I've been avoiding introducing getters for mapping properties because I
do not know what the performance implications are, but here, I think it
is sensible to make an exception, given the benefits.
2023-05-08 15:24:10 +02:00
Matthias Pigulla
9ac063d879 Add a new topological sort implementation (#10592)
This is the first chunk to break #10547 into smaller PRs suitable for reviewing. It adds a new topological sort implementation.

 #### Background

Topological sort is an algorithm that sorts the vertices of a directed acyclic graph (DAG) in a linear order such that for every directed edge from vertex A to vertex B, vertex A comes before vertex B in the ordering. This ordering is called a topological order.

Ultimately (beyond the scope of this PR), in the ORM we'll need this to find an order in which we can insert new entities into the database. When one entity needs to refer to another one by means of a foreign key, the referred-to entity must be inserted before the referring entity. Deleting entities is similar.

A topological sorting can be obtained by running a depth first search (DFS) on the graph. The order in which the DFS finishes on the vertices is a topological order. The DFS is possible iif there are no cycles in the graph. When there are cycles, the DFS will find them.

For more information about topological sorting, as well as a description of an DFS-based topological sorting algorithm, see https://en.wikipedia.org/wiki/Topological_sorting.

 #### Current situation

There is a DFS-based topological sorting implemented in the `CommitOrderCalculator`. This implementation has two kinks:

1. It does not detect cycles

When there is a cycle in the DAG that cannot be resolved, we need to know about it. Ultimately, this means we will not be able to insert entities into the database in any order that allows all foreign keys constraints to be satisfied.

If you look at `CommitOrderCalculator`, you'll see that there is no code dealing with this situation.

2. It has an obscure concept of edge "weights"

To me, it is not clear how those are supposed to work. The weights are related to whether a foreign key is nullable or not, but can (could) be arbitrary integers. An edge will be ignored if it has a higher (lower) weight than another, already processed edge... 🤷🏻?

 #### Suggested change

In fact, when inserting entities into the database, we have two kinds of foreign key relationships: Those that are `nullable`, and those that are not.

Non-nullable foreign keys are hard requirements: Referred-to entities must be inserted first, no matter what. These are "non-optional" edges in the dependency graph.

Nullable foreign keys can be set to `NULL` when first inserting an entity, and then coming back and updating the foreign key value after the referred-to (related) entity has been inserted into the database. This is already implemented in `\Doctrine\ORM\UnitOfWork::scheduleExtraUpdate`, at the expense of performing one extra `UPDATE` query after all the `INSERT`s have been processed. These edges are "optional".

When finding a cycle that consists of non-optional edges only, treat it as a failure. We won't be able to insert entities with a circular dependency when all foreign keys are non-NULLable.

When a cycle contains at least one optional edge, we can use it to break the cycle: Use backtracking to go back to the point before traversing the last _optional_ edge. This omits the edge from the topological sort order, but will cost one extra UPDATE later on.

To make the transition easier, the new implementation is provided as a separate class, which is marked as `@internal`.

 #### Outlook

Backtracking to the last optional edge is the simplest solution for now. In general, it might be better to find _another_ (optional) edge that would also break the cycle, if that edge is also part of _other_ cycles.

Remember, every optional edge skipped costs an extra UPDATE query later on. The underlying problem is known as the "minimum feedback arc set" problem, and is not easily/efficiently solvable. Thus, for the time being, picking the nearest optional edge seems to be reasonable.
2023-05-08 13:30:07 +02:00
Matthias Pigulla
b52a8f8b9e Make Annotations/Attribute mapping drivers report fields for the classes where they are declared
This PR will make the annotations and attribute mapping drivers report mapping configuration for the classes where it is declared, instead of omitting it and reporting it for subclasses only. This is necessary to be able to catch mis-configurations in `ClassMetadataFactory`.

Fixes #10417, closes #10450, closes #10454.

#### ⚠️ Summary for users getting `MappingExceptions` with the new mode

When you set the `$reportFieldsWhereDeclared` constructor parameters to `true` for the AnnotationDriver and/or AttributesDriver and get `MappingExceptions`, you may be doing one of the following:

* Using `private` fields with the same name in different classes of an entity inheritance hierarchy (see #10450)
* Redeclaring/overwriting mapped properties inherited from mapped superclasses and/or other entities (see #10454)

As explained in these two PRs, the ORM cannot (or at least, was not designed to) support such configurations. Unfortunately, due to the old – now deprecated – driver behaviour, the misconfigurations could not be detected, and due to previously missing tests, this in turn was not noticed.

#### Current situation

The annotations mapping driver has the following condition to skip properties that are reported by the PHP reflection API:

69c7791ba2/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php (L345-L357)

This code has been there basically unchanged since the initial 2.0 release. The same condition can be found in the attribute driver, probably it has been copied when attributes were added.

I _think_ what the driver tries to do here is to deal with the fact that Reflection will also report `public`/`protected` properties inherited from parent classes. This is supported by the observation (see #5744) that e. g. YAML and XML drivers do not contain this logic.

The conditions are not precise enough for edge cases. They lead to some fields and configuration values not even being reported by the driver. 

Only since the fields would be "discovered" again when reflecting on subclasses, they eventually end up in class metadata structures for the subclasses. In one case of inherited ID generator mappings, the `ClassMetadataFactory` would also rely on this behaviour.

Two potential bugs that can result from this are demonstrated in #10450 and #10454.

#### Suggested solution

In order to find a more reliable way of separating properties that are merely reported again in subclasses from those that are actual re-declarations, use the information already available in `ClassMetadata`. In particular, `declared` tells us in which non-transient class a "field" was first seen.

Make the mapping driver skip only those properties for which we already know that they have been declared in parent classes, and skip them only when the observed declaring class matches the expectation. 

For all other properties, report them to `ClassMetadataFactory` and let that deal with consistency checking/error handling.

#10450 and #10454 are merged into this PR to show that they pass now.

#### Soft deprecation strategy

To avoid throwing new/surprising exceptions (even for misconfigurations) during a minor version upgrade, the new driver mode is opt-in.

Users will have to set the `$reportFieldsWhereDeclared` constructor parameters to `true` for the `AnnotationDriver` and/or `AttributesDriver`. Unless they do so, a deprecation warning will be raised.

In 3.0, the "new" mode will become the default. The constructor parameter can be deprecated (as of ORM 3.1, probably) and is a no-op.

We need to follow up in other places (DoctrineBundle, ... – what else?) to make this driver parameter an easy-to-change configuration setting.
2023-05-08 11:23:28 +00:00
Terence Eden
70477d81e9 Documentation typo (#10686)
The past tense of spin is spun, not "spinned"

https://en.wiktionary.org/wiki/spin#English
2023-05-08 12:22:09 +02:00
Grégoire Paris
05678dcd97 Merge pull request #10681 from greg0ire/rework-class-hierarchy
Rework association mapping hierarchy
2023-05-07 23:49:32 +02:00
Grégoire Paris
a9c80c2293 Merge pull request #10682 from greg0ire/remove-unneeded-fields
Make sure unneeded fields are not present
2023-05-07 23:48:41 +02:00
Grégoire Paris
1b2771f964 Merge pull request #10685 from doctrine/2.15.x-merge-up-into-2.16.x_vNvlgHpG
Merge release 2.15.1 into 2.16.x
2023-05-07 21:06:56 +02:00
Grégoire Paris
e18b80c1bf Rework association mapping hierarchy
- Each type is now either final, abstract or an interface.
- The mappedBy attribute is no longer nullable and moved down the
  hierarchy.
- The inversedBy attribute is still nullable and also moved down the
  hierarchy.
- Code common to ManyToOneAssociationMapping and
  OneToOneOwningSideMapping is de-duplicated and moved up the hierarchy
- Code inside ToManyInverseSideMapping and ToManyOwningSideMapping comes
  from a trait to avoid duplication.
2023-05-07 21:04:02 +02:00
Alexander M. Turek
9bc6f5b4ac Support unserializing 2.14 ParserResult instances (#10684) 2023-05-07 20:56:25 +02:00
Grégoire Paris
3ddb2a845c Make sure unneeded fields are not present
Instead of ensuring every mapping array has a mappedBy and an inversedBy
field, let us do the opposite, and remove them when they are null.
Likewise if there is a joinColumns field, it is useless if null or
empty.
2023-05-05 21:02:25 +02:00
Grégoire Paris
9766b6b03e Merge pull request #10651 from mpdude/unit-of-work-schedule-single-entities
Prepare entity-level commit order computation in the `UnitOfWork`
2023-05-05 20:43:23 +02:00
Grégoire Paris
9baf213673 Merge pull request #10680 from greg0ire/3.0.x
Merge 2.16.x up into 3.0.x
2023-05-05 18:46:19 +02:00
Grégoire Paris
f874bc85f1 Merge remote-tracking branch 'origin/2.16.x' into 3.0.x 2023-05-05 09:32:05 +02:00
Grégoire Paris
37c8953015 Merge pull request #10678 from doctrine/2.15.x
Merge 2.15.x up into 2.16.x
2023-05-05 08:25:43 +02:00
Grégoire Paris
60c625be17 Upgrade to Psalm 5.11.0 (#10679) 2023-05-05 07:21:05 +02:00
Grégoire Paris
8b0d6a13c2 Merge pull request #10671 from BoShurik/fix-attribute-many-to-many-mapping
Fix attribute ManyToMany mapping
2023-05-04 23:52:47 +02:00
Grégoire Paris
a7ac6ff8d9 Merge pull request #10677 from greg0ire/psalm-5-10
Upgrade to Psalm 5.10.0
2023-05-04 23:49:02 +02:00
Grégoire Paris
222d544b0c Upgrade to Psalm 5.10.0 2023-05-04 22:12:31 +02:00
Grégoire Paris
a199ca3002 Merge pull request #10676 from doctrine/2.15.x
Merge 2.15.x up into 2.16.x
2023-05-04 19:35:13 +02:00
ixitheblue
6f1fd7a81e Fix iteration index initialisation (#10675)
In the code examples of the use of the ``Query#toIterable()`` method, an index ``$i`` is used to control the size of the current batch, which ends when the condition ``($i % $batchSize) === 0`` becomes true.

Because this condition is preceded by ``++$i`` and ``$i`` is initialized to 1, the first batch is actually of size ``$batchSize - 1`` instead of ``$batchSize``.

To solve this, ``$i`` should be initialized to 0 instead of 1.
2023-05-04 14:43:56 +02:00
BoShurik
2af6e4db38 Take into account join columns specifications.
Currently, the AttributeDriver ignores any join column attribute specified on a many to many relationship.
Let's copy code from the AnnotationDriver to fix that.

Fixes #9902
2023-05-04 15:36:29 +03:00
BoShurik
b48dafded8 Update doc-block for AttributeDriverTest's fixtures 2023-05-04 15:35:40 +03:00
Grégoire Paris
ffe1550a68 Bump version numbers in the README (#10674)
2.15.0 has been released.
2023-05-04 13:44:58 +02:00
Grégoire Paris
eef5a1db81 Merge pull request #10668 from stollr/doc_attr_uniqueconstraint
Added doc for the fields parameter of the UniqueConstraint attribute
2023-05-04 08:13:33 +02:00
Grégoire Paris
d075f5d5f8 Merge pull request #10667 from greg0ire/throw-on-invalid-oto
Throw on invalid one to one
2023-05-03 23:25:34 +02:00
Grégoire Paris
c2d053d185 Update branch metadata (#10672) 2023-05-03 22:41:13 +02:00
Grégoire Paris
fac8d84fdb Throw on invalid one to one
One to one relationships are not allowed to define a join column. That
should be done on the owning side of the relationship.
2023-05-03 21:28:25 +02:00
stollr
77822d623e Added doc for the fields parameter of the UniqueConstraint attribute 2023-05-03 10:45:07 +02:00
Grégoire Paris
09680b18ee Merge pull request #10646 from greg0ire/migrate-basic-entity-persister
Migrate basic entity persister to the object API of association mapping
2023-05-02 22:47:52 +02:00
Grégoire Paris
caf8d876da Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-04-26 21:43:19 +02:00
Grégoire Paris
7b5fafffbe Merge pull request #10654 from mpdude/join-column-does-not-make-it-own
Deprecate usage of `@JoinColumn` on the inverse side of one-to-one associations
2023-04-26 20:52:02 +02:00
Grégoire Paris
629c600b10 Merge origin/2.15.x into 3.0.x (using imerge) 2023-04-25 22:28:05 +02:00
Matthias Pigulla
aba8d74017 Deprecate usage of @JoinColumn on the inverse side of one-to-one associations
Following up on #10652:

 #### Current situation

The implementation of `\Doctrine\ORM\Mapping\ClassMetadataInfo::_validateAndCompleteOneToOneMapping` will consider a field with a one-to-one association to be the owning side also when it configures `@JoinColumn` settings.

 #### Suggested change

For a one to one association, a field should be the inverse side when it uses the `mappedBy` attribute, and be the owning side otherwise. The `JoinColumn` may be configured on the owning side only.

This PR adds a deprecation notice when `@JoinColumn` is used on the side of a one-to-one association where `mappedBy` occurs.

In 3.0, this will throw a `MappingException`.
2023-04-25 15:29:17 +02:00
Alexander M. Turek
a056552db9 Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  PHPStan 1.10.14 (#10655)
  Remove JoinColumn from inverse side (#10652)
  Apply `SlevomatCodingStandard.Commenting.AnnotationName` CS rule (#10653)
2023-04-25 13:43:39 +02:00
Alexander M. Turek
1142a396d3 PHPStan 1.10.14 (#10655) 2023-04-25 13:32:39 +02:00
Grégoire Paris
f01b7d254d Remove JoinColumn from inverse side (#10652)
This makes no sense because it describes a one-to-one where each table
references the other one. I do not think this is deliberately supported,
and it probably will not be supported at all in 3.0.
2023-04-25 13:16:20 +02:00
Matthias Pigulla
ed34327941 More precisely state conditions for the postPersist event 2023-04-25 09:48:41 +02:00
Javier Spagnoletti
1ea8424e07 Apply SlevomatCodingStandard.Commenting.AnnotationName CS rule (#10653) 2023-04-25 08:56:58 +02:00
Grégoire Paris
7f46fad0f0 Merge pull request #10650 from greg0ire/better-comments
Improve named constructors' phpdoc
2023-04-24 23:36:22 +02:00
Matthias Pigulla
b42cf99402 Prepare entity-level commit order computation in the UnitOfWork
This is the second chunk to break #10547 into smaller PRs suitable for reviewing. It prepares the `UnitOfWork` to work with a commit order computed on the entity level, as opposed to a class-based ordering as before.

#### Background

#10531 and #10532 show that it is not always possible to run `UnitOfWork::commit()` with a commit order given in terms of  entity _classes_. Instead it is necessary to process entities in an order computed on the _object_ level. That may include

* a particular order for multiple entities of the _same_ class
* a particular order for entities of _different_ classes, possibly even going back and forth (entity `$a1` of class `A`, then `$b` of class `B`, then `$a2` of class `A` – revisiting that class).

This PR is about preparing the `UnitOfWork` so that its methods will be able to perform inserts and deletions on that level of granularity. Subsequent PRs will deal with implementing that particular order computation.

#### Suggested change

Change the private `executeInserts` and `executeDeletions` methods so that they do not take a `ClassMetadata` identifying the class of entities that shall be processed, but pass them the list of entities directly.

The lists of entities are built in two dedicated methods. That happens basically as previously, by iterating over `$this->entityInsertions` or `$this->entityDeletions` and filtering those by class.

#### Potential (BC breaking?) changes that need review scrutiny

* `\Doctrine\ORM\Persisters\Entity\EntityPersister::addInsert()` was previously called multiple times, before the insert would be performed by a call to `\Doctrine\ORM\Persisters\Entity\EntityPersister::executeInserts()`. With the changes here, this batching effectively no longer takes place. `executeInserts()` will always see one entity/insert only, and there may be multiple `executeInserts()` calls during a single `UoW::commit()` phase.
* The caching in `\Doctrine\ORM\Cache\Persister\Entity\AbstractEntityPersister` previously would cache entities from the last executed insert batch only. Now it will collect entities across multiple batches. I don't know if that poses a problem.
* Overhead in `\Doctrine\ORM\Persisters\Entity\BasicEntityPersister::executeInserts` is incurred multiple times; that may, however, only be about SQL statement preparation and might be salvageable.
* The `postPersist` event previously was not dispatched before _all_ instances of a particular entity class had been written to the database. Now, it will be dispatched immediately after every single entity that has been inserted.
2023-04-24 13:32:09 +02:00
Grégoire Paris
559e1d139a Improve named constructors' phpdoc
They were inconsistently documented.
2023-04-24 09:08:37 +02:00
Grégoire Paris
bd9cd989a0 Merge pull request #10649 from greg0ire/wrong-field
Use valid relationships
2023-04-23 22:13:53 +02:00
Grégoire Paris
f7e49a53be Use valid relationships
During a recent refactoring, I had to pick a relationship type for this
piece of code, and I chose wrong, because a many-to-one cannot have a
mappedBy field.
2023-04-23 10:34:12 +02:00
Grégoire Paris
ba9f51a363 Merge pull request #10648 from doctrine/2.14.x-merge-up-into-2.15.x_VZV5I0St
Merge release 2.14.3 into 2.15.x
2023-04-22 15:45:17 +02:00
Grégoire Paris
ade5559ed5 Migrate basic entity persister to the object API of association mapping 2023-04-21 22:33:44 +02:00
Grégoire Paris
c019f8649b Merge pull request #10641 from greg0ire/move-to-1-properties-down
Move $(sourceToTarget|targetToSource)KeyColumns down
2023-04-20 23:20:46 +02:00
Grégoire Paris
68571184ca Become strict about notices and warnings
Since PHPUnit 10, it is possible to display details when notices and
warnings happen, and to fail the test suite on notice.
failOnWarning is older than that.
2023-04-20 22:41:57 +02:00
Heiko Przybyl
1ae74b8ec5 Fix single table inheritance with intermediate abstract class(es)
Fixes #10625
2023-04-20 15:37:42 +02:00
Grégoire Paris
f171d49dc0 Move $(sourceToTarget|targetToSource)KeyColumns down
These properties can be made non nullable if we move them down to the 2
owning side classes that actually use them.
2023-04-20 09:11:47 +02:00
Grégoire Paris
ae88844353 Merge pull request #10638 from greg0ire/migrate-m2m
Migrate ManyToManyPersister to the object API of association mappings
2023-04-19 23:34:03 +02:00
Grégoire Paris
8d1d32ce81 Migrate ManyToManyPersister to the object API of association mappings 2023-04-18 21:22:22 +02:00
Grégoire Paris
01aa9a5870 Add nice assertion for PHPStan 2023-04-18 21:15:39 +02:00
Grégoire Paris
bf7ffa94cf Merge pull request #10637 from greg0ire/move-properties-down 2023-04-18 15:01:40 +02:00
Grégoire Paris
672ff01f44 Move properties down
These properties only make sense for the owning side of a many-to-many
relationship.
Moving them down allows us simplify the serialization code, because the
case when these properties are empty no longer happen.
2023-04-17 22:52:04 +02:00
Grégoire Paris
fd64e137c8 Merge pull request #10636 from greg0ire/join-table-columns-down
Move joinTableColumns down
2023-04-17 22:22:50 +02:00
Grégoire Paris
49cc83d273 Move joinTableColumns down
This field only makes sense for the owning side of many-to-many
mappings. Moving it down allows us to make it non-nullable.
2023-04-17 21:45:20 +02:00
Grégoire Paris
ada109bc90 Merge pull request #10633 from greg0ire/inspect-owning-side
Check only owning relationships
2023-04-15 14:58:21 +02:00
Grégoire Paris
303baeea33 Merge pull request #10635 from greg0ire/convenience-methods
Introduce and leverage more convenience methods
2023-04-15 14:58:02 +02:00
Grégoire Paris
eeae5734a5 Merge pull request #10634 from greg0ire/wrong-comparison
Remove wrong comparison
2023-04-15 14:53:45 +02:00
Grégoire Paris
b6860328c0 Introduce and leverage more convenience methods 2023-04-15 14:49:32 +02:00
Grégoire Paris
3e04516740 Remove wrong comparison
This is a remnant of when this was done with the type and the &
operator.
2023-04-15 13:07:26 +02:00
Grégoire Paris
ec9e79a35b Check only owning relationships
The inverse side does not have access to join columns / join tables.
2023-04-15 11:48:34 +02:00
Alexander M. Turek
2d3e89e2cb Remove obsolete RequiresPhp attributes (#10631) 2023-04-14 23:05:11 +02:00
Grégoire Paris
727a9914f2 Merge pull request #10628 from greg0ire/discriminator-mapping-object-api
Migrate to DiscriminatorColumnMapping's object API
2023-04-14 22:55:47 +02:00
Grégoire Paris
5aebfefc45 Merge pull request #10629 from greg0ire/embedded-class-mapping-object-api
Migrate to embedded class mapping object API
2023-04-14 22:54:36 +02:00
Grégoire Paris
118eb87032 Migrate to embedded class mapping object API 2023-04-14 15:42:00 +02:00
Grégoire Paris
7df7503af6 Migrate to DiscriminatorColumnMapping's object API
Its array access implementation should stay for external consumers, but
should be deprecated as of Doctrine 3.1.0
2023-04-14 14:27:50 +02:00
Grégoire Paris
c49bba7a5e Merge pull request #10617 from greg0ire/field-mapping-object-api
Use Rector to migrate to the object API of FieldMapping
2023-04-14 07:40:39 +02:00
Grégoire Paris
2acb298e74 Use Rector to migrate to the object API of FieldMapping
This makes the array access implementation of FieldMapping useful only
to consumers, it is no longer useful internally, and should be
deprecated as of Doctrine 3.1.0
2023-04-13 19:39:51 +02:00
Grégoire Paris
eaac5cd3dc Merge pull request #10613 from greg0ire/association-mapping
Extract AssociationMapping in its own DTO
2023-04-13 19:32:13 +02:00
Grégoire Paris
a78e5bcf65 Merge pull request #10519 from mpdude/deprecate-override-association
Deprecate overriding associations not inherited from a mapped superclass
2023-04-07 20:03:39 +02:00
Grégoire Paris
14d615201e Extract AssociationMapping in its own DTO 2023-04-07 08:39:19 +02:00
Thibault Buathier
09b4a75ed3 Fix id hash of entity with enum as identifier
When an entity have a backed enum as identifier, `UnitOfWork` tries to
cast to string when generating the hash of the id.
This fix calls `->value` when identifier is a `BackedEnum`.
Fixes #10471
Fixes #10334
2023-04-03 17:20:48 +02:00
Grégoire Paris
545070f879 Merge pull request #10612 from doctrine/embedded-class-mapping-dto 2023-04-03 10:06:40 +02:00
Grégoire Paris
9d3ae4a55a Extract embedded class mapping into its own DTO 2023-04-03 09:33:28 +02:00
Grégoire Paris
c213974234 Use the correct argument order for PHPUnit's assertions 2023-04-03 08:58:03 +02:00
Grégoire Paris
b984b567b8 Merge pull request #10599 from amina-seraoui/2.14.x
fix(persistent-collection): check association is not nullable before using it as an array
2023-04-02 23:26:11 +02:00
Grégoire Paris
e22592f06b Extract discriminator column mapping into its own DTO (#10609) 2023-04-02 14:19:03 +02:00
tasmim-concept
92c56164ee throw exception if association is null 2023-04-01 08:50:06 +02:00
Grégoire Paris
e4a7403ead Merge pull request #10607 from greg0ire/field-mapping-dto
Field mapping DTO
2023-03-31 23:34:30 +02:00
Grégoire Paris
175cdefd67 Extract FieldMapping in its own DTO
In the past, it has been decided to use arrays for this out of
legitimate performance concerns. But PHP has evolved, and now, it is
more performant and memory efficient to use objects.
2023-03-31 21:53:00 +02:00
Grégoire Paris
e8376b3995 Create array access implementation
We are going to have many DTOs, all of which will need an array access
implementation as a backward compatibility layer.
2023-03-31 09:10:38 +02:00
Grégoire Paris
b87f86e6f0 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-03-30 21:03:14 +02:00
Grégoire Paris
b2707509fc Merge pull request #10605 from greg0ire/2.15.x
Merge 2.14.x up into 2.15.x
2023-03-30 20:37:50 +02:00
Grégoire Paris
1d02139d2a Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-03-30 17:22:56 +02:00
Grégoire Paris
7ed28dba50 Merge pull request #10601 from JanTvrdik/discriminated-column-options 2023-03-30 13:31:59 +02:00
Jan Tvrdík
f215515bab Support options like charset and collation on DiscriminatedColumn
[closes #10462]
2023-03-30 11:58:29 +02:00
Grégoire Paris
ffbfbfcda1 Merge pull request #10602 from greg0ire/remove-or
Remove duplicate array shape
2023-03-29 23:30:10 +02:00
Grégoire Paris
4a30f622ec Remove duplicate array shape
DiscriminatorColumnMapping is just a specialization of the array shape
that is right of the pipe: it has the same fields, except fewer fields
are nullable. The union of that is the same thing as the array shape.
2023-03-29 21:58:36 +02:00
Grégoire Paris
df7a5bc712 Merge pull request #7199 from greg0ire/inherit_base_mapping_exception
Inherit from homonym exception in parent package
2023-03-25 12:46:36 +01:00
Grégoire Paris
fc314a2abf Merge pull request #10596 from doctrine/remove-comment
Remove contradictory comment of ORMException
2023-03-24 23:41:35 +01:00
Claudio Zizza
ebfab93d15 Remove contradictory comment
ORMException is an interface in 3.0 already
2023-03-24 23:22:36 +01:00
Grégoire Paris
aec3556502 Merge pull request #10554 from mpdude/mapped-superclass-resolve-to-many-lazy-check
Make "targetEntity must not be a mapped superclass" a lazy check
2023-03-24 08:27:38 +01:00
Grégoire Paris
13d8695780 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-03-23 16:08:09 +01:00
Grégoire Paris
33a19f1bf3 Merge pull request #10593 from mpdude/workflows
Run workflows also for the `entity-level-commit-order` branch
2023-03-23 09:15:33 +01:00
Matthias Pigulla
b6669746b7 Run workflows also for the entity-level-commit-order branch 2023-03-23 08:01:15 +00:00
Grégoire Paris
cc72796fff Inherit from homonym exception in parent package
This means that a class implementing a doctrine/persistence interface or
extending a class from that package can throw a specialized exception
that will still be caught by code in the parent package.
2023-03-22 20:02:40 +01:00
Gabriel Ostrolucký
25bd41a504 Merge branch '2.14.x' into 2.15.x 2023-03-19 22:46:07 +01:00
Grégoire Paris
35a29731bb Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-03-07 14:00:29 +01:00
Grégoire Paris
04573fc283 Address deprecation of fetchAll() (#10569)
The methods Connection::fetchAll() and Result::fetchAll() have been
deprecated in favor of more their precise counterparts.
2023-03-07 13:17:42 +01:00
Alexander M. Turek
7568328a6d Forbid PHPUnit annotations (#10567) 2023-03-06 12:02:16 +01:00
Christopher Hertel
b904f44c6c Convert PHPUnit annotations to attributes (#10559) 2023-03-06 11:14:22 +01:00
Alexander M. Turek
46ab755728 Merge 2.15.x into 3.0.x (#10565) 2023-03-06 09:31:33 +01:00
Alexander M. Turek
82362ee65e Merge 2.14.x into 2.15.x (#10564) 2023-03-06 09:30:02 +01:00
Alexander M. Turek
476ffd5cd8 Merge branch '2.15.x' into 3.0.x
* 2.15.x:
  Skip test instead of commenting it out (#10560)
  Add missing return statements to Command:configure methods
  Fix a Markdown/RST formatting glitch
  Add mapping configurations for classes that were used in tests as entities, but never declared
  Allow to-many associations on mapped superclasses w/ ResolveTargetEntityListener
2023-03-05 23:02:45 +01:00
Alexander M. Turek
9ff0440aac Merge 2.14.x into 2.15.x (#10561) 2023-03-05 22:35:31 +01:00
Alexander M. Turek
59fb8ca571 Remove Doctrine\ORM\Proxy\Proxy interface (#10551) 2023-03-05 12:43:47 +01:00
Alexander M. Turek
c44e19a5e7 PHPUnit 10 (#10492) 2023-03-05 12:43:00 +01:00
Alexander M. Turek
b69e8e0267 Add more native types to entity manager (#10556) 2023-03-02 15:19:42 +01:00
Matthias Pigulla
2c40e917c8 Revert unnecessary changes from #10473 2023-03-01 21:30:22 +00:00
Matthias Pigulla
5c06d46874 Add tests for the schema validator check 2023-03-01 21:30:22 +00:00
Matthias Pigulla
24c4ac4dd8 Do not check at runtime that associations do not refer to mapped superclasses 2023-03-01 20:40:55 +00:00
Grégoire Paris
4fad7a1190 Merge pull request #10473 from mpdude/mapped-superclass-resolve-to-many
Allow to-many associations on mapped superclasses w/ ResolveTargetEntityListener
2023-03-01 08:16:07 +01:00
Alexander M. Turek
4444a29c14 Merge branch '2.15.x' into 3.0.x
* 2.15.x:
  Ignore the cache dir of PHPUnit 10 (#10546)
  Make data providers static (#10545)
  Make data providers static (#10544)
  Bump dev tools (#10541)
  Mark SqlWalker methods as not deprecated (#10540)
  docs: consistency order for docblock in association mapping (#10534)
  Correct use of PHP attribute
  fix typo in faq.rst (#10526)
  fix: use executeStatement in SchemaTool (#10516)
  Write a test in a more specific way
  Put up a warning sign that mapping may not be inherited from transient classes (#10392)
  Avoid unnecessary information in query hints to improve query cache hit ratio
2023-02-28 17:09:23 +01:00
Alexander M. Turek
f36a8c879c Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Ignore the cache dir of PHPUnit 10 (#10546)
  Make data providers static (#10544)
  Bump dev tools (#10541)
  Mark SqlWalker methods as not deprecated (#10540)
  docs: consistency order for docblock in association mapping (#10534)
  Correct use of PHP attribute
  fix typo in faq.rst (#10526)
  fix: use executeStatement in SchemaTool (#10516)
  Write a test in a more specific way
  Put up a warning sign that mapping may not be inherited from transient classes (#10392)
  Avoid unnecessary information in query hints to improve query cache hit ratio
2023-02-28 13:50:36 +01:00
Alexander M. Turek
fa4b945b94 Make data providers static (#10545) 2023-02-28 08:29:47 +01:00
Alexander M. Turek
9c2c1178e2 Stabilize DBAL version constraint (#10542) 2023-02-28 08:29:02 +01:00
Matthias Pigulla
7814cbf4ec Fix a Markdown/RST formatting glitch 2023-02-24 17:59:02 +01:00
Grégoire Paris
f98b33f764 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-02-14 00:11:12 +01:00
Grégoire Paris
979b3dcb8d Merge pull request #10513 from greg0ire/use-array-shapes
Use array shapes where appropriate
2023-02-13 23:57:57 +01:00
Grégoire Paris
759ae5678f Merge pull request #10520 from mpdude/10470-as-exception
Turn deprecation from #10470 into an exception in 3.0.x
2023-02-13 23:08:48 +01:00
Matthias Pigulla
6b61e52baa Turn deprecation from #10470 into an exception in 3.0.x 2023-02-13 20:50:42 +00:00
Matthias Pigulla
8efdcb0555 Deprecate overriding associations not inherited from a mapped superclass 2023-02-13 20:46:11 +00:00
Grégoire Paris
21c3f4d826 Merge pull request #10517 from greg0ire/3.0.x
Merge 2.15.x up into 3.0.x
2023-02-12 22:13:24 +01:00
Grégoire Paris
7a7464e6d3 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-02-12 18:33:13 +01:00
Grégoire Paris
3810a0b6f9 Merge pull request #10470 from mpdude/prevent-entity-override
Deprecate overriding fields/associations inherited from other entities
2023-02-12 18:30:46 +01:00
Matthias Pigulla
c9b644dced Trigger a deprecation notice when entity fields/associations are overridden
This was brought up in #8348, but seemingly forgotten to be implenented in later versions.

Closes #10289.
2023-02-09 22:15:05 +00:00
Grégoire Paris
ae6de13c01 Use array shapes where appropriate
Working on converting these array shapes to DTO allowed me to find every
signature where they are supposed to be used.

The Psalm baseline gets worse because it considers accessing an array
key differently depending on whether it is defined vaguely, as
array<string, mixed>, or precisely, as array{my-key?: string}.
2023-02-09 19:44:47 +01:00
Grégoire Paris
0f77181a2c Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-02-09 00:07:14 +01:00
Matthias Pigulla
072c40357f Add mapping configurations for classes that were used in tests as entities, but never declared
Now that we validate association targets, that's an error.
2023-02-08 21:11:59 +00:00
Matthias Pigulla
ca94e82828 Allow to-many associations on mapped superclasses w/ ResolveTargetEntityListener
Allow to-many associations to be used on mapped superclasses when the owning (inverse) side does not refer back to the mapped superclass, thanks to `ResolveTargetEntityListener`.

 #### Current situation

The [documentation states](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html):

> No database table will be created for a mapped superclass itself

> [...] persistent relationships defined by a mapped superclass must be unidirectional (with an owning side only). This means that One-To-Many associations are not possible on a mapped superclass at all.

That's a though limitation.

~Obviously~ ~apparently~ Probably the limitation comes from the fact that in a to-many association the "many" side has to hold a foreign key. Since the mapped superclass does not have a database table (it's not an entity), no such backreference can be established.

Currently, to-many associations trigger an exception as soon as they are seen on a mapped superclass:

d6c0031d44/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php (L459-L461)

 #### `ResolveTargetEntityListener`

The `ResolveTargetEntityListener` can be used to substitute interface or class names in mapping configuration at runtime, during the metadata load phase.

When this gimmick is used to replace _all_ references to the mapped superclass with an entity class in time, it should be possible to have to-many associations on the inheriting entity classes.

 #### Suggested solution

Instead of rejecting to-many associations on mapped superclasses right away, validate that at the end of the day (after the `loadClassMetadata` event has been processed) no association may target at a non-entity class. That includes mapped superclasses as well as transient classes.

 #### Motivating example

Consider a library that comes with a `User` base class. This class is `abstract` and has to be subclassed/filled when the library is used.

By making this a mapped superclass, library users have the freedom to either have a simple user entity class or a user class hierarchy, but we do not impose any requirements on them. (NB we also don't want to have a root entity in the library, because that would have to declare the entire class hierarchy, including library users' classes.)

The actual user class to be used will be configured through the `ResolveTargetEntityListener`.

The library also includes a `SocialMediaAccount` entity. A `User` can have multiple of these accounts, and we want to be able to navigate the accounts from the user side.

To make the example even more fancy, there is a self-referencing association on the `User`: A `User` has been created by another user, and holds a collection of all other `User`s it created.

The test case contained in this PR contains this example and validates that all association mappings look just as if the final user class had been written as an entity directly, without the superclass.

 #### Potential review talking points

- Am I missing other reasons why to-many is not feasible?
- We now reject association mappings with `targetEntity`s that are not entities; relevant BC break? (IMHO: no.)

 #### Review tip

Review commit by commit, not all files at once. The last commit adds a lot of entity declarations that were previously missed in tests and now raised exceptions; that's a lot of clutter in the PR.
2023-02-08 21:11:58 +00:00
Grégoire Paris
db0b9d13c6 Merge pull request #10511 from doctrine/2.14.x
Merge 2.14.x up into 2.15.x
2023-02-08 22:07:14 +01:00
Grégoire Paris
f86fa175df Merge pull request #10509 from greg0ire/php8-migration
Migrate the rest of the source code to PHP 8 syntax
2023-02-08 20:44:15 +01:00
Grégoire Paris
f5e7ddb21c Migrate the rest of the source code to PHP 8 syntax 2023-02-08 20:35:53 +01:00
Matthias Pigulla
7e2eb61deb Make missing inheritance declarations a failure (#10463)
This follows up on #10431: This kind of misconfiguration triggered a deprecation warning since 2.15.x. Now let's make it an exception.
2023-02-08 08:56:21 +01:00
Grégoire Paris
dfcb20ea1e Merge pull request #10506 from doctrine/php8-migration
Migrate Parser to PHP 8
2023-02-08 00:01:25 +01:00
Grégoire Paris
ce03a61b7a Migrate Parser to PHP 8 2023-02-07 23:35:57 +01:00
Grégoire Paris
0f25ae4b83 Merge pull request #10503 from greg0ire/php8-migration
Migrate ClassMetadata to PHP 8 syntax
2023-02-07 08:13:46 +01:00
Alexander M. Turek
6c17e47624 Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Remove calls to assertObjectHasAttribute() (#10502)
  Remove calls to withConsecutive() (#10501)
  Use recognized array key
  Fix #9095 by re-applying #9096
  Use linebreaks
2023-02-07 01:21:39 +01:00
Grégoire Paris
4fe224a320 Migrate ClassMetadata to PHP 8 syntax 2023-02-06 23:54:52 +01:00
Grégoire Paris
703648580a Merge pull request #10500 from greg0ire/no-underscore-protected
Stop relying on underscores to indicate property visibility
2023-02-06 23:43:15 +01:00
Grégoire Paris
09caeb2753 Stop relying on underscores to indicate property visibility
It conflicts with our coding standard.
2023-02-06 23:27:21 +01:00
Grégoire Paris
7f9827df4f Merge pull request #10497 from greg0ire/php8-migration
Migrate more classes to PHP 8 syntax
2023-02-06 23:26:22 +01:00
Grégoire Paris
941292fe85 Migrate more classes to PHP 8 syntax 2023-02-06 23:06:21 +01:00
Grégoire Paris
de8b444938 Merge pull request #10496 from greg0ire/php8-migration
Migrate database driver to PHP 8 syntax
2023-02-05 09:05:45 +01:00
Grégoire Paris
e8c1e6c1d3 Migrate database driver to PHP 8 syntax 2023-02-04 23:25:16 +01:00
Grégoire Paris
4ad077b3d7 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-02-04 21:33:12 +01:00
Grégoire Paris
83d56d75e1 Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-02-04 10:09:15 +01:00
Grégoire Paris
9415275195 Merge pull request #10479 from greg0ire/php8-migration 2023-01-30 11:31:01 +01:00
Grégoire Paris
5c34678580 Migrate exec namespace to PHP 8 syntax 2023-01-29 16:44:55 +01:00
Grégoire Paris
d593c33ffa Merge pull request #10478 from greg0ire/better-psalm-type-location
Move psalm types to ClassMetadata
2023-01-28 16:35:37 +01:00
Grégoire Paris
6c925f5b60 Move psalm types to ClassMetadata
This spares us from referencing ClassMetadataInfo from other classes,
which is a good thing since it is deprecated. It also means merging up
is easier.
2023-01-28 15:40:27 +01:00
Grégoire Paris
82bf68d482 Remove underscore prefix on private variables (#10477) 2023-01-28 15:33:34 +01:00
Alexander M. Turek
642a20bcff Merge branch '2.15.x' into 3.0.x
* 2.15.x:
  Psalm 5.6.0, PHPStan 1.9.14 (#10468)
  Fix some tests that were missed in #10431 (#10464)
  Remove commented-out code sections (#10465)
2023-01-27 09:41:48 +01:00
Alexander M. Turek
2ee936acb4 Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Psalm 5.6.0, PHPStan 1.9.14 (#10468)
2023-01-26 19:08:35 +01:00
Matthias Pigulla
843bff4971 Fix some tests that were missed in #10431 (#10464)
In #10431, some invalid inheritance declarations in our test base were fixed. However, the change missed to update XML, PHP and static PHP mapping configurations as well.

Apparently, this did not raise any flags because the misconfiguration only caused a deprecation notice in 2.15.x. Running the tests against 3.0 (where the misconfiguration will be an error) unveiled the mistake.
2023-01-26 19:04:57 +01:00
Matthias Pigulla
d679292861 Remove commented-out code sections (#10465)
This removes comments added in #10431 on the 2.15.x branch, as suggested in https://github.com/doctrine/orm/pull/10460#issuecomment-1404889903.
2023-01-26 14:09:35 +01:00
Alexander M. Turek
4d8cf2698e Merge branch '2.15.x' into 3.0.x
* 2.15.x:
  Deprecate undeclared entity inheritance (#10431)
  Psalm 5.5.0 (#10445)
2023-01-26 08:49:28 +01:00
Grégoire Paris
5233a139bb Merge 01028cf3b into 3.0.x (using imerge) 2023-01-25 12:05:43 +01:00
Matthias Pigulla
65687821a7 Deprecate undeclared entity inheritance (#10431)
Inheritance has to be declared as soon as one entity class extends (directly or through middle classes) another one.

This is also pointed out in the opening comment for #8348:

> Entities are not allowed to extend from entities without an inheritence mapping relationship (Single Table or Joined Table inheritance). [...] While Doctrine so far allowed these things, they are fragile and will break on certain scenarios.

Throwing an exception in case of this misconfiguration is nothing we should do light-heartedly, given that it may surprise users in a bugfix or feature release. So, we should start with a deprecation notice  and make this an exception in 3.0. The documentation is updated accordingly at #10429.

Catching missing inheritance declarations early on is important to avoid weird errors further down the road, giving users a clear indication of the root cause.

In case you are affected by this, please understand that although things "previously worked" for you, you have been using the ORM outside of what it was designed to do. That may have worked in simple cases, but may also have caused invalid results (wrong or missing data after hydration?) that possibly went unnoticed in subtle cases.
2023-01-24 22:47:27 +01:00
Grégoire Paris
fbcf91d074 Merge pull request #10448 from greg0ire/php8-migration
Migrate ParserResult to PHP 8 syntax
2023-01-24 08:58:28 +01:00
Grégoire Paris
3d1f172788 Migrate ParserResult to PHP 8 syntax 2023-01-23 22:21:39 +01:00
Grégoire Paris
ca0dffb53e Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-01-23 19:27:03 +01:00
Grégoire Paris
01028cf3b8 Merge commit '8b2854393' into 2.15.x 2023-01-23 19:20:22 +01:00
Grégoire Paris
84bfe7cbb9 Merge pull request #10446 from greg0ire/update-psalm-baseline
Update Psalm baseline
2023-01-23 19:20:00 +01:00
Grégoire Paris
1b3978e8c9 Update Psalm baseline 2023-01-23 19:17:40 +01:00
Grégoire Paris
7f783b59c8 Merge pull request #10442 from greg0ire/embedded-class-array-shape 2023-01-23 10:58:11 +01:00
Grégoire Paris
68662f5920 Add embedded class mapping array shape
This should be replaced with a DTO in the next major.
To be able to have something usable, I had to move the validation of the
DTO (checking that it has a "class" attribute) to mapEmbedded, which
happens earlier than doLoadMetadata(). It is unclear to me why it was
not put here in the first place.
2023-01-22 23:49:43 +01:00
Grégoire Paris
6ea4411789 Merge pull request #10440 from greg0ire/php8-migration
Migrate entity manager to PHP 8 syntax
2023-01-22 23:47:38 +01:00
Grégoire Paris
4357161c3d Migrate entity manager to PHP 8 syntax 2023-01-22 15:37:38 +01:00
Adrien Crivelli
769b161dff Identity map cannot contain null value (#10156) 2023-01-22 14:15:20 +07:00
Grégoire Paris
9857cf971b Merge pull request #10438 from greg0ire/2.15.x
Merge 2.14.x up into 2.15.x
2023-01-20 23:58:44 +01:00
Grégoire Paris
f73dae9bc4 Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-01-20 21:19:28 +01:00
Grégoire Paris
1c357b9fb3 Merge pull request #10426 from mpdude/parent-classes-docblock
Slight docblock improvements for `CM::parentClasses`
2023-01-20 12:46:34 +01:00
Matthias Pigulla
3d031ed541 Slight docblock improvements for CM::parentClasses 2023-01-20 11:26:28 +00:00
Grégoire Paris
15ed97b7b1 Merge pull request #10437 from greg0ire/update-baseline
Update Psalm baseline
2023-01-20 12:03:42 +01:00
Grégoire Paris
9fd4af23e1 Update Psalm baseline 2023-01-20 12:00:34 +01:00
Grégoire Paris
4206f01e7b Use FieldMapping array shape even more (#10430)
I experimented on converting FieldMapping to a DTO, and it allowed me to
find more places where it should be used.
2023-01-19 10:06:03 +01:00
Matthias Pigulla
7d4052c9e7 Fix version number in UPGRADE.md (#10428)
This was a mistake in #10423.
2023-01-19 08:23:27 +01:00
Grégoire Paris
3b5bd316e6 Merge pull request #10427 from greg0ire/3.0.x
Merge 2.15.x up into 3.0.x
2023-01-18 23:29:04 +01:00
Grégoire Paris
2d92c09101 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-01-18 23:26:21 +01:00
Grégoire Paris
fc6feb5938 Merge pull request #10423 from mpdude/deprecate-table-type-per-class
Add deprecations for "table per class" inheritance
2023-01-18 23:23:53 +01:00
Matthias Pigulla
89b98bdff9 Add deprecations for "table per class" inheritance 2023-01-18 16:30:57 +00:00
Grégoire Paris
4c1e520bd3 Migrate remaining exceptions to PHP 8 syntax (#10402) 2023-01-18 17:11:42 +01:00
Matthias Pigulla
7a08253f18 Remove "table per class" inheritance that was never actually implemented (#10414) 2023-01-18 16:13:26 +01:00
Grégoire Paris
e6382d393e Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-01-17 23:17:32 +01:00
Grégoire Paris
37572802cc Reuse association mapping array shape (#10403) 2023-01-17 11:27:42 +01:00
Grégoire Paris
a5bdc619c7 Merge pull request #10408 from greg0ire/field-mapping-improvements
Field mapping improvements
2023-01-17 09:08:33 +01:00
Grégoire Paris
65a7c8882f Merge pull request #10413 from doctrine/2.14.x-merge-up-into-2.15.x_2sgwy6Oi
Merge release 2.14.1 into 2.15.x
2023-01-16 20:44:54 +01:00
Grégoire Paris
2d6295c9db Merge remote-tracking branch 'origin/2.14.x' into 2.15.x 2023-01-16 20:24:44 +01:00
Alexander M. Turek
f0616626e0 Test with a stable PHPUnit (#10406) 2023-01-16 15:53:19 +07:00
Matthias Pigulla
a8ef69dbe6 Factor out logic that tracks mapping inheritance (#10397) 2023-01-16 06:33:54 +04:00
Grégoire Paris
c0a7317e8d Reuse array shape 2023-01-15 21:55:32 +01:00
Grégoire Paris
843b0fcc16 Add missing fields 2023-01-15 21:55:32 +01:00
Grégoire Paris
b56de5b0e2 Type TypedFieldMapper API more precisely 2023-01-15 21:55:32 +01:00
Alexander M. Turek
0b35e637b8 Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Stop allowing phpbench's master branch
2023-01-15 14:54:24 +07:00
Grégoire Paris
3cd65b12a8 Merge pull request #10401 from greg0ire/3.0.x
Merge 2.15.x up into 3.0.x
2023-01-14 11:34:19 +01:00
Grégoire Paris
d4c53a8885 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-01-14 11:14:06 +01:00
Grégoire Paris
277614d9c2 Merge pull request #10400 from doctrine/2.14.x
Merge 2.14.x up into 2.15.x
2023-01-14 11:10:20 +01:00
Grégoire Paris
c8b0931f9c Merge pull request #10379 from greg0ire/remove-cmi
Remove ClassMetadataInfo
2023-01-13 23:18:24 +01:00
Grégoire Paris
c226b951b3 Merge pull request #10378 from greg0ire/php8-migration
Migrate classes with the fewest changes
2023-01-11 09:33:24 +01:00
Grégoire Paris
91b662edb6 Merge pull request #10380 from greg0ire/php8-migration-exceptions
Migrate exceptions to PHP 8 syntax
2023-01-10 11:04:17 +01:00
Grégoire Paris
c313440962 Migrate exceptions to PHP 8 syntax
Co-authored-by: Alexander M. Turek <me@derrabus.de>
Co-authored-by: Claudio Zizza <859964+SenseException@users.noreply.github.com>
2023-01-10 07:58:40 +01:00
Grégoire Paris
a86d5a799d Migrate classes with the fewest changes 2023-01-09 09:10:17 +01:00
Alexander M. Turek
9b1f397ab2 Merge branch '2.15.x' into 3.0.x
* 2.15.x:
  Use more precise types for class strings (#10381)
  PHPStan 1.9.8, Psalm 5.4.0 (#10382)
  fix typo for missing a comma (#10377)
  Docs: Removing `type: 'integer'` from mappings (#10368)
  Docs: Moving *attributes* mapping to first position (#10364)
  Docs: Deleting duplicate mapping example (#10363)
2023-01-09 11:47:02 +07:00
Alexander M. Turek
29b8b0bffb Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  PHPStan 1.9.8, Psalm 5.4.0 (#10382)
  fix typo for missing a comma (#10377)
  Docs: Removing `type: 'integer'` from mappings (#10368)
  Docs: Moving *attributes* mapping to first position (#10364)
  Docs: Deleting duplicate mapping example (#10363)
2023-01-09 11:32:00 +07:00
Grégoire Paris
b7ba018f0a Use more precise types for class strings (#10381) 2023-01-09 11:29:56 +07:00
Grégoire Paris
d83b1e338c Remove ClassMetadataInfo 2023-01-07 18:38:46 +01:00
Grégoire Paris
07937b5b9a Merge pull request #10374 from greg0ire/php8-migration
Migrate classes with the fewest changes to PHP 8
2023-01-07 10:59:50 +01:00
Grégoire Paris
a3db423eab Migrate classes with the fewest changes to PHP 8 2023-01-06 23:32:22 +01:00
Grégoire Paris
2b2f4e8acc Merge pull request #10375 from greg0ire/remove-deprecated-methods
Remove deprecated methods and classes
2023-01-06 23:31:24 +01:00
Grégoire Paris
84e78b8200 Remove deprecated methods and classes
This is a follow-up for https://github.com/doctrine/orm/pull/9876
2023-01-04 21:28:14 +01:00
Grégoire Paris
601948baaa Merge pull request #10373 from greg0ire/3.0.x
Merge 2.15.x up into 3.0.x
2023-01-04 20:50:17 +01:00
Grégoire Paris
19168ca8d6 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-01-04 20:08:12 +01:00
Grégoire Paris
72b1bf0c02 Use the same type as in the DBAL (#10372)
* Use the same type as in the DBAL

Implementations pass this parameter unchanged to DBAL methods.

* Update Psalm baseline
2023-01-04 19:32:28 +01:00
Grégoire Paris
5e828e20cf Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2023-01-04 18:00:24 +01:00
Grégoire Paris
70241d3407 Merge pull request #10365 from greg0ire/precise-return-type
Address new behavior of $firstResult
2023-01-03 23:55:01 +01:00
Grégoire Paris
3a10714d6f Merge pull request #10367 from greg0ire/php8-migration
Migrate files with the least changes to PHP 8
2023-01-03 23:54:44 +01:00
Grégoire Paris
7e379f6872 Migrate files with the least changes to PHP 8
These are the lowest hanging fruits I could find after running Rector: I
looked for files with a diff of 2 lines.
I did not include some changes that I find controversial, such as
marking some constants as final when we should maybe consider making
classes themselves final.
2023-01-03 23:20:25 +01:00
Grégoire Paris
1d5d47964c Address new behavior of $firstResult
Following 1915dcd1e8, 0 is now used as a
default value, and Query::$firstResult is no longer nullable, but it
seems getFirstResult() was overlooked. The class is final, so this is no
breaking change.
2023-01-03 21:29:09 +01:00
Alexander M. Turek
8b1c353650 Merge branch '2.15.x' into 3.0.x
* 2.15.x:
  PHPStan 1.9.5 (#10359)
  Drop doctrine/lexer 1
2023-01-02 23:22:27 +01:00
Alexander M. Turek
c9c4203a1e Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  PHPStan 1.9.5 (#10359)
2023-01-02 23:14:10 +01:00
Grégoire Paris
75bff1d983 Drop doctrine/lexer 2
This allows us to have a totally typed lexer
2023-01-02 22:37:41 +01:00
Grégoire Paris
091da8c420 Merge pull request #10329 from greg0ire/drop-lexer-1-backport
Drop doctrine/lexer 1
2023-01-02 21:07:13 +01:00
Alexander M. Turek
8b35dae5a9 Merge branch '2.15.x' into 3.0.x
* 2.15.x:
  Shorter deprecation message (#10357)
  Add Fully-Qualified class name in UnrecognizedField exception to ease debugging (#10342)
  Include parameter types in hydration cache key generation (#10355)
  Allow doctrine/instantiator 2 (#10351)
2022-12-31 17:56:01 +01:00
Alexander M. Turek
515a3d8b8b Merge branch '2.14.x' into 2.15.x
* 2.14.x:
  Shorter deprecation message (#10357)
  Add Fully-Qualified class name in UnrecognizedField exception to ease debugging (#10342)
  Include parameter types in hydration cache key generation (#10355)
2022-12-31 17:45:59 +01:00
Alexander M. Turek
9062af45ca Fix build for DBAL 4 (#10354) 2022-12-31 16:18:08 +01:00
Grégoire Paris
603ab9a185 Drop doctrine/lexer 1 2022-12-31 00:20:27 +01:00
Alexander M. Turek
57f256912a Leverage new ArrayParameterType constants (#10352) 2022-12-30 19:53:30 +01:00
Alexander M. Turek
10d27c18ea Allow doctrine/instantiator 2 (#10351) 2022-12-30 19:52:12 +01:00
Alexander M. Turek
b31afda33b Modernize QueryExpressionVisitor (#10346) 2022-12-29 15:11:29 +01:00
Alexander M. Turek
ccb9ef7246 Merge pull request #10347 from derrabus/improvement/allow-lexer-3
Allow Lexer 3
2022-12-29 15:10:14 +01:00
Grégoire Paris
bdb3fc72da Allow Lexer 3
Co-authored-by: Alexander M. Turek <me@derrabus.de>
2022-12-29 12:58:35 +01:00
Alexander M. Turek
8aa05b89a0 Merge branch '2.15.x' into 3.0.x
* 2.15.x:
  Support of NOT expression from doctrine/collections ^2.1 (#10234)
  Fix Psalm errors with Collection 2.1.2 (#10343)
  Added warning about query cache in relation to parameters (#10276)
2022-12-29 00:48:06 +01:00
Alexander M. Turek
ae9fb8ca21 Merge 2.14.x into 2.15.x (#10344) 2022-12-28 17:23:15 +01:00
Rémi San
c7f2a1d580 Support of NOT expression from doctrine/collections ^2.1 (#10234) 2022-12-28 17:22:39 +01:00
Grégoire Paris
d8a2e329b6 Merge remote-tracking branch 'origin/2.15.x' into 3.0.x 2022-12-20 23:36:39 +01:00
Grégoire Paris
b3f441cb8b Merge pull request #10330 from doctrine/2.14.x
Merge 2.14.x up into 2.15.x
2022-12-20 20:07:49 +01:00
michnovka
ad58c6a6e2 Cleanup code from PR10313 from 2.14.x (#10326) 2022-12-20 07:32:34 +01:00
Alexander M. Turek
8f360f08c5 Migrate Doctrine\ORM\Internal\CommitOrder to PHP 8.1 (#10323) 2022-12-20 07:28:33 +01:00
Grégoire Paris
2e2bca8cf8 Merge pull request #10324 from doctrine/2.14.x-merge-up-into-3.0.x_YfifaF7w
Merge release 2.14.0 into 3.0.x
2022-12-19 23:57:12 +01:00
Grégoire Paris
32eae38f07 Merge remote-tracking branch 'origin/2.14.x' into 2.14.x-merge-up-into-3.0.x_YfifaF7w 2022-12-19 23:32:57 +01:00
Alexander M. Turek
3a2bfce92c Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Drop forceful loading of annotations (#10321)
  Document stdClass structures used by CommitOrderCalculator (#10315)
  Psalm 5.3.0 (#10317)
  PHPStan 1.9.4 (#10318)
  add apcu enabled check if apcu extension loaded (#10310) (#10311)
  Add TypedFieldMapper for automatic mapping of typed PHP fields to DBAL types (#10313)
2022-12-19 22:41:51 +01:00
Grégoire Paris
57e18d0b1b Merge pull request #10309 from greg0ire/drop-lexer-1
Drop doctrine/lexer 1
2022-12-15 11:54:03 +01:00
michnovka
b3f9acd1bf Clean-up code after PR10288 merge (#10305) 2022-12-15 11:50:18 +01:00
Grégoire Paris
cdc7feccc8 Drop doctrine/lexer 1
This allows us to introduce the TokenType enum that represents the type
of DQL tokens.
2022-12-14 22:15:20 +01:00
Grégoire Paris
275fe31c04 Merge pull request #10308 from greg0ire/3.0.x
Merge 2.14.x up into 3.0.x
2022-12-14 21:38:25 +01:00
Grégoire Paris
8e9ea9e9e0 Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-12-14 20:52:37 +01:00
Alexander M. Turek
92a8453b92 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Add assertions about non nullability
  Add support for enum discriminator columns
2022-12-14 09:29:24 +01:00
Alexander M. Turek
7fd49b7547 Remove $entityAnnotationClasses and getReader() (#10303) 2022-12-13 23:28:07 +01:00
Alexander M. Turek
8212ba8803 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Bump coding standard to v11 (#10295)
  PHPStan 1.9.3 (#10298)
  Rename AbstractCommandTest (#10294)
2022-12-13 19:38:01 +01:00
Alexander M. Turek
2bfcb6e5ab Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Fix changeset computation for enum arrays (#10277)
  Psalm 5.2.0 (#10291)
  Run tools on PHP 8.2 (#10287)
2022-12-12 14:15:47 +01:00
Alexander M. Turek
9d8cadf1fc Remove setAccessible() calls (#10286) 2022-12-10 23:18:23 +01:00
Alexander M. Turek
a17809c3b9 Modernize Closure::fromCallable() calls (#10285) 2022-12-10 23:18:10 +01:00
Alexander M. Turek
9dbe3d003a Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Control proxy implementation via env (#10282)
  Fix association mapping with enum fields
  Correct spelling errors
2022-12-10 21:55:54 +01:00
Alexander M. Turek
38c476f704 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Leverage LazyGhostTrait when possible
  Fix deprecation message (#10270)
2022-12-10 15:27:43 +01:00
Alexander M. Turek
90efde936a Remove InExpression (#10272) 2022-12-06 21:46:53 +01:00
Alexander M. Turek
caaf1509bf Drop support for Symfony 4 (#10259) 2022-12-06 21:46:30 +01:00
Grégoire Paris
9e578a4f0d Migrate AST namespace to PHP 8 syntax (#10219)
* Migrate AST namespace to PHP 8 syntax

* Use typed properties when type is non-object

We know the phpdoc types in that namespace are pretty messed up, but it
should be safe to assume that's only the case when the type is an object
type.
2022-12-05 22:38:16 +01:00
Alexander M. Turek
f1c180ba50 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Add $not constructor parameter to AST classes (#10267)
2022-12-05 12:26:48 +01:00
Grégoire Paris
8c732120bc Use intersection types (#10255)
We could not do that before, because it would make Psalm crash.
2022-12-04 22:28:19 +01:00
Grégoire Paris
6cf69ec6d1 Merge pull request #10266 from greg0ire/3.0.x
Merge 2.14.x into 3.0.x
2022-12-04 09:34:22 +01:00
Grégoire Paris
67f876372c Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-12-04 00:17:19 +01:00
Alexander M. Turek
f4d658ab7e Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Bump Psalm to 5.0.0 and fix errors for Symfony 6.2 (#10261)
  Make use statements redundant
  Leverage Lexer's Token type (follow up)
2022-11-30 22:10:44 +01:00
Grégoire Paris
7433c3ad47 Merge pull request #10227 from greg0ire/php8-migration-expr
Migrate Expr and Lexer to PHP 8 syntax
2022-11-28 08:03:39 +01:00
Grégoire Paris
4d73e3ce78 Migrate Expr and Lexer to PHP 8 syntax 2022-11-27 22:14:04 +01:00
Grégoire Paris
5afa36097a Merge pull request #10254 from greg0ire/3.0.x
Merge 2.14.x up into 3.0.x
2022-11-26 15:01:01 +01:00
Grégoire Paris
afe010ed0f Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-11-26 14:52:30 +01:00
Grégoire Paris
02f3a93b71 Merge pull request #10243 from greg0ire/php8-migration-persisters
Migrate persisters to PHP 8 syntax
2022-11-22 21:47:05 +01:00
Grégoire Paris
e9f3a43f37 Migrate persisters to PHP 8 syntax 2022-11-21 23:49:34 +01:00
Alexander M. Turek
8c7386fea0 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Remove fragile assertions (#10239)
  update help for RunDqlCommand (#10233)
  Make the code easier to statically analyse
  Widen parameter type
  Document property as non-nullable
2022-11-20 21:09:46 +01:00
Grégoire Paris
d6b9da008b Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-11-11 16:34:25 +01:00
Alexander M. Turek
436142a1d8 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Add a constructor to CacheKey (#10212)
  Psalm 4.30.0, PHPStan 1.9.2 (#10213)
  Allow "Expr\Func" as condition in join (#10202)
  refactor: use list type in SchemaTool (#10199)
2022-11-11 11:00:23 +01:00
Grégoire Paris
a8445c9661 Migrate function nodes to PHP 8 syntax (#10214) 2022-11-11 10:49:48 +01:00
Grégoire Paris
bfb9e16fcf Merge pull request #10210 from greg0ire/php8-migration
Migrate Cache namespace to php 8
2022-11-09 00:05:11 +01:00
Grégoire Paris
3d729a768f Stop modifying readonly properties 2022-11-08 23:58:15 +01:00
Grégoire Paris
2f1ed28f09 Migrate cache namespace to php 8 2022-11-08 23:58:15 +01:00
Grégoire Paris
ee1b78441c Purge annotations from /lib (#10203)
* Remove file used by annotation registry

* Remove meta-annotations

They should have been removed when the annotation driver was removed.

* Remove unneeded coding standard rule exclusion

* Remove annotation documentation of indexBy
2022-11-07 12:00:28 +01:00
Grégoire Paris
2cbd674141 Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-11-06 23:02:35 +01:00
michnovka
3182cceda4 EntityManager#refresh lockMode on 3.0.x (#10196) 2022-11-02 16:50:55 +01:00
Alexander M. Turek
71bcd64fb5 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Remove Doctrine\Persistence\ObjectManager::refresh from Psalm baseline
  Add lockMode to EntityManager#refresh() (#10040)
2022-11-02 00:49:02 +01:00
Alexander M. Turek
c2fa7282ca Merge pull request #10192 from derrabus/remove/annotation
Remove the Annotation interface
2022-10-31 10:24:41 +01:00
Alexander M. Turek
373fd32b0e Remove the Annotation interface 2022-10-31 09:50:08 +01:00
Alexander M. Turek
3865835070 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Deprecate the Annotation interface (#10178)
  Bump CI to PHP 8.2 and latest database versions (#10180)
  Remove reference to deprecated DriverChain from docs (#10179)
2022-10-31 09:26:10 +01:00
Grégoire Paris
4be38e2dda Remove last remnants of the YAML driver (#10185) 2022-10-26 23:50:26 +02:00
Alexander M. Turek
ba286de3cb Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  PHPStan 1.8.11 (#10182)
  Add isMemberOf and isInstanceOf to Expr helper list (#10104)
  Migrate more references to annotations (#10176)
  Fix grammer in working-with-objects (#10120)
  Automap events in AttachEntityListenersListener (#10122)
  Adapt use statements to the code (#10174)
2022-10-26 12:00:57 +02:00
Alexander M. Turek
31db15f501 Remove DriverChain (#10175) 2022-10-26 10:15:47 +02:00
Grégoire Paris
1f15e3b198 Purge annotations from the codebase and docs (#10177) 2022-10-26 09:37:39 +02:00
Grégoire Paris
189883e267 Merge pull request #10113 from greg0ire/migrate-to-attributes
Migrate to attributes
2022-10-26 07:30:01 +02:00
Alexander M. Turek
ae6524bb2f Bump DBAL to 3.5 and remove BC hacks (#10173) 2022-10-25 23:51:42 +02:00
Grégoire Paris
ef4543df33 Just a little cs fix, no big deal. 2022-10-25 23:32:47 +02:00
Grégoire Paris
d46f67bf95 Add missing ManyToOne attribute
The tests does not behave as expected without it.
2022-10-25 23:32:47 +02:00
Grégoire Paris
bbdbfb807c Run Rector
I used the following config:

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Doctrine\Set\DoctrineSetList;

return function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/tests',
    ]);
    $rectorConfig->sets([
        DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
    ]);
};
2022-10-25 23:32:47 +02:00
Grégoire Paris
29aee06e76 Remove annotations that duplicate attributes 2022-10-25 23:32:47 +02:00
Grégoire Paris
f8587c4ed7 Remove annotation driver 2022-10-25 23:32:47 +02:00
Grégoire Paris
9c7f575569 Switch to attribute driver 2022-10-25 23:12:12 +02:00
Alexander M. Turek
adceff29f1 Remove EntityManager::create() (#10172) 2022-10-25 16:59:19 +02:00
Alexander M. Turek
59b7fa2ebc Fix build 2022-10-25 00:22:28 +02:00
Alexander M. Turek
94e3772221 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Deprecate EntityManager::create() (#9961)
  Address deprecation of SchemaDiff::toSaveSql()
  Address deprecation of SchemaDiff::toSql()
  Use error style for notifications
  Fix calls to AbstractSchemaManager::createSchema() (#10165)
  Fix build with DBAL 3.5 (#10163)
  Adjust comments (#10160)
  Deprecate methods related to the annotation driver
  Use correct link
  Deprecate annotations
  Remove trailing whitespace
  Migrate more documentation towards attributes
  Remove wrong sentence
  Do not export phpstan stuff (#10154)
2022-10-24 23:16:35 +02:00
Alexander M. Turek
8efcaf97eb Add native types to annotation classes (#10151) 2022-10-18 09:39:12 +02:00
Alexander M. Turek
eda69c23bd Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Modernize documentation code
  Add CI jobs for SQLite3 driver (#10141)
  Fix type doc blocks in annotation classes (#10145)
  Fix FieldMapping for generated key (#10144)
  Stop triggering static analysis workflows on tests
2022-10-17 23:29:39 +02:00
Alexander M. Turek
8c00c88818 Merge 2.14.x into 3.0.x (#10140) 2022-10-17 10:26:54 +02:00
Alexander M. Turek
99e07eb11c Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Allow doctrine/event-manager 2 (#10123)
  Psalm 4.29 (#10128)
  Address deprecation of Table::changeColumn() (#10121)
  Make code blocks consistent (#10103)
  Fix change set computation with enums (#10074)
  PHPStan 1.8.8, Psalm 4.28.0 (#10115)
  fix deprecated trigger help comment
2022-10-13 18:01:09 +02:00
Grégoire Paris
5367ce843e Merge pull request #10084 from greg0ire/drop-collections-1 2022-10-10 14:16:46 +02:00
Grégoire Paris
55d58ddb60 Merge pull request #10117 from doctrine/2.14.x
Merge 2.14.x up into 3.0.x
2022-10-10 09:00:45 +02:00
Grégoire Paris
dc2bd9e412 Migrate collections to PHP 8 syntax 2022-10-09 23:29:08 +02:00
Grégoire Paris
7c17bba801 Remove SQL resultset mapping (#10114) 2022-10-09 22:24:18 +02:00
Grégoire Paris
0c6d3ec6e0 Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-10-07 21:40:29 +02:00
Grégoire Paris
813e807ea6 Merge pull request #10112 from greg0ire/dont-instantiate-interface
Do not instantiate interface
2022-10-07 21:38:59 +02:00
Grégoire Paris
cfefa1e9b7 Do not instantiate interface
In DBAL 4.0, Doctrine\DBAL\Exception becomes an interface.
2022-10-07 21:28:57 +02:00
Grégoire Paris
426ab21b69 Merge pull request #10102 from greg0ire/address-dbal-changes 2022-10-06 10:24:21 +02:00
Grégoire Paris
f310e1f5ba Address method rename
See https://github.com/doctrine/dbal/pull/5724
2022-10-06 08:57:32 +02:00
Grégoire Paris
41fd9816e8 Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-10-04 23:38:17 +02:00
Grégoire Paris
5abe6a5875 Merge pull request #10083 from greg0ire/3.0.x
Merge 2.14.x up into 3.0.x
2022-09-30 23:07:19 +02:00
Grégoire Paris
e308b0aee1 Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-09-30 20:02:02 +02:00
Grégoire Paris
38b1fee344 Merge pull request #10048 from greg0ire/php8-migration
Migrate QueryBuilder / ClassMetadataInfo
2022-09-27 23:45:04 +02:00
Grégoire Paris
75a7cc983c Migrate ClassMetadataInfo to PHP 8.1 2022-09-27 08:45:54 +02:00
Grégoire Paris
d62359a009 Migrate QueryBuilder to PHP 8.1 2022-09-22 17:50:12 +02:00
Grégoire Paris
745250942f Merge remote-tracking branch 'origin/2.14.x' into 3.0.x 2022-09-22 16:26:14 +02:00
Alexander M. Turek
f32ae29385 Add types to PersisterHelper (#10053) 2022-09-22 15:34:46 +02:00
Alexander M. Turek
ffd47ce2dd Add types to mapping builders (#10052) 2022-09-22 11:24:05 +02:00
Alexander M. Turek
a3ec3f368f Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  PHPStan 1.8.5, Psalm 4.27.0 (#10033)
  Fix EnumType not being hydrated with HYDRATE_ARRAY (#9995)
  "Strange" return lines in documentation of inheritance-mapping.rst (#10027)
  More strange break lines in inheritance-mapping.rst (#10028)
  Add phpdoc for discriminatorColumn
2022-09-22 08:52:01 +02:00
Grégoire Paris
57054caca5 Merge pull request #10050 from greg0ire/fix-dbal-build
Fix dbal 4 build
2022-09-22 00:09:16 +02:00
Grégoire Paris
965de8b742 Address AbstractSchemaManager::createSchema() removal 2022-09-21 23:54:39 +02:00
Grégoire Paris
1479848714 Specify precision for decimal columns
doctrine/dbal 4 no longer provides a default value for that column
option.
2022-09-21 23:30:11 +02:00
Alexander M. Turek
5fe78f7892 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Bump Ubuntu version and shared workflows (#10020)
  Make paginator covariant (#10002)
  Fail gracefully if EM could not be constructed in tests (#10008)
2022-08-31 00:01:28 +02:00
Grégoire Paris
cdd79bc764 Merge commit '8dfe8b878' into 3.0.x 2022-08-29 23:18:19 +02:00
Grégoire Paris
52b96538b7 Merge pull request #10011 from greg0ire/cs10-on-3.0
Upgrade to doctrine/coding-standard 10.0 on 3.0.x
2022-08-29 23:16:43 +02:00
Grégoire Paris
4aa3c630df Address DBAL deprecations
- listTableDetails() has been deprecated in favor of introspectTable().
- createSchema() has been deprecated in favor of introspectSchema().
2022-08-29 23:03:28 +02:00
Grégoire Paris
883c8c443f Update baseline 2022-08-29 22:29:28 +02:00
Grégoire Paris
1d3c6d6eb8 Adjust CPP migration 2022-08-29 22:29:28 +02:00
Grégoire Paris
4dcaa2c23b Improve PHPDoc for WhereClause::$conditionalExpression 2022-08-29 22:29:28 +02:00
Grégoire Paris
21e142b9a5 Revert changes that cause test failures 2022-08-29 22:29:28 +02:00
Grégoire Paris
3cd2562626 Upgrade to doctrine/coding-standard 10.0 2022-08-29 22:29:28 +02:00
Alexander M. Turek
28b5dfdb84 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Bump coding standard to 9.0.2
  Fix tests for doctrine/common 3.4
  Fix static analysis errors for Collections 1.7
  Fix type in docs (#9994)
  Improve orphan removal documentation - recommend using cascade=persist  (#9848)
2022-08-26 13:12:51 +02:00
Alexander M. Turek
41bca04103 Add types to EntityListenerResolver (#9976) 2022-08-08 22:02:40 +02:00
Alexander M. Turek
7abeb9bf00 Merge branch '2.14.x' into 3.0.x
* 2.14.x:
  Backport type fixes for EntityListenerResolver (#9977)
  Undeprecate LifecycleEventArgs (#9980)
  Update documentation to not use deprecated method (#9979)
2022-08-08 21:41:43 +02:00
Alexander M. Turek
7c4442561f Add types to Node::dispatch() (#9978) 2022-08-08 21:30:51 +02:00
Alexander M. Turek
7e45006300 Update Psalm config (#9974) 2022-08-07 22:35:19 +02:00
Alexander M. Turek
c39cbf15be Add types to ProxyFactory (#9962) 2022-08-07 21:37:36 +02:00
Alexander M. Turek
9e304fbe69 Merge 2.14.x into 3.0.x (#9973) 2022-08-07 20:13:52 +02:00
Alexander M. Turek
f9257cdf78 Flag QueryType as internal (#9963) 2022-08-07 19:22:03 +02:00
Alexander M. Turek
0e074e407a Stabilize the DBAL dependency (#9968) 2022-08-07 18:42:52 +02:00
Alexander M. Turek
71cba3d1fe Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Address DBAL 3.4 deprecations (#9969)
  Improve phpdoc for ClassMetadataInfo (#9965)
  Fix build (#9964)
  fix: class normalisation test (#9966)
  Support native enum hydration when using `NEW` operator (#9936)
2022-08-07 18:22:43 +02:00
Alexander M. Turek
23f5c016cf Resolve QueryBuilder deprecations (#9953) 2022-08-04 22:51:21 +02:00
Alexander M. Turek
1a82e4a294 Drop unmaintained Symfony versions (#9957) 2022-08-04 08:29:29 +02:00
Alexander M. Turek
a0be22b65f Use intersection types in tests (#9959) 2022-08-04 08:28:50 +02:00
Alexander M. Turek
6e5626bbff Flag properties as readonly if possible (#9956) 2022-08-04 08:27:02 +02:00
Alexander M. Turek
6e6b81dcdf Remove obsolete PHP version checks (#9954) 2022-08-04 00:12:00 +02:00
Alexander M. Turek
3c19eb6de2 Require PHP 8.1 (#9925) 2022-08-03 23:01:41 +02:00
Alexander M. Turek
309e48ad54 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Deprecate QueryBuilder APIs exposing its internal state (#9945)
  Update branch info in README and .doctrine-project.json (#9943)
  Psalm 4.25.0, PHPStan 1.8.2 (#9941)
  Stop passing event manager to constructor (#9938)
  Use a more precise phpdoc for ClassMetadataInfo::versionField than mixed (#9937)
  Make EntityManager `@final` and its constructor public
2022-08-03 22:48:03 +02:00
Alexander M. Turek
ef82567730 Fix DBAL 4 compatibility (#9950) 2022-08-03 17:05:42 +02:00
Grégoire Paris
61cc67e4b7 Merge pull request #9940 from greg0ire/php8-migration
Migrate UnitOfWork to PHP 8
2022-07-28 18:40:56 +02:00
Grégoire Paris
0c2d1df424 Migrate Configuration class to PHP 8 again 2022-07-28 17:06:29 +02:00
Grégoire Paris
35afdb1c84 Migrate UnitOfWork to PHP 8 2022-07-28 16:16:49 +02:00
Alexander M. Turek
a3a8caae51 Split TreeWalker and SqlWalker (#9551) 2022-07-25 22:27:45 +02:00
Alexander M. Turek
5830736537 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Add helper function TreeWalkerAdapter::getMetadataForDqlAlias() (#9932)
  Simplify LanguageRecognitionTest (#9930)
  test/added test for foreign keys with custom id object types
  Widen types for DiscriminatorMap (#9922)
  schema tool: remove useless text from --dump-sql output
  Update IdentifierFlattener.php
  Update IdentifierFlattener.php
2022-07-25 20:59:42 +02:00
Alexander M. Turek
0bfdbe1e2c Add native types to QuoteStrategy classes (#9923) 2022-07-21 10:16:31 +02:00
Alexander M. Turek
d41c4c6cc6 Adjust casing of SQLitePlatform for DBAL 4 (#9924) 2022-07-20 22:14:27 +00:00
Grégoire Paris
2550417804 Merge pull request #9900 from greg0ire/php8-migration
Migrate part of the tools namespace to PHP8 syntax
2022-07-19 20:17:46 +02:00
Grégoire Paris
c44db2cc35 Fulfill ReturnTypeWillChange prophecy 2022-07-19 08:45:48 +02:00
Grégoire Paris
660cb3b6ac Migrate part of the tools namespace to PHP 8 syntax 2022-07-19 08:43:30 +02:00
Grégoire Paris
ad12df8fcc Remove unused exception 2022-07-19 08:43:30 +02:00
Grégoire Paris
b7ff742f84 Throw on error
That way we have some level of error handling, and don't muddy the
return type.
2022-07-19 08:43:29 +02:00
Grégoire Paris
220bfa1da5 Merge pull request #9911 from craigfrancis/3.0.x
Show Expr::countDistinct() and Expr::concat() use variable-length argument lists
2022-07-18 23:36:00 +02:00
Grégoire Paris
80188edbdd Merge remote-tracking branch 'origin/2.13.x' into 3.0.x 2022-07-18 23:06:06 +02:00
Craig Francis
0f98b3d9f2 Update Expr::countDistinct() and Expr::concat() to variable-length argument lists 2022-07-18 21:05:20 +01:00
Grégoire Paris
0b9fb97557 Merge pull request #9851 from greg0ire/php8-migration
Migrate more code to PHP8
2022-07-14 19:49:14 +02:00
Grégoire Paris
214a912b37 Migrate more code to PHP8 2022-07-14 19:26:22 +02:00
Grégoire Paris
990a1fe952 Merge pull request #9885 from greg0ire/fix-build 2022-07-13 12:10:19 +02:00
Grégoire Paris
1ac9d52332 Ignore errors caused by nullable assets filter 2022-07-12 20:24:19 +02:00
Grégoire Paris
1fa1e7072b Address removal/deprecation of ArrayType/ObjectType 2022-07-12 20:24:19 +02:00
Grégoire Paris
68dc5fe901 Rely on platform options
Custom schema options have been removed in doctrine/dbal 4
2022-07-12 20:24:19 +02:00
Grégoire Paris
db9c43feea Merge remote-tracking branch 'origin/2.13.x' into fix-build 2022-07-12 20:24:16 +02:00
Alexander M. Turek
9e0c7de24e Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Psalm 4.24.0, PHPStan 1.7.15 (#9865)
  PHP CodeSniffer 3.7.1, PHPStan 1.7.14 (#9858)
2022-06-28 15:42:44 +02:00
Alexander M. Turek
07fa660a47 Fix broken mocks due to removal of Driver::getSchemaManager() (#9869) 2022-06-28 15:30:59 +02:00
Grégoire Paris
734a1c63a2 Merge pull request #9852 from MarcBrillault/internal-php8
Migrate Internal namespace to PHP8
2022-06-18 21:40:27 +02:00
Marc Brillault
e22f02f198 Migrate Internal namespace to PHP8 2022-06-17 19:20:57 +02:00
Alexander M. Turek
318e6ec067 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Deprecate omitting the alias in QueryBuilder (#9765)
  Run tests on PHP 8.2 (#9840)
  PHPStan 1.7.13 (#9844)
  Flip conditional extension of legacy AnnotationDriver class (#9843)
  PHP CodeSniffer 3.7 (#9842)
  Make Reflection available to ConvertMappingCommand (#9619)
  Add missing property declaration
  Use proper API for introspection of tables
2022-06-17 10:42:13 +02:00
Grégoire Paris
af1303ec96 Merge pull request #9835 from greg0ire/php8-configuration
Migrate Configuration to PHP 8 syntax
2022-06-15 07:33:19 +02:00
Grégoire Paris
5ecf9e9202 update psalm baseline 2022-06-14 15:03:06 +02:00
Grégoire Paris
d52f9ee87e Migrate Configuration to PHP 8 syntax 2022-06-14 15:01:25 +02:00
Grégoire Paris
78c9490212 Merge pull request #9838 from greg0ire/remove-identity-columns-emulation
Stop allowing identity columns emulation
2022-06-11 18:10:45 +02:00
Grégoire Paris
2d230ce033 Stop allowing identity columns emulation
That feature has been deprecated.
2022-06-10 21:14:10 +02:00
Grégoire Paris
894dc4fc8f Merge pull request #9836 from greg0ire/3.0.x
Merge 2.13.x up into 3.0.x
2022-06-10 21:00:51 +02:00
Grégoire Paris
ec6ada4935 Merge remote-tracking branch 'origin/2.13.x' into 3.0.x 2022-06-10 20:14:33 +02:00
Grégoire Paris
646cbf6d30 Merge pull request #9828 from MarcBrillault/schema-validator-php8
migrate Tools/Schema* to php8.0
2022-06-10 09:12:06 +02:00
Grégoire Paris
47d9d46304 Merge pull request #9834 from doctrine/2.13.x
Merge 2.13.x up into 3.0.x
2022-06-10 00:01:53 +02:00
Grégoire Paris
2f16062f78 Merge pull request #9832 from greg0ire/enable-test-dbal-4
Run test with DBAL 4
2022-06-09 21:32:32 +02:00
Marc Brillault
e22bfec6b6 migrate Tools/Schema* to php8.0
refs #9772
2022-06-09 21:19:18 +02:00
Grégoire Paris
bf24177bfd Run test with DBAL 4 2022-06-09 21:16:36 +02:00
Grégoire Paris
62eb3bd96c Merge pull request #9829 from MarcBrillault/fix-build
Address removals of doctrine-dbal
2022-06-09 21:12:23 +02:00
Grégoire Paris
e1ebd77811 Run test only with DBAL 3
With DBAL 4, there is no longer a filtering of assets.
2022-06-09 19:40:41 +02:00
Grégoire Paris
69253bc083 Use a better check for the DBAL version
It seems AbstractPlatform::getGuidExpression() cannot do the trick, as
it is missing from both branches.
2022-06-09 19:40:41 +02:00
Grégoire Paris
36b35f99a4 Run foreign key tests on all platforms
SQLite now supports foreign keys.
2022-06-09 17:14:36 +02:00
Marc Brillault
a91d208d10 Address removals of doctrine-dbal
- Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets
- Doctrine\DBAL\Schema\Schema::visit
- Doctrine\DBAL\Tools\Console\Command\ReservedWordsCommand
2022-06-09 17:14:14 +02:00
Grégoire Paris
89dd9dd9ed Merge pull request #9815 from greg0ire/fix-deprecation-fk
Address deprecation of supportsForeignKeyConstraints()
2022-06-03 21:43:15 +02:00
Grégoire Paris
068da9d89f Address deprecation of supportsForeignKeyConstraints()
All platforms are supposed to support foreign key constraints now.
2022-06-03 21:24:19 +02:00
Grégoire Paris
53661fefc9 Merge pull request #9776 from greg0ire/native-types-abstract-query
Migrate to PHP 8: AbstractQuery and child classes
2022-06-03 20:53:45 +02:00
Grégoire Paris
d462ed3b4d Update baseline 2022-06-03 20:51:21 +02:00
Grégoire Paris
4a02a79abb Remove unneeded checks
Both array and ArrayCollection are countable.
2022-06-03 20:51:15 +02:00
Grégoire Paris
2ee4482d00 Remove deprecation when wrong fetch mode is used 2022-06-03 20:51:10 +02:00
Grégoire Paris
9f4339e7dc Run rector 2022-06-03 20:06:39 +02:00
Alexander M. Turek
7e20e97ee0 Remove MockBuilderCompatibilityTools (#9814) 2022-06-03 19:57:49 +02:00
Grégoire Paris
86d23f42db Add native types to AbstractQuery 2022-06-03 19:57:23 +02:00
Alexander M. Turek
b8299feae0 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  PHPStan 1.7.9 (#9812)
  Remove empty test file (#9805)
  Remove calls to deprecated MockBuilder::setMethods() (#9808)
  Deprecate passing null to Query::setFirstResult()
  Rename Abstract*Test to *TestCase (#9806)
  Add primary key on temp table (#9770)
  Fix wrong types (#9802)
  Widen return type
  Update baseline
  Fix
  Add type for AssociationMapping
2022-06-03 13:36:16 +02:00
Grégoire Paris
ec03eb3451 Merge pull request #9800 from greg0ire/rector-tests
Migrate tests to PHP8 syntax
2022-06-02 08:36:34 +02:00
Grégoire Paris
4117209b69 Revert to normal properties
The order is not the same as in the constructor, and that seems to
matter.
2022-06-02 07:24:48 +02:00
Grégoire Paris
a870290575 Add test to exclude rule 2022-06-02 07:24:48 +02:00
Grégoire Paris
e7a466b708 fix cs 2022-06-02 07:24:48 +02:00
Grégoire Paris
66ae30085b Adjust expectations 2022-06-01 22:51:13 +02:00
Grégoire Paris
c49636c923 Revert to untyped property
This causes "Cannot assign string to property
Doctrine\Tests\Models\Cache\ComplexAction::$action2 of type
Doctrine\Tests\Models\Cache\Action" for some reason.
2022-06-01 22:51:13 +02:00
Grégoire Paris
2f6303faef Revert to untyped property
This causes the following error for some reason:
Typed property Doctrine\Tests\ORM\Functional\TrainOrder::$train must not
be accessed before initialization
2022-06-01 22:51:13 +02:00
Grégoire Paris
8d4c3d3a34 Fix wrong types 2022-06-01 22:51:13 +02:00
Grégoire Paris
d212e52a20 Migrate tests to PHP 8 2022-06-01 22:51:11 +02:00
Grégoire Paris
301892bcff Merge remote-tracking branch 'origin/2.13.x' into 3.0.x 2022-06-01 22:44:52 +02:00
Alexander M. Turek
62892dc4e4 Made setters parameters mandatory (#9798) 2022-05-31 07:58:35 +02:00
Alexander M. Turek
f08aa92da0 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Add missing import (#9796)
  Deprecate calling setters without arguments (#9791)
  Move duplicate fixture into dedicated file (#9789)
  MockTreeWalker should be an SqlWalker (#9790)
2022-05-31 00:43:58 +02:00
Vincent Langlet
e5fe46a051 Precise phpdoc of getRootEntities (#9778)
* Precise phpdoc of getRootEntities

* Restrict from param

* Prefer phpdoc
2022-05-30 20:43:24 +02:00
Alexander M. Turek
0c8808a57a Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Make phpdoc more precise
  Deprecate setting fetch mode to random integers
  Prepare split of output walkers and tree walkers (#9786)
  PHPStan 1.7.0 (#9785)
  Deprecate passing null to Query::setDQL()
  Kill call_user_func(_array) (#9780)
  Fix wrong types for AbstractQuery and child classes (#9774)
  Document callable as possible
  Remove override phpdoc tag
  Add use statement (#9769)
2022-05-24 21:16:11 +02:00
Grégoire Paris
9384ca8e20 Merge pull request #9755 from greg0ire/mandatory-class-name-arg
Require new argument to joinColumnName()
2022-05-20 22:00:16 +02:00
Grégoire Paris
5e536ed412 Require new argument to joinColumnName() 2022-05-20 21:53:02 +02:00
Grégoire Paris
bb1fdcfa77 Merge pull request #9767 from greg0ire/3.0.x
Merge 2.13.x up into 3.0.x
2022-05-18 21:05:11 +02:00
Grégoire Paris
b91825bc73 Remove static PHP driver
It is deprecated in favor of its parent class.
2022-05-18 20:58:46 +02:00
Grégoire Paris
e879ce0b12 Merge remote-tracking branch 'origin/2.13.x' into 3.0.x 2022-05-18 08:02:06 +02:00
Grégoire Paris
c8735de2c1 Merge pull request #9758 from greg0ire/native-types-ns 2022-05-17 11:47:06 +02:00
Grégoire Paris
98cf5836fd Use native type declarations for naming strategies 2022-05-17 09:16:50 +02:00
Grégoire Paris
72810e9c05 Use createSchemaForModels()
This allows to get rid of tearDown(), which contained a special handling
that is no longer necessary since we switched away from explicitely
managed sequences, and caused the test suite to fail.
2022-05-16 22:38:59 +02:00
Grégoire Paris
3404ac174e Merge remote-tracking branch 'origin/2.13.x' into 3.0.x 2022-05-16 22:02:37 +02:00
Grégoire Paris
60f59b29ed Merge pull request #9757 from greg0ire/3.0.x
3.0.x
2022-05-12 09:24:53 +02:00
Grégoire Paris
0f7ae0a660 Merge remote-tracking branch 'origin/2.13.x' into 3.0.x 2022-05-12 09:06:58 +02:00
Alexander M. Turek
d294e1d453 Add native types to reflection property classes (#9631) 2022-05-11 20:34:49 +02:00
Grégoire Paris
1c97f970eb Merge pull request #9741 from greg0ire/number-aware-only
Make UnderscoreNamingStrategy number-aware only
2022-05-11 20:33:36 +02:00
Grégoire Paris
8117f42634 Make UnderscoreNamingStrategy number-aware only 2022-05-11 20:12:16 +02:00
Alexander M. Turek
e83404e57d Update Psalm baseline 2022-05-11 12:31:17 +02:00
Alexander M. Turek
499409dbc1 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Update Psalm baseline (#9751)
  Omit version number in README (#9749)
2022-05-11 12:30:18 +02:00
Grégoire Paris
3da3becc24 Merge pull request #9750 from doctrine/2.13.x 2022-05-10 11:52:23 +02:00
Sergei Morozov
a711fad058 Merge pull request #9742 from morozov/dbal-4@dev-static-analysis
Run static analysis with DBAL 4@dev
2022-05-08 12:49:49 -07:00
Sergei Morozov
2e856599b3 Run static analysis with DBAL 4@dev 2022-05-08 12:23:35 -07:00
Sergei Morozov
0119d8cbbc Accommodate API changes in the Column class
See https://github.com/doctrine/dbal/pull/3511
2022-05-08 11:54:22 -07:00
Sergei Morozov
d8159b8be2 Suppress known issues related to sequence-based identity generation
See https://github.com/doctrine/orm/issues/8850
2022-05-08 11:50:55 -07:00
Sergei Morozov
10442a7b4e Assert that date interval expressions are numeric strings
See https://github.com/doctrine/dbal/pull/3498
2022-05-08 11:50:55 -07:00
Sergei Morozov
413e2a79fb Separate PHPStan configuration for DBAL 4
See https://github.com/doctrine/dbal/pull/3480
2022-05-08 11:50:24 -07:00
Grégoire Paris
cfb0f7ffa7 Merge pull request #9738 from greg0ire/uuid-traces
Address some deprecations
2022-05-08 11:11:31 +02:00
Sergei Morozov
7e9ef10f67 Merge pull request #9740 from morozov/dbal-4@dev-pgsql
Build with DBAL 4@dev on PostgreSQL
2022-05-07 13:54:52 -07:00
Sergei Morozov
38f3d71a2f Merge pull request #9735 from morozov/dbal-4@dev-mysql
Build with DBAL 4@dev on MySQL and MariaDB
2022-05-07 13:54:37 -07:00
Sergei Morozov
9eba533f7c Build with DBAL 4@dev on PostgreSQL 2022-05-07 12:47:26 -07:00
Sergei Morozov
9acdac02cf Account for DBAL 4 no longer reordering table columns
See https://github.com/doctrine/dbal/pull/4777
2022-05-07 12:45:15 -07:00
Sergei Morozov
dfb7c1cc38 Build with DBAL 4@dev on MySQL and MariaDB 2022-05-07 08:11:56 -07:00
Sergei Morozov
702b491981 Account for DBAL 4 no longer reordering table columns
See https://github.com/doctrine/dbal/pull/4777
2022-05-07 08:11:56 -07:00
Sergei Morozov
44207c1628 Cast port in PHPUnit configuration to int
See https://github.com/doctrine/dbal/pull/2854
2022-05-07 08:11:01 -07:00
Sergei Morozov
85cfd10cae Merge branch '2.13.x' into 3.0.x 2022-05-07 07:59:50 -07:00
Grégoire Paris
6ead3a5cbb Make targetEntity mandatory 2022-05-07 15:47:05 +02:00
Grégoire Paris
e1586ea6cb Remove deprecated class 2022-05-07 15:45:56 +02:00
Grégoire Paris
72d88a2d69 Address deprecations 2022-05-07 15:41:11 +02:00
Grégoire Paris
3f5a1054a8 Remove remnants of UuidGeneratorStrategy 2022-05-07 15:38:41 +02:00
Sergei Morozov
134f12f419 Merge pull request #9734 from morozov/dbal-4.0.x-dev
Build with DBAL 4@dev on SQLite
2022-05-06 06:51:16 -07:00
Sergei Morozov
f3113f1a2f Build with DBAL 4@dev on SQLite 2022-05-06 06:36:23 -07:00
Alexander M. Turek
5d860bfc9b Merge pull request #9727 from morozov/dbal-4.0.x-dev
Run builds with DBAL 4.0.x-dev
2022-05-06 08:25:43 +02:00
Sergei Morozov
aa8c2937d7 Catch exception from Connection::commit() 2022-05-05 22:14:02 -07:00
Sergei Morozov
38e954248c Improve mocks 2022-05-05 22:14:02 -07:00
Sergei Morozov
6c64f7db34 Quote only strings
See https://github.com/doctrine/dbal/pull/3488
2022-05-05 22:14:01 -07:00
Sergei Morozov
d4a9015c2b Look up only string parameter types
See https://github.com/doctrine/dbal/pull/3569
2022-05-05 22:14:01 -07:00
Sergei Morozov
0c745d9021 Pass column name as part of the definition
See https://github.com/doctrine/dbal/pull/3583
2022-05-05 22:14:00 -07:00
Sergei Morozov
6ef4b5f396 Merge branch '2.13.x' into 3.0.x 2022-05-05 15:54:14 -07:00
Alexander M. Turek
ee83302751 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Allow doctrine/deprecations 1.0 (#9723)
  Allow setting column options like `charset` and `collation` everywhere (#9655)
  Fix psalm annotation
2022-05-05 18:09:05 +02:00
Sergei Morozov
7e83c9231d Merge pull request #9728 from morozov/phpunit-mysql-table-options
Test MySQL DDL using explicit table options
2022-05-04 12:23:54 -07:00
Sergei Morozov
f5e922ed92 Test MySQL DDL using explicit table options 2022-05-04 09:23:13 -07:00
Sergei Morozov
3c41e421de Remove ConnectionMock (#9724)
* Remove ConnectionMock::getExecuteStatements()

* Remove ConnectionMock::quote()

* Remove ConnectionMock
2022-05-02 21:30:40 +00:00
Grégoire Paris
4c2950a9da Remove last references to ClassMetadataInfo (#9713)
* Remove disconnected class metadata factory

It is unused apart from a tests where it is easily replaced.

* Remove ClassMetadataInfo

It has been deprecated for a long, long time.
2022-05-02 19:55:42 +02:00
Sergei Morozov
b8d3929dce Remove DriverResultMock (#9722) 2022-05-02 18:31:33 +02:00
Sergei Morozov
a8b4f05418 Remove ConnectionMock::delete() (#9717) 2022-05-02 17:14:18 +02:00
Sergei Morozov
f671fa8477 Remove DatabasePlatformMock (#9716) 2022-05-02 16:56:16 +02:00
Alexander M. Turek
53e8674899 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Psalm 4.23, PHPStan 1.6.3 (#9718)
2022-05-02 11:18:49 +02:00
Sergei Morozov
11049b441e Remove some mock classes (#9715) 2022-05-01 21:28:30 +00:00
Sergei Morozov
6fe69f16e2 Remove non-API DriverConnectionMock methods (#9709) 2022-05-01 22:37:32 +02:00
Grégoire Paris
8353e981be Merge remote-tracking branch 'origin/2.13.x' into 3.0.x 2022-05-01 22:24:36 +02:00
Sergei Morozov
ae76d91437 Merge branch '2.13.x' into 3.0.x 2022-05-01 12:27:51 -07:00
Sergei Morozov
04830b787c Merge pull request #9705 from morozov/remove-require-conversion
Remove support for Type::canRequireSQLConversion()
2022-05-01 11:42:42 -07:00
Sergei Morozov
fa844b1274 Remove support for Type::canRequireSQLConversion() 2022-04-30 12:07:31 -07:00
Grégoire Paris
3043dcc823 Merge remote-tracking branch 'origin/2.13.x' into 3.0.x 2022-04-29 08:57:20 +02:00
Grégoire Paris
7f2dd9bea1 Remove invalid mapping
The named queries feature has been removed in 3.0
2022-04-27 11:47:51 +02:00
Alexander M. Turek
01edf115db Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  PHPStan 1.6.1 (#9688)
  Drop SymfonyStyle[listing] for sqls (#9679)
  Remove dynamic property declarations (#9683)
  PHPStan 1.6.0 (#9682)
  Validate XML mapping against XSD file
  Document ORM drivers only really load ORM metadata
  Fix HydrationException::invalidDiscriminatorValue parameter type (#9676)
  Fix type on ClassMetadata discriminatorMap (#9675)
2022-04-27 10:30:29 +02:00
Alexander M. Turek
aebd3f30cb Remove the doctrine binary (#9662) 2022-04-22 22:46:50 +02:00
Alexander M. Turek
801a7504a6 Merge branch '2.13.x' into 3.0.x
* 2.13.x:
  Conditionally extend the old AnnotationDriver class (#9671)
2022-04-22 20:12:06 +02:00
Alexander M. Turek
a5ad24c0fd Drop support for persistence 2 (#9665)
* Drop support for persistence 2

* Switch to the common static analysis job
2022-04-22 20:09:39 +02:00
Alexander M. Turek
682b4e39fb Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Deprecate the doctrine binary (#9661)
  ScalarColumnHydrator: prevent early-bail on falsy values (#9663)
  Fix enum hydration when fetching partial results (#9657)
2022-04-19 21:34:02 +02:00
Alexander M. Turek
046683ab60 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Indicate support for doctrine/persistence 3 (#9656)
  Fix tests for enum ID hydration (#9658)
  Revert "Use charset/collation from column or table default when creating relations (#9636)"
  Fix test file/class names (#9649)
2022-04-15 13:22:31 +02:00
Alexander M. Turek
29a3495c8b Remove console helper (#9640) 2022-04-11 12:43:41 +02:00
Alexander M. Turek
b2ca75e074 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Leverage generic persistence event classes (#9633)
  Fix static analysis for Persistence 2.5 (#9648)
  Improve exception message (#9646)
  Deprecate console helper (#9641)
  Use charset/collation from column or table default when creating relations (#9636)
  Support Enum IDs and search by Enum fields (#9629)
  Fix composer install in contributing readme
2022-04-11 12:07:29 +02:00
Grégoire Paris
16748bdee9 Merge pull request #7196 from greg0ire/document_exception_split_bc_breaks
Document exception-splitting-related BC-breaks
2022-04-10 12:12:29 +02:00
Grégoire Paris
7ef5f7004d Document exception-splitting-related BC-breaks
Closes #7194
2022-04-09 11:10:59 +02:00
Alexander M. Turek
b7ff9db6e7 Remove deprecated handling of custom ObjectRepository implementations (#9634) 2022-04-08 01:25:27 +02:00
Alexander M. Turek
953c63392c Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Deprecate custom ObjectRepository implementations (#9533)
  Fix types on walkLiteral() and walkLikeExpression() (#9566)
2022-04-06 13:59:44 +02:00
Alexander M. Turek
476a6ba935 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Add support for array of enums (#9497)
  explicitly use the non-deprecated ORMException
2022-04-05 13:05:28 +02:00
Alexander M. Turek
6e65db5d2d Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Fix types on ResultSetMapping (#9621)
2022-04-04 22:14:14 +02:00
Alexander M. Turek
30591eaf56 Add native types to ResultSetMapping (#9620) 2022-04-04 17:36:54 +02:00
Alexander M. Turek
435587c260 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Support enums as default values (#9616)
  Skip tests requiring ObjectManagerAware (#9612)
  Remove "Description of" PHPDoc (#9611)
2022-03-31 00:19:16 +02:00
Alexander M. Turek
6a15af599c Remove support for ObjectManagerAware (#9614) 2022-03-28 21:07:55 +02:00
Alexander M. Turek
6ba0455129 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Update psalm.xml
  PHPStan 1.5.0 (#9607)
  Remove Sphinx config
  Indicate what feature is deprecated
  Implement int-mask-of where appropriate
  Use correct syntax for external links
  Update XmlExporter.php - Type problem in php8.x (#9589)
  Ignore deprecation from Persistence
  Stands with Ukraine (#9567)
  Use internal links when self-referencing
  Link to docs for the stable version
2022-03-28 10:51:09 +02:00
Grégoire Paris
793a3e3b75 Merge pull request #9597 from greg0ire/drop-ns-aliases
Remove support for entity namespace aliases
2022-03-20 19:15:30 +01:00
Grégoire Paris
a02dad303c Remove support for entity namespace aliases 2022-03-20 15:38:36 +01:00
Grégoire Paris
fc7e1c4e39 Merge remote-tracking branch 'origin/2.12.x' into 3.0.x 2022-03-20 14:38:53 +01:00
Grégoire Paris
032dd3289a Merge remote-tracking branch 'origin/2.12.x' into 3.0.x 2022-03-20 12:37:58 +01:00
Grégoire Paris
ab991de8a2 Merge remote-tracking branch 'origin/2.12.x' into 3.0.x 2022-03-19 13:47:54 +01:00
Alexander M. Turek
f14f5dc72c Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Leverage MemcachedAdapter::isSupported() (#9578)
  Baseline Psalm errors caused by DBAL 3.3.3 (#9577)
  Make sure MemcachedAdapter is supported before tring to use it (#9574)
  Fixing `:doc:` link (#9569)
  Adding PHP attributes (#9555)
  Remove reference to removed class
2022-03-11 00:06:20 +01:00
Alexander M. Turek
35615ef60e Merge pull request #9559 from doctrine/2.12.x 2022-03-03 20:30:55 +01:00
Alexander M. Turek
7f51f6d6ad Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Leverage Lexer's Token type
2022-03-01 00:12:27 +01:00
Alexander M. Turek
9ddd82bc3c Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Update baselines for Lexer 1.2.3 (#9546)
2022-02-28 14:13:43 +01:00
Alexander M. Turek
4292d8e0e6 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Document QueryComponent array shape (#9527)
  Improve templating
  Un-deprecate the current proxy mechanism (#9532)
  Remove unused methods
  Fix bug-#9536
2022-02-25 15:05:03 +01:00
Alexander M. Turek
5ebe984194 Add native types to SQLFilter (#9524) 2022-02-24 11:15:21 +01:00
Grégoire Paris
1712e3cbd0 Merge remote-tracking branch 'origin/2.12.x' into 3.0.x 2022-02-22 18:14:53 +01:00
Alexander M. Turek
87b894ea22 Leverage the Stringable interface (#9535) 2022-02-22 00:47:51 +01:00
Alexander M. Turek
597460d5ea Add native types to caches (#9508) 2022-02-22 00:47:00 +01:00
Alexander M. Turek
d739e44ee6 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Make creating test models more straightforward
  Trigger the desired code path
  Fix syntax typo in attributes reference (#9513)
  Constructor-Argument "options" has the same type as the associated property. (#9501)
2022-02-20 12:23:23 +01:00
Alexander M. Turek
6b33fa6ddd Add native types to EntityRepository (#9515) 2022-02-17 23:38:31 +01:00
Alexander M. Turek
3a9cc3d258 Remove TreeWalkerChainIterator (#9520) 2022-02-16 09:19:54 +01:00
Alexander M. Turek
dd4a38ce9f Merge 2.12.x into 3.0.x (#9518) 2022-02-15 23:11:54 +01:00
Alexander M. Turek
4158915af3 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Fix types on caches (#9507)
  Fix AbstractQuery::setParameter phpdoc (#9504)
  Added "false" value to $columnPrefix type declaration. (#9493)
2022-02-14 09:48:56 +01:00
Alexander M. Turek
954439af64 Remove quoting methods from ClassMetadata (#9500) 2022-02-11 21:09:32 +01:00
Alexander M. Turek
a74807aa86 Add native types to persisters (#9469) 2022-02-11 02:13:58 +01:00
Alexander M. Turek
0d4281ddfa Add native types to QueryBuilder (#9490) 2022-02-10 23:34:28 +01:00
Alexander M. Turek
32214ddaa6 Remove various deprecated methods and properties (#9498) 2022-02-10 09:33:11 +01:00
Alexander M. Turek
3a43f924c6 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Fix types on QueryBuilder (#9492)
  Fix types on EntityRepository (#9474)
  Avoid calling merge() (#9489)
  PHPStan 1.4.6, Psalm 4.20.0 (#9491)
  Fix `#[DiscriminatorMap]` params (#9487)
  Run tests with stricter error handling (#9482)
2022-02-09 01:05:25 +01:00
Alexander M. Turek
d13d0f5848 Remove ability to merge detached entities (#9488) 2022-02-09 00:43:44 +01:00
Alexander M. Turek
fd83543026 Remove ability to flush the EM partially (#9485) 2022-02-07 22:29:51 +01:00
Alexander M. Turek
607911ff27 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Modernize strpos() calls (#9480)
  Fix types on persisters (#9466)
  Rename DoctrineSetup to ORMSetup (#9481)
  Remove useless catches
2022-02-07 09:41:12 +01:00
Alexander M. Turek
e6f07fa0b1 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Deprecate methods removed in 3.0 (#9475)
  Skip tests related to PersistentObject if that class is missing (#9472)
  Run Postgres 14 and MariaDB 10.6 in CI (#9470)
2022-02-05 23:00:32 +01:00
Alexander M. Turek
1c67f4274b Remove ability to clear the UoW partially (#9471) 2022-02-05 18:00:37 +01:00
Alexander M. Turek
5efdff2a4f Remove PHP 7 code (#9462) 2022-02-02 22:53:48 +01:00
Alexander M. Turek
b15b95ee8f Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Check requirements for metadata drivers (#9459)
  PDO is not a required extension (#9457)
  Check requirements for metadata drivers (#9452)
  Remove trailing underscore (#9446)
2022-02-01 22:15:51 +01:00
Alexander M. Turek
b0a351f55a Remove support for Doctrine Cache (#9456) 2022-02-01 13:47:39 +01:00
Alexander M. Turek
1ea83e5774 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Support enums in findBy() calls (#9453)
  Streamline cache creation in tests (#9451)
2022-01-31 23:13:42 +01:00
Alexander M. Turek
4244dfe0a2 Add more native types to entity manager implementations (#9450) 2022-01-31 22:42:21 +01:00
Alexander M. Turek
e7e9db8cee Remove deprecated Setup class (#9447) 2022-01-31 09:11:39 +01:00
Alexander M. Turek
6b53ac6790 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Document the new DoctrineSetup class (#9448)
2022-01-31 09:09:23 +01:00
Alexander M. Turek
9872d1c997 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Introduce DoctrineSetup as a replacement for Setup (#9443)
  Introduce __unserialize behaviour in docs (#9390)
  Adapt test logic to PHP and SQLite II (#9442)
  Use the identify generator strategy
  Added php 8.1 to CI
  Psalm 4.19.0, PHPStan 1.4.3 (#9438)
  Ignore PHPUnit result cache everywhere (#9425)
2022-01-31 00:02:14 +01:00
Ahmadou Waly NDIAYE
31b7d78516 Removing the deprecated Named (Native) Queries in Metadata/EntityRepository (#9428)
This feature has been deprecated.
2022-01-30 15:57:12 +01:00
Alexander M. Turek
36dcf15ebc Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Introduce assertQueryCount (#9423)
2022-01-24 11:44:27 +01:00
Alexander M. Turek
56021c1af9 Remove DBAL 2 compatible SQL logging (#9422) 2022-01-24 08:09:53 +01:00
Alexander M. Turek
1d8dd53995 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Add support for PHP 8.1 enums in embedded classes (#9419)
  Switch tests to the middleware logging system (#9418)
  Added class-string typehint on $targetEntity (#9415)
  Allow DiscriminatorColumn with length=0 (#9410)
  Move UnderscoreNamingStrategyTest to correct namespace (#9414)
2022-01-24 00:13:13 +01:00
Alexander M. Turek
7375c8a058 Remove old cache accessors and mutators from query classes (#9392) 2022-01-23 21:29:47 +01:00
Alexander M. Turek
f61d5c24ac Remove check for getSQLResultCasing() (#9413) 2022-01-20 16:46:37 +01:00
Alexander M. Turek
7c17c11a04 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Fix types on CacheLogger implementations (#9401)
  Rework some tests that use hardcoded DBAL mocks (#9404)
2022-01-20 15:32:29 +01:00
Alexander M. Turek
d4f5db4b8a Add native types to CacheLogger implementations (#9400) 2022-01-20 10:27:21 +01:00
Alexander M. Turek
be4f88c811 Add native types to EntityHydrator (#9396) 2022-01-19 23:41:57 +01:00
Alexander M. Turek
6f150a343b Remove MultiGetRegion and add native types to Region implementations (#9403) 2022-01-19 23:41:26 +01:00
Sergei Morozov
30ea3a26d0 Merge pull request #9402 from morozov/dbal-4.0.x-types
Make test types compatible with Doctrine DBAL 4.0.x-dev
2022-01-18 15:53:20 -08:00
Sergei Morozov
cb3f554e38 Make test types compatible with Doctrine DBAL 4.0.x-dev 2022-01-18 15:33:48 -08:00
Alexander M. Turek
3999837279 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Deprecate MultiGetRegion (#9397)
  Fix type on loadCacheEntry (#9398)
  Update baselines for DBAL 3.3 (#9393)
  Accessing private properties and methods from the same class is forbidden (#9311)
  Expose enumType to DBAL to make native DB Enum possible (#9382)
2022-01-18 23:38:49 +01:00
Alexander M. Turek
9d3ad08a82 Stabilize DBAL dependency (#9395) 2022-01-18 10:39:40 +01:00
Alexander M. Turek
a21843f974 Remove AbstractIdGenerator::generate() (#9367)
… and add native types to ID generators
2022-01-17 23:19:58 +01:00
Alexander M. Turek
fd2bab9b11 Merge branch '2.12.x' into 3.0.x
* 2.12.x:
  Allow using Enum from different namespace than Entity (#9384)
  Corrected ORM version and added missing dependency (#9386)
  PHPStan 1.4.0 (#9385)
  [GH-9380] Bugfix: Delegate ReflectionEnumProperty::getAttributes(). (#9381)
  Support enum cases as parameters (#9373)
  Add detach as of list cascade-all operations (#9357)
2022-01-17 11:58:21 +01:00
Alexander M. Turek
7d8134ca36 Merge release 2.11.0 into 3.0.x (#9369) 2022-01-12 14:38:36 +01:00
Alexander M. Turek
fc287b2943 Merge branch '3.0.x' into 2.11.x-merge-up-into-3.0.x_gaayDumb 2022-01-12 14:31:05 +01:00
Alexander M. Turek
4b1a419883 Remove Configuration::ensureProductionSettings() (#9358) 2022-01-12 14:29:07 +01:00
Alexander M. Turek
002587824e Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Use EntityManagerInterface in type declarations (#9325)
  Add errors caused by the lexer update to the baselines (#9360)
  Generated/Virtual Columns: Insertable / Updateable (#9118)
  Remove the composer/package-versions-deprecated package
  Relax assertion to include null as possible outcome (#9355)
2022-01-12 11:10:49 +01:00
Alexander M. Turek
96241294bb Add native types to AbstractHydrator and child classes (#9353) 2022-01-12 10:57:33 +01:00
Alexander M. Turek
9f85e2769c Add native types to command classes (#9359) 2022-01-11 08:53:17 +01:00
Alexander M. Turek
cf62f931d9 Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Leverage generic ObjectManagerDecorator (#9312)
  Fix WhereInWalker description to better describe the behaviour of this class (#9268)
  Regenerate Psalm baseline
  Update Psalm baseline for Persistence 2.3 (#9349)
  Support readonly properties for read operations (#9316)
2022-01-10 00:02:21 +01:00
Alexander M. Turek
1af202bf10 Remove support for Doctrine Cache in second level cache (#9348) 2022-01-09 18:25:51 +01:00
Alexander M. Turek
98331a662f Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  PHPStan 1.3.3, Psalm 4.18.1
  Remove Psalm job for analyzing DBAL 2
  Use the readonly annotation (#9340)
  Add support for custom types with requireSQLConversion and ResultSetMappingBuilder::generateSelectClause()
  PSR-6 second level cache
  Fix type errors in AbstractQuery and QueryBuilder (#9275)
  Mark columnName as always set
  Add support for PHP 8.1 enums.
  Remove ignore rules for issues fixed upstream (#9336)
  [GH-9277] deprecate php driver (#9309)
2022-01-09 17:30:10 +01:00
Benjamin Eberlei
2dce2d0d63 [GH-9277] remove deprecated PHPDriver (#9308)
* Remove deprecated PHPDriver mapping driver, use StaticPHPDriver instead.

* Update docs

* Housekeeping

* Update UPGRADE.md
2022-01-06 10:24:05 +01:00
Alexander M. Turek
80bca72915 Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Added runtime deprecation to `UnitOfWork::commit()` and `clear()` (#9327)
  Document return type of getEntityState() (#9328)
  Fix broken type declaration (#9330)
  Enable some previously disabled PHPCS rules (#9324)
2022-01-05 10:06:28 +01:00
Alexander M. Turek
2a0c73d0e5 Add types to UnitOfWork (#9329) 2022-01-05 07:57:09 +01:00
Alexander M. Turek
ea97ea4c47 Add types to entity manager (#9292) 2022-01-05 00:29:22 +01:00
Alexander M. Turek
081f3e43c0 Enable PHPCS rules for PHP 8.0 (#9293) 2022-01-02 21:29:38 +01:00
Alexander M. Turek
9b3d89db04 Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Run static analysis with language level PHP 8.1 (#9314)
  Document LockMode enums (#9319)
  Document PHPUnit mocks with intersection types (#9318)
  Run PHP CodeSniffer on PHP 8.1 (#9317)
  Psalm 4.17.0 (#9315)
  Run static analysis on PHP 8.1 (#9310)
2022-01-02 20:18:23 +01:00
Alexander M. Turek
f151daa2f9 Replace mocks with middlewares. (#9291) 2022-01-02 13:04:19 +01:00
Alexander M. Turek
4b062a4010 Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Bump PHPStan & Psalm (#9303)
  Removing list "Lifecycle Events" (#9243)
  Drop unneeded backslashes
  Fix Hidden fields triggering error when using getSingleScalarResult() (#8340)
  Findby joined lookup (#8285)
2021-12-31 03:09:21 +01:00
Alexander M. Turek
d7817793c3 Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Fix type errors in AnnotationDriver (#9274)
2021-12-30 01:06:24 +01:00
Alexander M. Turek
3f2cc10bfe Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Leverage get_debug_type() (#9297)
  Fix return type (#9295)
  Synchronize Psalm baseline (#9296)
  Fix union type on QueryExpressionVisitorTest::testWalkComparison() (#9294)
  Allow arithmetic expressions within IN operator (#9242)
  Bump reusable workflows
2021-12-28 10:29:29 +01:00
Alexander M. Turek
9c07649287 Drop support for PHP 7.4 (#9290) 2021-12-27 19:57:51 +01:00
Alexander M. Turek
47f931c8b2 Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Enable UnusedUse sniff again (#9267)
  Whitelist composer plugins used by this repository (#9286)
  Fix XML export for `change-tracking-policy` (#9285)
  Allow symfony/cache 6 (#9283)
  Put actual value instead of index inside $originalEntityData. (#9244)
  Fix return types of cache interfaces (#9271)
  Better explain limitations of DQL "DELETE" (#9281)
  Fix docblocks on nullable EM properties (#9273)
  Docs: use canonical order for phpdoc tags, add missed semicolon (#9190)
  Make PrimaryReadReplicaConnection enforcement explicit (#9239)
  Regenerate Psalm baseline (#9272)
  Improve compatibility with Doctrine DBAL 4 (#9266)
  [docs] Fix wording for attributes=>parameters. (#9265)
  Support for nesting attributes with PHP 8.1 (#9241)
  Revert "Fix SchemaValidator with abstract child class in discriminator map (#9096)" (#9262)
  Docs: consistency for FQCN, spacing, etc (#9232)
2021-12-26 01:31:31 +01:00
Alexander M. Turek
61e2caf818 Remove EntityManager::transactional() (#9278) 2021-12-25 23:06:29 +01:00
Sergei Morozov
ad97969e93 Remove the orm:ensure-production-settings console command (#9263) 2021-12-18 11:17:37 +01:00
Sergei Morozov
25ca8dc835 Merge pull request #9259 from morozov/dbal-3.2-deprecations
Do not use AbstractPlatform::canEmulateSchemas()
2021-12-17 07:41:24 -08:00
Sergei Morozov
a41c6d32c3 Do not use AbstractPlatform::canEmulateSchemas() 2021-12-16 22:21:38 -08:00
Alexander M. Turek
f2e34bd172 Remove DBAL 2 compat code 2021-12-16 23:35:09 +01:00
Alexander M. Turek
5bbd1d20cf Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Address more DBAL 3.2 deprecations (#9256)
2021-12-16 23:28:03 +01:00
Alexander M. Turek
ff44938f9f Remove Setup::registerAutoloadDirectory() (#9251) 2021-12-14 10:06:46 +01:00
Alexander M. Turek
414aae50c2 Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Deprecate Setup::registerAutoloadDirectory() (#9249)
  PHPCS 3.6.2, Psalm 4.15.0 (#9247)
  Add SchemaIgnoreClasses property for #8195. (#9202)
  Remove fallbacks for old doctrine/annotations version (#9235)
  Update docs/en/reference/events.rst
  Added psalm param to abstract addFilterConstraint (#9229)
  Merge pull request #9210 from alexander-schranz/patch-2
  Fix typo assumptio--> assumption
  Update events.rst
  Completing links to `EventArgs` classes in overview table
  Using `const` for `type`
  [Documentation] Events Overview Table: Adding "Passed Argument" column
2021-12-14 00:12:10 +01:00
Alexander M. Turek
36160a81fb Remove YAML metadata mapping (#9237) 2021-12-13 19:43:11 +01:00
Alexander M. Turek
36a4f662b2 Remove code generators (#9226) 2021-12-11 13:31:40 +01:00
Alexander M. Turek
3d406e5213 Remove the Version class (#9227) 2021-12-06 13:27:13 +01:00
Alexander M. Turek
61237d4c08 Merge 2.11.x into 3.0.x (#9220) 2021-12-03 18:59:43 +01:00
Alexander M. Turek
341c6b2929 Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Add missing deprecations for YAML metadata mapping (#9206)
  Drop support for DBAL 3.1
  Psalm 4.13.1, PHPStan 1.2.0 (#9204)
  Add a psalm type for field mapping
  Use `equal to` instead of `equal of` in `assertSqlGeneration()` (#9195)
  Adding Attributes code block (#9161)
2021-11-29 17:28:44 +01:00
Grégoire Paris
4f7a2dfb50 Merge pull request #9197 from greg0ire/3.0.x
Merge 2.11.x into 3.0.x
2021-11-20 15:56:19 +01:00
Grégoire Paris
0542c12aae Merge remote-tracking branch 'origin/2.11.x' into 3.0.x 2021-11-20 15:46:04 +01:00
Mariusz Soltys
203cd6ecf2 Changed EntityRepository count method $criteria parameter to optional (#9104)
Currently to get count of all items there is need to provide empty array
to count() method as $criteria parameter is required.  I believe there
shouldn't be a need to provide it if I want to count all Entities
without any criteria.
2021-10-11 17:42:13 +02:00
Alexander M. Turek
2adc193421 Bump required PHP version to 7.4 (#9094) 2021-10-05 20:14:12 +02:00
Alexander M. Turek
fe2ebeef25 Merge 2.11.x into 3.0.x (#9093)
Merge 2.11.x into 3.0.x
2021-10-05 15:18:53 +02:00
Grégoire Paris
e9cd90f52e Refactor ORMException into an interface (#9085) 2021-10-05 15:15:40 +02:00
Grégoire Paris
d973fa129b Merge pull request #9076 from derrabus/remove/hydrate-row 2021-10-04 12:13:52 +02:00
Alexander M. Turek
4fa65f3853 Remove AbstractHydrator::hydrateRow() 2021-10-04 10:42:14 +02:00
Alexander M. Turek
f478fee5fb Merge 2.11.x into 3.0.x 2021-10-04 10:38:52 +02:00
Alexander M. Turek
4b4022358a Merge branch '2.11.x' into 3.0.x
* 2.11.x:
  Deprecate AbstractHydrator::hydrateRow() (#9072)
  Reflect latest minor release in metadata
  Revert "Pin laminas/automatic-releases to 1.11.1"
  Revert "Try using docker image directly"
  Revert "Explicitly disallow workflows for tags"
  Revert "Use org admin token"

Signed-off-by: Alexander M. Turek <me@derrabus.de>
2021-10-03 23:59:03 +02:00
Alexander M. Turek
413c33274d Remove support for DBAL 2 (#9069) 2021-10-03 23:32:44 +02:00
Alexander M. Turek
e13714e400 Remote Query::iterate() (#9070) 2021-10-03 22:59:44 +02:00
Grégoire Paris
bcd6ac885d Merge pull request #9066 from doctrine/2.10.x-merge-up-into-3.0.x_6159cb4217e697.30353290
Merge release 2.10.0 into 3.0.x
2021-10-03 17:51:19 +02:00
Grégoire Paris
512dfd6aaf Merge remote-tracking branch 'origin/2.10.x' into 3.0.x 2021-10-03 17:40:24 +02:00
Alexander M. Turek
d95f304073 Remove TABLE and UUID strategies (#9045) 2021-10-02 18:00:45 +02:00
Kévin Dunglas
18c153ef8a Merge branch '2.10.x' into 3.0.x 2021-09-30 08:37:31 +02:00
Alexander M. Turek
bb60e06b88 Merge pull request #9044 from doctrine/2.10.x
Merge 2.10.x into 3.0.x
2021-09-29 22:45:16 +02:00
Alexander M. Turek
0ae2a2ded8 Merge pull request #9005 from doctrine/2.10.x
Merge 2.10.x into 3.0.x
2021-09-12 01:51:58 +02:00
Grégoire Paris
811f1b19bd Merge pull request #8967 from doctrine/2.10.x
Merge 2.10.x into 3.0.x
2021-08-31 23:08:51 +02:00
Grégoire Paris
a0b739c259 Merge pull request #8912 from greg0ire/3.0.x
Merge 2.10.x into 3.0.x
2021-08-11 22:45:58 +02:00
Grégoire Paris
cbda203f23 Merge remote-tracking branch 'origin/2.10.x' into 3.0.x 2021-08-11 22:31:29 +02:00
Grégoire Paris
d7a5eab7d5 Merge pull request #8877 from greg0ire/3.0.x 2021-08-03 13:06:16 +02:00
Grégoire Paris
e51f0cec94 Merge remote-tracking branch 'origin/2.10.x' into 3.0.x 2021-08-03 12:42:16 +02:00
Grégoire Paris
c6f8dc2482 Change ->assert* to self::assert* 2021-08-03 12:41:53 +02:00
Grégoire Paris
e3387386e0 Merge pull request #8876 from doctrine/2.10.x
Merge 2.10.x up into 3.0.x
2021-08-03 07:46:06 +02:00
Grégoire Paris
520bfa5c42 Merge pull request #8319 from simPod/fix-args
Fix variadic args in Expr
2021-07-23 23:45:34 +02:00
Simon Podlipsky
77c73e8801 Fix variadic args in Expr 2021-07-23 10:34:34 +02:00
Grégoire Paris
0a46111bb2 Merge pull request #8849 from doctrine/2.10.x
Merge 2.10.x into 3.0.x
2021-07-18 12:47:34 +02:00
Grégoire Paris
551018136b Merge pull request #8826 from greg0ire/3.0.x 2021-07-08 12:15:53 +02:00
Grégoire Paris
48be0c1bd0 Merge remote-tracking branch 'origin/2.10.x' into 3.0.x 2021-07-06 08:31:57 +02:00
Grégoire Paris
1c983629b5 Merge pull request #8706 from greg0ire/3.0.x
Merge 2.9.x into 3.0.x
2021-05-21 09:27:38 +02:00
Grégoire Paris
65160f626d Merge remote-tracking branch 'origin/2.9.x' into 3.0.x 2021-05-21 09:17:53 +02:00
Grégoire Paris
1445a655fe Merge pull request #8654 from smilesrg/remove_entitymanager_copy
Removed EntityManagerInteface::copy()
2021-04-24 17:05:26 +02:00
Serhii Smirnov
cf8adfe5d3 Updated UPGRADE.md 2021-04-24 15:05:25 +03:00
Grégoire Paris
cf624ebb7b Merge pull request #8656 from doctrine/2.9.x
Manually merge 2.9.x into 3.0.x
2021-04-24 09:59:46 +02:00
Serhii Smirnov
c9a81e5241 #8462: Removed EntityManagerInterface::copy() 2021-04-23 19:31:40 +03:00
Grégoire Paris
d7e47f413f Merge pull request #8585 from doctrine/2.9.x
Merge 2.9.x into 3.0.x
2021-04-02 09:24:27 +02:00
Grégoire Paris
28b62cfb71 Merge pull request #8560 from doctrine/2.9.x
Merge 2.9.x up into 3.0.x
2021-03-25 23:48:51 +01:00
1970 changed files with 48765 additions and 88258 deletions

View File

@@ -6,26 +6,70 @@
"docsSlug": "doctrine-orm",
"versions": [
{
"name": "3.0",
"branchName": "3.0.x",
"name": "4.0",
"branchName": "4.0.x",
"slug": "latest",
"upcoming": true
},
{
"name": "3.2",
"branchName": "3.2.x",
"slug": "3.2",
"upcoming": true
},
{
"name": "3.1",
"branchName": "3.1.x",
"slug": "3.1",
"current": true
},
{
"name": "3.0",
"branchName": "3.0.x",
"slug": "3.0",
"maintained": false
},
{
"name": "2.20",
"branchName": "2.20.x",
"slug": "2.20",
"upcoming": true
},
{
"name": "2.19",
"branchName": "2.19.x",
"slug": "2.19",
"maintained": true
},
{
"name": "2.18",
"branchName": "2.18.x",
"slug": "2.18",
"maintained": false
},
{
"name": "2.17",
"branchName": "2.17.x",
"slug": "2.17",
"maintained": false
},
{
"name": "2.16",
"branchName": "2.16.x",
"slug": "2.16",
"maintained": false
},
{
"name": "2.15",
"branchName": "2.15.x",
"slug": "2.15",
"upcoming": true
"maintained": false
},
{
"name": "2.14",
"branchName": "2.14.x",
"slug": "2.14",
"current": true,
"aliases": [
"current",
"stable"
]
"maintained": false
},
{
"name": "2.13",
@@ -50,42 +94,6 @@
"branchName": "2.10.x",
"slug": "2.10",
"maintained": false
},
{
"name": "2.9",
"branchName": "2.9.x",
"slug": "2.9",
"maintained": false
},
{
"name": "2.8",
"branchName": "2.8.x",
"slug": "2.8",
"maintained": false
},
{
"name": "2.7",
"branchName": "2.7",
"slug": "2.7",
"maintained": false
},
{
"name": "2.6",
"branchName": "2.6",
"slug": "2.6",
"maintained": false
},
{
"name": "2.5",
"branchName": "2.5",
"slug": "2.5",
"maintained": false
},
{
"name": "2.4",
"branchName": "2.4",
"slug": "2.4",
"maintained": false
}
]
}

9
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "CI"
target-branch: "2.19.x"

View File

@@ -8,7 +8,7 @@ on:
- .github/workflows/coding-standards.yml
- bin/**
- composer.*
- lib/**
- src/**
- phpcs.xml.dist
- tests/**
push:
@@ -18,10 +18,10 @@ on:
- .github/workflows/coding-standards.yml
- bin/**
- composer.*
- lib/**
- src/**
- phpcs.xml.dist
- tests/**
jobs:
coding-standards:
uses: "doctrine/.github/.github/workflows/coding-standards.yml@3.0.0"
uses: "doctrine/.github/.github/workflows/coding-standards.yml@5.0.1"

View File

@@ -8,7 +8,7 @@ on:
- .github/workflows/continuous-integration.yml
- ci/**
- composer.*
- lib/**
- src/**
- phpunit.xml.dist
- tests/**
push:
@@ -18,7 +18,7 @@ on:
- .github/workflows/continuous-integration.yml
- ci/**
- composer.*
- lib/**
- src/**
- phpunit.xml.dist
- tests/**
@@ -33,36 +33,32 @@ jobs:
strategy:
matrix:
php-version:
- "7.2"
- "7.3"
- "7.4"
- "8.0"
- "8.1"
- "8.2"
- "8.3"
dbal-version:
- "default"
- "3.7"
extension:
- "sqlite3"
- "pdo_sqlite"
proxy:
- "common"
deps:
- "highest"
include:
- php-version: "8.0"
dbal-version: "2.13"
- php-version: "8.2"
dbal-version: "4@dev"
extension: "pdo_sqlite"
- php-version: "8.2"
dbal-version: "3@dev"
extension: "pdo_sqlite"
- php-version: "8.2"
dbal-version: "default"
dbal-version: "4@dev"
extension: "sqlite3"
- php-version: "8.1"
dbal-version: "default"
proxy: "lazy-ghost"
deps: "lowest"
extension: "pdo_sqlite"
steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"
with:
fetch-depth: 2
@@ -79,26 +75,25 @@ jobs:
if: "${{ matrix.dbal-version != 'default' }}"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
uses: "ramsey/composer-install@v3"
with:
composer-options: "--ignore-platform-req=php+"
dependency-versions: "${{ matrix.deps }}"
- name: "Run PHPUnit"
run: "vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml --coverage-clover=coverage-no-cache.xml"
env:
ENABLE_SECOND_LEVEL_CACHE: 0
ORM_PROXY_IMPLEMENTATION: "${{ matrix.proxy }}"
- name: "Run PHPUnit with Second Level Cache"
run: "vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml --exclude-group performance,non-cacheable,locking_functional --coverage-clover=coverage-cache.xml"
env:
ENABLE_SECOND_LEVEL_CACHE: 1
ORM_PROXY_IMPLEMENTATION: "${{ matrix.proxy }}"
- name: "Upload coverage file"
uses: "actions/upload-artifact@v3"
uses: "actions/upload-artifact@v4"
with:
name: "phpunit-${{ matrix.extension }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-coverage"
name: "phpunit-${{ matrix.extension }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-${{ matrix.deps }}-coverage"
path: "coverage*.xml"
@@ -111,21 +106,22 @@ jobs:
matrix:
php-version:
- "8.2"
- "8.3"
dbal-version:
- "default"
- "3@dev"
- "3.7"
postgres-version:
- "15"
extension:
- pdo_pgsql
- pgsql
include:
- php-version: "8.0"
dbal-version: "2.13"
- php-version: "8.2"
dbal-version: "4@dev"
postgres-version: "14"
extension: pdo_pgsql
- php-version: "8.2"
dbal-version: "default"
dbal-version: "3.7"
postgres-version: "9.6"
extension: pdo_pgsql
@@ -143,7 +139,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"
with:
fetch-depth: 2
@@ -160,7 +156,7 @@ jobs:
if: "${{ matrix.dbal-version != 'default' }}"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
uses: "ramsey/composer-install@v3"
with:
composer-options: "--ignore-platform-req=php+"
@@ -168,9 +164,9 @@ jobs:
run: "vendor/bin/phpunit -c ci/github/phpunit/pdo_pgsql.xml --coverage-clover=coverage.xml"
- name: "Upload coverage file"
uses: "actions/upload-artifact@v3"
uses: "actions/upload-artifact@v4"
with:
name: "${{ github.job }}-${{ matrix.postgres-version }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-coverage"
name: "${{ github.job }}-${{ matrix.postgres-version }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-${{ matrix.extension }}-coverage"
path: "coverage.xml"
@@ -183,19 +179,16 @@ jobs:
matrix:
php-version:
- "8.2"
- "8.3"
dbal-version:
- "default"
- "3@dev"
- "3.7"
- "4@dev"
mariadb-version:
- "10.9"
extension:
- "mysqli"
- "pdo_mysql"
include:
- php-version: "8.0"
dbal-version: "2.13"
mariadb-version: "10.6"
extension: "pdo_mysql"
services:
mariadb:
@@ -212,7 +205,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"
with:
fetch-depth: 2
@@ -229,7 +222,7 @@ jobs:
extensions: "${{ matrix.extension }}"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
uses: "ramsey/composer-install@v3"
with:
composer-options: "--ignore-platform-req=php+"
@@ -237,7 +230,7 @@ jobs:
run: "vendor/bin/phpunit -c ci/github/phpunit/${{ matrix.extension }}.xml --coverage-clover=coverage.xml"
- name: "Upload coverage file"
uses: "actions/upload-artifact@v3"
uses: "actions/upload-artifact@v4"
with:
name: "${{ github.job }}-${{ matrix.mariadb-version }}-${{ matrix.extension }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-coverage"
path: "coverage.xml"
@@ -252,9 +245,10 @@ jobs:
matrix:
php-version:
- "8.2"
- "8.3"
dbal-version:
- "default"
- "3@dev"
- "3.7"
mysql-version:
- "5.7"
- "8.0"
@@ -262,8 +256,12 @@ jobs:
- "mysqli"
- "pdo_mysql"
include:
- php-version: "8.0"
dbal-version: "2.13"
- php-version: "8.2"
dbal-version: "4@dev"
mysql-version: "8.0"
extension: "mysqli"
- php-version: "8.2"
dbal-version: "4@dev"
mysql-version: "8.0"
extension: "pdo_mysql"
@@ -281,7 +279,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"
with:
fetch-depth: 2
@@ -298,7 +296,7 @@ jobs:
if: "${{ matrix.dbal-version != 'default' }}"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
uses: "ramsey/composer-install@v3"
with:
composer-options: "--ignore-platform-req=php+"
@@ -313,45 +311,11 @@ jobs:
ENABLE_SECOND_LEVEL_CACHE: 1
- name: "Upload coverage files"
uses: "actions/upload-artifact@v3"
uses: "actions/upload-artifact@v4"
with:
name: "${{ github.job }}-${{ matrix.mysql-version }}-${{ matrix.extension }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-coverage"
path: "coverage*.xml"
phpunit-lower-php-versions:
name: "PHPUnit with SQLite"
runs-on: "ubuntu-22.04"
strategy:
matrix:
php-version:
- "7.1"
deps:
- "highest"
- "lowest"
steps:
- name: "Checkout"
uses: "actions/checkout@v3"
with:
fetch-depth: 2
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
php-version: "${{ matrix.php-version }}"
ini-values: "zend.assertions=1, apc.enable_cli=1"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
with:
dependency-versions: "${{ matrix.deps }}"
- name: "Run PHPUnit"
run: "vendor/bin/phpunit -c ci/github/phpunit/pdo_sqlite.xml"
upload_coverage:
name: "Upload coverage to Codecov"
runs-on: "ubuntu-22.04"
@@ -363,16 +327,18 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"
with:
fetch-depth: 2
- name: "Download coverage files"
uses: "actions/download-artifact@v3"
uses: "actions/download-artifact@v4"
with:
path: "reports"
- name: "Upload to Codecov"
uses: "codecov/codecov-action@v3"
uses: "codecov/codecov-action@v4"
with:
directory: reports
env:
CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}"

49
.github/workflows/documentation.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: "Documentation"
on:
pull_request:
branches:
- "*.x"
paths:
- .github/workflows/documentation.yml
- docs/**
push:
branches:
- "*.x"
paths:
- .github/workflows/documentation.yml
- docs/**
jobs:
validate-with-guides:
name: "Validate documentation with phpDocumentor/guides"
runs-on: "ubuntu-22.04"
steps:
- name: "Checkout code"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "8.3"
- name: "Remove existing composer file"
run: "rm composer.json"
- name: "Require phpdocumentor/guides-cli"
run: "composer require --dev phpdocumentor/guides-cli --no-update"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v3"
with:
dependency-versions: "highest"
- name: "Add orphan metadata where needed"
run: |
printf '%s\n\n%s\n' ":orphan:" "$(cat docs/en/sidebar.rst)" > docs/en/sidebar.rst
printf '%s\n\n%s\n' ":orphan:" "$(cat docs/en/reference/installation.rst)" > docs/en/reference/installation.rst
- name: "Run guides-cli"
run: "vendor/bin/guides -vvv --no-progress docs/en 2>&1 | grep -v 'No template found for rendering directive' | ( ! grep WARNING )"

View File

@@ -8,7 +8,7 @@ on:
paths:
- .github/workflows/phpbench.yml
- composer.*
- lib/**
- src/**
- phpbench.json
- tests/**
push:
@@ -17,7 +17,7 @@ on:
paths:
- .github/workflows/phpbench.yml
- composer.*
- lib/**
- src/**
- phpbench.json
- tests/**
@@ -32,11 +32,11 @@ jobs:
strategy:
matrix:
php-version:
- "7.4"
- "8.1"
steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"
with:
fetch-depth: 2
@@ -47,15 +47,8 @@ jobs:
coverage: "pcov"
ini-values: "zend.assertions=1, apc.enable_cli=1"
- name: "Cache dependencies installed with composer"
uses: "actions/cache@v3"
with:
path: "~/.composer/cache"
key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
restore-keys: "php-${{ matrix.php-version }}-composer-locked-"
- name: "Install dependencies with composer"
run: "composer update --no-interaction --no-progress"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v3"
- name: "Run PHPBench"
run: "vendor/bin/phpbench run --report=default"

View File

@@ -7,7 +7,7 @@ on:
jobs:
release:
uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@3.0.0"
uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@5.0.1"
secrets:
GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}

View File

@@ -7,97 +7,83 @@ on:
paths:
- .github/workflows/static-analysis.yml
- composer.*
- lib/**
- src/**
- phpstan*
- psalm*
- tests/Doctrine/StaticAnalysis/**
- tests/StaticAnalysis/**
push:
branches:
- "*.x"
paths:
- .github/workflows/static-analysis.yml
- composer.*
- lib/**
- src/**
- phpstan*
- psalm*
- tests/Doctrine/StaticAnalysis/**
- tests/StaticAnalysis/**
jobs:
static-analysis-phpstan:
name: "Static Analysis with PHPStan"
runs-on: "ubuntu-22.04"
name: Static Analysis with PHPStan
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
dbal-version:
- "default"
persistence-version:
- "default"
include:
- dbal-version: "2.13"
persistence-version: "default"
- dbal-version: "default"
persistence-version: "2.5"
- dbal-version: default
config: phpstan.neon
- dbal-version: 3.8.2
config: phpstan-dbal3.neon
steps:
- name: "Checkout code"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
coverage: "none"
php-version: "8.2"
coverage: none
php-version: "8.3"
tools: cs2pr
- name: "Require specific DBAL version"
- name: Require specific DBAL version
run: "composer require doctrine/dbal ^${{ matrix.dbal-version }} --no-update"
if: "${{ matrix.dbal-version != 'default' }}"
- name: "Require specific persistence version"
run: "composer require doctrine/persistence ^$([ ${{ matrix.persistence-version }} = default ] && echo '3.1' || echo ${{ matrix.persistence-version }}) --no-update"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
with:
dependency-versions: "highest"
- name: Install dependencies with Composer
uses: ramsey/composer-install@v2
- name: "Run a static analysis with phpstan/phpstan"
run: "vendor/bin/phpstan analyse"
if: "${{ matrix.dbal-version == 'default' && matrix.persistence-version == 'default'}}"
- name: "Run a static analysis with phpstan/phpstan"
run: "vendor/bin/phpstan analyse -c phpstan-dbal2.neon"
if: "${{ matrix.dbal-version == '2.13' }}"
- name: "Run a static analysis with phpstan/phpstan"
run: "vendor/bin/phpstan analyse -c phpstan-persistence2.neon"
if: "${{ matrix.dbal-version == 'default' && matrix.persistence-version != 'default'}}"
- name: Run static analysis with phpstan/phpstan
run: "vendor/bin/phpstan analyse -c ${{ matrix.config }} --error-format=checkstyle | cs2pr"
static-analysis-psalm:
name: "Static Analysis with Psalm"
runs-on: "ubuntu-22.04"
name: Static Analysis with Psalm
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
dbal-version:
- default
- 3.8.2
steps:
- name: "Checkout code"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
coverage: "none"
php-version: "8.2"
coverage: none
php-version: "8.3"
tools: cs2pr
- name: "Require specific persistence version"
run: "composer require doctrine/persistence ^3.1 --no-update"
- name: Require specific DBAL version
run: "composer require doctrine/dbal ^${{ matrix.dbal-version }} --no-update"
if: "${{ matrix.dbal-version != 'default' }}"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
with:
dependency-versions: "highest"
- name: Install dependencies with Composer
uses: ramsey/composer-install@v3
- name: "Run a static analysis with vimeo/psalm"
run: "vendor/bin/psalm --show-info=false --stats --output-format=github --threads=$(nproc)"
- name: Run static analysis with Vimeo Psalm
run: vendor/bin/psalm --shepherd

3
.gitignore vendored
View File

@@ -3,9 +3,6 @@ logs/
reports/
dist/
download/
lib/api/
lib/Doctrine/Common
lib/Doctrine/DBAL
/.settings/
.buildpath
.project

6
.gitmodules vendored
View File

@@ -1,6 +0,0 @@
[submodule "docs/en/_theme"]
path = docs/en/_theme
url = git://github.com/doctrine/doctrine-sphinx-theme.git
[submodule "lib/vendor/doctrine-build-common"]
path = lib/vendor/doctrine-build-common
url = git://github.com/doctrine/doctrine-build-common.git

View File

@@ -23,7 +23,7 @@ You may fix many some of the issues with `vendor/bin/phpcbf`.
Please try to add a test for your pull-request.
* If you want to fix a bug or provide a reproduce case, create a test file in
``tests/Doctrine/Tests/ORM/Functional/Ticket`` with the name of the ticket,
``tests/Tests/ORM/Functional/Ticket`` with the name of the ticket,
``DDC1234Test.php`` for example.
* If you want to contribute new functionality add unit- or functional tests
depending on the scope of the feature.
@@ -40,6 +40,11 @@ cd orm
composer install
```
You will also need to enable the PHP extension that provides the SQLite driver
for PDO: `pdo_sqlite`. How to do so depends on your system, but checking that it
is enabled can universally be done with `php -m`: that command should list the
extension.
To run the testsuite against another database, copy the ``phpunit.xml.dist``
to for example ``mysql.phpunit.xml`` and edit the parameters. You can
take a look at the ``ci/github/phpunit`` directory for some examples. Then run:
@@ -52,7 +57,7 @@ sqlite database.
Tips for creating unit tests:
1. If you put a test into the `Ticket` namespace as described above, put the testcase and all entities into the same class.
See `https://github.com/doctrine/orm/tree/2.8.x/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2306Test.php` for an
See `https://github.com/doctrine/orm/tree/3.0.x/tests/Tests/ORM/Functional/Ticket/DDC2306Test.php` for an
example.
## Getting merged

View File

@@ -1,11 +1,11 @@
| [3.0.x][3.0] | [2.14.x][2.14] | [2.13.x][2.13] |
|:----------------:|:----------------:|:----------:|
| [![Build status][3.0 image]][3.0] | [![Build status][2.14 image]][2.14] | [![Build status][2.13 image]][2.13] |
| [![Coverage Status][3.0 coverage image]][3.0 coverage]| [![Coverage Status][2.14 coverage image]][2.14 coverage] | [![Coverage Status][2.13 coverage image]][2.13 coverage] |
| [4.0.x][4.0] | [3.2.x][3.2] | [3.1.x][3.1] | [2.20.x][2.20] | [2.19.x][2.19] |
|:------------------------------------------------------:|:------------------------------------------------------:|:------------------------------------------------------:|:--------------------------------------------------------:|:--------------------------------------------------------:|
| [![Build status][4.0 image]][4.0] | [![Build status][3.2 image]][3.2] | [![Build status][3.1 image]][3.1] | [![Build status][2.20 image]][2.20] | [![Build status][2.19 image]][2.19] |
| [![Coverage Status][4.0 coverage image]][4.0 coverage] | [![Coverage Status][3.2 coverage image]][3.2 coverage] | [![Coverage Status][3.1 coverage image]][3.1 coverage] | [![Coverage Status][2.20 coverage image]][2.20 coverage] | [![Coverage Status][2.19 coverage image]][2.19 coverage] |
[<h1 align="center">🇺🇦 UKRAINE NEEDS YOUR HELP NOW!</h1>](https://www.doctrine-project.org/stop-war.html)
Doctrine ORM is an object-relational mapper for PHP 7.1+ that provides transparent persistence
Doctrine ORM is an object-relational mapper for PHP 8.1+ that provides transparent persistence
for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features
is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL),
inspired by Hibernate's HQL. This provides developers with a powerful alternative to SQL that maintains flexibility
@@ -18,15 +18,23 @@ without requiring unnecessary code duplication.
* [Documentation](https://www.doctrine-project.org/projects/doctrine-orm/en/stable/index.html)
[3.0 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.0.x
[3.0]: https://github.com/doctrine/orm/tree/3.0.x
[3.0 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.0.x/graph/badge.svg
[3.0 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.0.x
[2.14 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.14.x
[2.14]: https://github.com/doctrine/orm/tree/2.14.x
[2.14 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.14.x/graph/badge.svg
[2.14 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.14.x
[2.13 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.13.x
[2.13]: https://github.com/doctrine/orm/tree/2.13.x
[2.13 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.13.x/graph/badge.svg
[2.13 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.13.x
[4.0 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0.x
[4.0]: https://github.com/doctrine/orm/tree/4.0.x
[4.0 coverage image]: https://codecov.io/gh/doctrine/orm/branch/4.0.x/graph/badge.svg
[4.0 coverage]: https://codecov.io/gh/doctrine/orm/branch/4.0.x
[3.2 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.2.x
[3.2]: https://github.com/doctrine/orm/tree/3.2.x
[3.2 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.2.x/graph/badge.svg
[3.2 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.2.x
[3.1 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.1.x
[3.1]: https://github.com/doctrine/orm/tree/3.1.x
[3.1 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.1.x/graph/badge.svg
[3.1 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.1.x
[2.20 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.20.x
[2.20]: https://github.com/doctrine/orm/tree/2.20.x
[2.20 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.20.x/graph/badge.svg
[2.20 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.20.x
[2.19 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.19.x
[2.19]: https://github.com/doctrine/orm/tree/2.19.x
[2.19 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.19.x/graph/badge.svg
[2.19 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.19.x

View File

@@ -13,6 +13,5 @@ understand the assumptions we make.
- [DBAL Security Page](https://www.doctrine-project.org/projects/doctrine-dbal/en/stable/reference/security.html)
- [ORM Security Page](https://www.doctrine-project.org/projects/doctrine-orm/en/stable/reference/security.html)
If you find a Security bug in Doctrine, please report it on Jira and change the
Security Level to "Security Issues". It will be visible to Doctrine Core
developers and you only.
If you find a Security bug in Doctrine, please follow our
[Security reporting guidelines](https://www.doctrine-project.org/policies/security.html#reporting).

View File

@@ -1,3 +1,854 @@
# Upgrade to 3.1
## Deprecate `Doctrine\ORM\Mapping\ReflectionEnumProperty`
This class is deprecated and will be removed in 4.0.
Instead, use `Doctrine\Persistence\Reflection\EnumReflectionProperty` from
`doctrine/persistence`.
## Deprecate passing null to `ClassMetadata::fullyQualifiedClassName()`
Passing `null` to `Doctrine\ORM\ClassMetadata::fullyQualifiedClassName()` is
deprecated and will no longer be possible in 4.0.
## Deprecate array access
Using array access on instances of the following classes is deprecated:
- `Doctrine\ORM\Mapping\DiscriminatorColumnMapping`
- `Doctrine\ORM\Mapping\EmbedClassMapping`
- `Doctrine\ORM\Mapping\FieldMapping`
- `Doctrine\ORM\Mapping\JoinColumnMapping`
- `Doctrine\ORM\Mapping\JoinTableMapping`
# Upgrade to 3.0
## BC BREAK: Calling `ClassMetadata::getAssociationMappedByTargetField()` with the owning side of an association now throws an exception
Previously, calling
`Doctrine\ORM\Mapping\ClassMetadata::getAssociationMappedByTargetField()` with
the owning side of an association returned `null`, which was undocumented, and
wrong according to the phpdoc of the parent method.
If you do not know whether you are on the owning or inverse side of an association,
you can use `Doctrine\ORM\Mapping\ClassMetadata::isAssociationInverseSide()`
to find out.
## BC BREAK: `Doctrine\ORM\Proxy\Autoloader` no longer extends `Doctrine\Common\Proxy\Autoloader`
Make sure to use the former when writing a type declaration or an `instanceof` check.
## Minor BC BREAK: Changed order of arguments passed to `OneToOne`, `ManyToOne` and `Index` mapping PHP attributes
To keep PHP mapping attributes consistent, order of arguments passed to above attributes has been changed
so `$targetEntity` is a first argument now. This change affects only non-named arguments usage.
## BC BREAK: AUTO keyword for identity generation defaults to IDENTITY for PostgreSQL when using `doctrine/dbal` 4
When using the `AUTO` strategy to let Doctrine determine the identity generation mechanism for
an entity, and when using `doctrine/dbal` 4, PostgreSQL now uses `IDENTITY`
instead of `SEQUENCE` or `SERIAL`.
* If you want to upgrade your existing tables to identity columns, you will need to follow [migration to identity columns on PostgreSQL](https://www.doctrine-project.org/projects/doctrine-dbal/en/4.0/how-to/postgresql-identity-migration.html)
* If you want to keep using SQL sequences, you need to configure the ORM this way:
```php
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\Mapping\ClassMetadata;
assert($configuration instanceof Configuration);
$configuration->setIdentityGenerationPreferences([
PostgreSQLPlatform::CLASS => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
]);
```
## BC BREAK: Throw exceptions when using illegal attributes on Embeddable
There are only a few attributes allowed on an embeddable such as `#[Column]` or
`#[Embedded]`. Previously all others that target entity classes where ignored,
now they throw an exception.
## BC BREAK: Partial objects are removed
- The `PARTIAL` keyword in DQL no longer exists.
- `Doctrine\ORM\Query\AST\PartialObjectExpression`is removed.
- `Doctrine\ORM\Query\SqlWalker::HINT_PARTIAL` and
`Doctrine\ORM\Query::HINT_FORCE_PARTIAL_LOAD` are removed.
- `Doctrine\ORM\EntityManager*::getPartialReference()` is removed.
## BC BREAK: `Doctrine\ORM\Persister\Entity\EntityPersister::executeInserts()` return type changed to `void`
Implementors should adapt to the new signature, and should call
`UnitOfWork::assignPostInsertId()` for each entry in the previously returned
array.
## BC BREAK: `Doctrine\ORM\Proxy\ProxyFactory` no longer extends abstract factory from `doctrine/common`
It is no longer possible to call methods, constants or properties inherited
from that class on a `ProxyFactory` instance.
`Doctrine\ORM\Proxy\ProxyFactory::createProxyDefinition()` and
`Doctrine\ORM\Proxy\ProxyFactory::resetUninitializedProxy()` are removed as well.
## BC BREAK: lazy ghosts are enabled unconditionally
`Doctrine\ORM\Configuration::setLazyGhostObjectEnabled()` and
`Doctrine\ORM\Configuration::isLazyGhostObjectEnabled()` are now no-ops and
will be deprecated in 3.1.0
## BC BREAK: collisions in identity map are unconditionally rejected
`Doctrine\ORM\Configuration::setRejectIdCollisionInIdentityMap()` and
`Doctrine\ORM\Configuration::isRejectIdCollisionInIdentityMapEnabled()` are now
no-ops and will be deprecated in 3.1.0.
## BC BREAK: Lifecycle callback mapping on embedded classes is now explicitly forbidden
Lifecycle callback mapping on embedded classes produced no effect, and is now
explicitly forbidden to point out mistakes.
## BC BREAK: The `NOTIFY` change tracking policy is removed
You should use `DEFERRED_EXPLICIT` instead.
## BC BREAK: `Mapping\Driver\XmlDriver::__construct()` third argument is now enabled by default
The third argument to
`Doctrine\ORM\Mapping\Driver\XmlDriver::__construct()` was introduced to
let users opt-in to XML validation, that is now always enabled by default.
As a consequence, the same goes for
`Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver`, and for
`Doctrine\ORM\ORMSetup::createXMLMetadataConfiguration()`.
## BC BREAK: `Mapping\Driver\AttributeDriver::__construct()` second argument is now a no-op
The second argument to
`Doctrine\ORM\Mapping\Driver\AttributeDriver::__construct()` was introduced to
let users opt-in to a new behavior, that is now always enforced, regardless of
the value of that argument.
## BC BREAK: `Query::setDQL()` and `Query::setFirstResult()` no longer accept `null`
The `$dqlQuery` argument of `Doctrine\ORM\Query::setDQL()` must always be a
string.
The `$firstResult` argument of `Doctrine\ORM\Query::setFirstResult()` must
always be an integer.
## BC BREAK: `orm:schema-tool:update` option `--complete` is now a no-op
`orm:schema-tool:update` now behaves as if `--complete` was provided,
regardless of whether it is provided or not.
## BC BREAK: Removed `Doctrine\ORM\Proxy\Proxy` interface.
Use `Doctrine\Persistence\Proxy` instead to check whether proxies are initialized.
## BC BREAK: Overriding fields or associations declared in other than mapped superclasses
As stated in the documentation, fields and associations may only be overridden when being inherited
from mapped superclasses. Overriding them for parent entity classes now throws a `MappingException`.
## BC BREAK: Undeclared entity inheritance now throws a `MappingException`
As soon as an entity class inherits from another entity class, inheritance has to
be declared by adding the appropriate configuration for the root entity.
## Removed `getEntityManager()` in `Doctrine\ORM\Event\OnClearEventArgs` and `Doctrine\ORM\Event\*FlushEventArgs`
Use `getObjectManager()` instead.
## BC BREAK: Removed `Doctrine\ORM\Mapping\ClassMetadataInfo` class
Use `Doctrine\ORM\Mapping\ClassMetadata` instead.
## BC BREAK: Removed `Doctrine\ORM\Event\LifecycleEventArgs` class.
Use one of the dedicated event classes instead:
* `Doctrine\ORM\Event\PrePersistEventArgs`
* `Doctrine\ORM\Event\PreUpdateEventArgs`
* `Doctrine\ORM\Event\PreRemoveEventArgs`
* `Doctrine\ORM\Event\PostPersistEventArgs`
* `Doctrine\ORM\Event\PostUpdateEventArgs`
* `Doctrine\ORM\Event\PostRemoveEventArgs`
* `Doctrine\ORM\Event\PostLoadEventArgs`
## BC BREAK: Removed `AttributeDriver::$entityAnnotationClasses` and `AttributeDriver::getReader()`
* If you need to change the behavior of `AttributeDriver::isTransient()`,
override that method instead.
* The attribute reader is internal to the driver and should not be accessed from outside.
## BC BREAK: Removed `Doctrine\ORM\Query\AST\InExpression`
The AST parser will create a `InListExpression` or a `InSubselectExpression` when
encountering an `IN ()` DQL expression instead of a generic `InExpression`.
As a consequence, `SqlWalker::walkInExpression()` has been replaced by
`SqlWalker::walkInListExpression()` and `SqlWalker::walkInSubselectExpression()`.
## BC BREAK: Changed `EntityManagerInterface#refresh($entity)`, `EntityManagerDecorator#refresh($entity)` and `UnitOfWork#refresh($entity)` signatures
The new signatures of these methods add an optional `LockMode|int|null $lockMode`
param with default `null` value (no lock).
## BC Break: Removed AnnotationDriver
The annotation driver and anything related to annotation has been removed.
Please migrate to another mapping driver.
The `Doctrine\ORM\Mapping\Annotation` maker interface has been removed in favor of the new
`Doctrine\ORM\Mapping\MappingAttribute` interface.
## BC BREAK: Removed `EntityManager::create()`
The constructor of `EntityManager` is now public and must be used instead of the `create()` method.
However, the constructor expects a `Connection` while `create()` accepted an array with connection parameters.
You can pass that array to DBAL's `Doctrine\DBAL\DriverManager::getConnection()` method to bootstrap the
connection.
## BC BREAK: Removed `QueryBuilder` methods and constants.
The following `QueryBuilder` constants and methods have been removed:
1. `SELECT`,
2. `DELETE`,
3. `UPDATE`,
4. `STATE_DIRTY`,
5. `STATE_CLEAN`,
6. `getState()`,
7. `getType()`.
## BC BREAK: Omitting only the alias argument for `QueryBuilder::update` and `QueryBuilder::delete` is not supported anymore
When building an UPDATE or DELETE query and when passing a class/type to the function, the alias argument must not be omitted.
### Before
```php
$qb = $em->createQueryBuilder()
->delete('User u')
->where('u.id = :user_id')
->setParameter('user_id', 1);
```
### After
```php
$qb = $em->createQueryBuilder()
->delete('User', 'u')
->where('u.id = :user_id')
->setParameter('user_id', 1);
```
## BC BREAK: Split output walkers and tree walkers
`SqlWalker` and its child classes don't implement the `TreeWalker` interface
anymore.
The following methods have been removed from the `TreeWalker` interface and
from the `TreeWalkerAdapter` and `TreeWalkerChain` classes:
* `setQueryComponent()`
* `walkSelectClause()`
* `walkFromClause()`
* `walkFunction()`
* `walkOrderByClause()`
* `walkOrderByItem()`
* `walkHavingClause()`
* `walkJoin()`
* `walkSelectExpression()`
* `walkQuantifiedExpression()`
* `walkSubselect()`
* `walkSubselectFromClause()`
* `walkSimpleSelectClause()`
* `walkSimpleSelectExpression()`
* `walkAggregateExpression()`
* `walkGroupByClause()`
* `walkGroupByItem()`
* `walkDeleteClause()`
* `walkUpdateClause()`
* `walkUpdateItem()`
* `walkWhereClause()`
* `walkConditionalExpression()`
* `walkConditionalTerm()`
* `walkConditionalFactor()`
* `walkConditionalPrimary()`
* `walkExistsExpression()`
* `walkCollectionMemberExpression()`
* `walkEmptyCollectionComparisonExpression()`
* `walkNullComparisonExpression()`
* `walkInExpression()`
* `walkInstanceOfExpression()`
* `walkLiteral()`
* `walkBetweenExpression()`
* `walkLikeExpression()`
* `walkStateFieldPathExpression()`
* `walkComparisonExpression()`
* `walkInputParameter()`
* `walkArithmeticExpression()`
* `walkArithmeticTerm()`
* `walkStringPrimary()`
* `walkArithmeticFactor()`
* `walkSimpleArithmeticExpression()`
* `walkPathExpression()`
* `walkResultVariable()`
* `getExecutor()`
The following changes have been made to the abstract `TreeWalkerAdapter` class:
* The method `setQueryComponent()` is now protected.
* The method `_getQueryComponents()` has been removed in favor of
`getQueryComponents()`.
## BC BREAK: Removed identity columns emulation through sequences
If the platform you are using does not support identity columns, you should
switch to the `SEQUENCE` strategy.
## BC BREAK: Made setters parameters mandatory
The following methods require an argument when being called. Pass `null`
instead of omitting the argument.
* `Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs::setFoundMetadata()`
* `Doctrine\ORM\AbstractQuery::setHydrationCacheProfile()`
* `Doctrine\ORM\AbstractQuery::setResultCache()`
* `Doctrine\ORM\AbstractQuery::setResultCacheProfile()`
## BC BREAK: New argument to `NamingStrategy::joinColumnName()`
### Before
```php
<?php
class MyStrategy implements NamingStrategy
{
/**
* @param string $propertyName A property name.
*/
public function joinColumnName($propertyName): string
{
// …
}
}
```
### After
The `class-string` type for `$className` can be inherited from the signature of
the interface.
```php
<?php
class MyStrategy implements NamingStrategy
{
/**
* {@inheritdoc}
*/
public function joinColumnName(string $propertyName, string $className): string
{
// …
}
}
```
## BC BREAK: Remove `StaticPHPDriver` and `DriverChain`
Use `Doctrine\Persistence\Mapping\Driver\StaticPHPDriver` and
`Doctrine\Persistence\Mapping\Driver\MappingDriverChain` from
`doctrine/persistence` instead.
## BC BREAK: `UnderscoreNamingStrategy` is number aware only
The second argument to `UnderscoreNamingStrategy::__construct()` was dropped,
the strategy can no longer be unaware of numbers.
## BC BREAK: Remove `Doctrine\ORM\Tools\DisconnectedClassMetadataFactory`
No replacement is provided.
## BC BREAK: Remove support for `Type::canRequireSQLConversion()`
This feature was deprecated in DBAL 3.3.0 and will be removed in DBAL 4.0.
The value conversion methods are now called regardless of the type.
The `MappingException::sqlConversionNotAllowedForIdentifiers()` method has been removed
as no longer relevant.
## BC Break: Removed the `doctrine` binary.
The documentation explains how the console tools can be bootstrapped for
standalone usage:
https://www.doctrine-project.org/projects/doctrine-orm/en/stable/reference/tools.html
The method `ConsoleRunner::printCliConfigTemplate()` has been removed as well
because it was only useful in the context of the `doctrine` binary.
## BC Break: Removed `EntityManagerHelper` and related logic
All console commands require a `$entityManagerProvider` to be passed via the
constructor. Commands won't try to get the entity manager from a previously
registered `em` console helper.
The following classes have been removed:
* `Doctrine\ORM\Tools\Console\EntityManagerProvider\HelperSetManagerProvider`
* `Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper`
The following breaking changes have been applied to `Doctrine\ORM\Tools\Console\ConsoleRunner`:
* The method `createHelperSet()` has been removed.
* The methods `run()` and `createApplication()` don't accept an instance of
`HelperSet` as first argument anymore.
* The method `addCommands()` requires an instance of `EntityManagerProvider`
as second argument now.
## BC Break: `Exception\ORMException` is no longer a class, but an interface
All methods in `Doctrine\ORM\ORMException` have been extracted to dedicated exceptions.
* `missingMappingDriverImpl()` => `Exception\MissingMappingDriverImplementation::create()`
* `unrecognizedField()` => `Persisters\Exception\UnrecognizedField::byName()`
* `unexpectedAssociationValue()` => `Exception\UnexpectedAssociationValue::create()`
* `invalidOrientation()` => `Persisters\Exception\InvalidOrientation::fromClassNameAndField()`
* `entityManagerClosed()` => `Exception\EntityManagerClosed::create()`
* `invalidHydrationMode()` => `Exception\InvalidHydrationMode::fromMode()`
* `mismatchedEventManager()` => `Exception\MismatchedEventManager::create()`
* `findByRequiresParameter()` => `Repository\Exception\InvalidMagicMethodCall::onMissingParameter()`
* `invalidMagicCall()` => `Repository\Exception\InvalidMagicMethodCall::becauseFieldNotFoundIn()`
* `invalidFindByInverseAssociation()` => `Repository\Exception\InvalidFindByCall::fromInverseSideUsage()`
* `invalidResultCacheDriver()` => `Cache\Exception\InvalidResultCacheDriver::create()`
* `notSupported()` => `Exception\NotSupported::create()`
* `queryCacheNotConfigured()` => `QueryCacheNotConfigured::create()`
* `metadataCacheNotConfigured()` => `Cache\Exception\MetadataCacheNotConfigured::create()`
* `queryCacheUsesNonPersistentCache()` => `Cache\Exception\QueryCacheUsesNonPersistentCache::fromDriver()`
* `metadataCacheUsesNonPersistentCache()` => `Cache\Exception\MetadataCacheUsesNonPersistentCache::fromDriver()`
* `proxyClassesAlwaysRegenerating()` => `Exception\ProxyClassesAlwaysRegenerating::create()`
* `invalidEntityRepository()` => `Exception\InvalidEntityRepository::fromClassName()`
* `missingIdentifierField()` => `Exception\MissingIdentifierField::fromFieldAndClass()`
* `unrecognizedIdentifierFields()` => `Exception\UnrecognizedIdentifierFields::fromClassAndFieldNames()`
* `cantUseInOperatorOnCompositeKeys()` => `Persisters\Exception\CantUseInOperatorOnCompositeKeys::create()`
## BC Break: `CacheException` is no longer a class, but an interface
All methods in `Doctrine\ORM\Cache\CacheException` have been extracted to dedicated exceptions.
* `updateReadOnlyCollection()` => `Cache\Exception\CannotUpdateReadOnlyCollection::fromEntityAndField()`
* `updateReadOnlyEntity()` => `Cache\Exception\CannotUpdateReadOnlyEntity::fromEntity()`
* `nonCacheableEntity()` => `Cache\Exception\NonCacheableEntity::fromEntity()`
* `nonCacheableEntityAssociation()` => `Cache\Exception\NonCacheableEntityAssociation::fromEntityAndField()`
## BC Break: Missing type declaration added for identifier generators
Although undocumented, it was possible to configure a custom repository
class that implements `ObjectRepository` but does not extend the
`EntityRepository` base class. Repository classes have to extend
`EntityRepository` now.
## BC BREAK: Removed support for entity namespace alias
- `EntityManager::getRepository()` no longer accepts the entity namespace alias
notation.
- `Configuration::addEntityNamespace()` and
`Configuration::getEntityNamespace()` have been removed.
## BC BREAK: Remove helper methods from `AbstractCollectionPersister`
The following protected methods of
`Doctrine\ORM\Cache\Persister\Collection\AbstractCollectionPersister`
have been removed.
* `evictCollectionCache()`
* `evictElementCache()`
## BC BREAK: `Doctrine\ORM\Query\TreeWalkerChainIterator`
This class has been removed without replacement.
## BC BREAK: Remove quoting methods from `ClassMetadata`
The following methods have been removed from the class metadata because
quoting is handled by implementations of `Doctrine\ORM\Mapping\QuoteStrategy`:
* `getQuotedIdentifierColumnNames()`
* `getQuotedColumnName()`
* `getQuotedTableName()`
* `getQuotedJoinTableName()`
## BC BREAK: Remove ability to merge detached entities
Merge semantics was a poor fit for the PHP "share-nothing" architecture.
In addition to that, merging caused multiple issues with data integrity
in the managed entity graph, which was constantly spawning more edge-case
bugs/scenarios.
The method `UnitOfWork::merge()` has been removed. The method
`EntityManager::merge()` will throw an exception on each call.
## BC BREAK: Removed ability to partially flush/commit entity manager and unit of work
The following methods don't accept a single entity or an array of entities anymore:
* `Doctrine\ORM\EntityManager::flush()`
* `Doctrine\ORM\Decorator\EntityManagerDecorator::flush()`
* `Doctrine\ORM\UnitOfWork::commit()`
The semantics of `flush()` and `commit()` will remain the same, but the change
tracking will be performed on all entities managed by the unit of work, and not
just on the provided entities, as the parameter is now completely ignored.
## BC BREAK: Removed ability to partially clear entity manager and unit of work
* Passing an argument other than `null` to `EntityManager::clear()` will raise
an exception.
* The unit of work cannot be cleared partially anymore. Passing an argument to
`UnitOfWork::clear()` does not have any effect anymore; the unit of work is
cleared completely.
* The method `EntityRepository::clear()` has been removed.
* The methods `getEntityClass()` and `clearsAllEntities()` have been removed
from `OnClearEventArgs`.
## BC BREAK: Remove support for Doctrine Cache
The Doctrine Cache library is not supported anymore. The following methods
have been removed from `Doctrine\ORM\Configuration`:
* `getQueryCacheImpl()`
* `setQueryCacheImpl()`
* `getHydrationCacheImpl()`
* `setHydrationCacheImpl()`
* `getMetadataCacheImpl()`
* `setMetadataCacheImpl()`
The methods have been replaced by PSR-6 compatible counterparts
(just strip the `Impl` suffix from the old name to get the new one).
## BC BREAK: Remove `Doctrine\ORM\Configuration::newDefaultAnnotationDriver`
This functionality has been moved to the new `ORMSetup` class. Call
`Doctrine\ORM\ORMSetup::createDefaultAnnotationDriver()` to create
a new annotation driver.
## BC BREAK: Remove `Doctrine\ORM\Tools\Setup`
In our effort to migrate from Doctrine Cache to PSR-6, the `Setup` class which
accepted a Doctrine Cache instance in each method has been removed.
The replacement is `Doctrine\ORM\ORMSetup` which accepts a PSR-6
cache instead.
## BC BREAK: Removed named queries
All APIs related to named queries have been removed.
## BC BREAK: Remove old cache accessors and mutators from query classes
The following methods have been removed from `AbstractQuery`:
* `setResultCacheDriver()`
* `getResultCacheDriver()`
* `useResultCache()`
* `getResultCacheLifetime()`
* `getResultCacheId()`
The following methods have been removed from `Query`:
* `setQueryCacheDriver()`
* `getQueryCacheDriver()`
## BC BREAK: Remove `Doctrine\ORM\Cache\MultiGetRegion`
The interface has been merged into `Doctrine\ORM\Cache\Region`.
## BC BREAK: Rename `AbstractIdGenerator::generate()` to `generateId()`
* Implementations of `AbstractIdGenerator` have to implement the method
`generateId()`.
* The method `generate()` has been removed from `AbstractIdGenerator`.
## BC BREAK: Remove cache settings inspection
Doctrine does not provide its own cache implementation anymore and relies on
the PSR-6 standard instead. As a consequence, we cannot determine anymore
whether a given cache adapter is suitable for a production environment.
Because of that, functionality that aims to do so has been removed:
* `Configuration::ensureProductionSettings()`
* the `orm:ensure-production-settings` console command
## BC BREAK: PSR-6-based second level cache
The second level cache has been reworked to consume a PSR-6 cache. Using a
Doctrine Cache instance is not supported anymore.
* `DefaultCacheFactory`: The constructor expects a PSR-6 cache item pool as
second argument now.
* `DefaultMultiGetRegion`: This class has been removed.
* `DefaultRegion`:
* The constructor expects a PSR-6 cache item pool as second argument now.
* The protected `$cache` property is removed.
* The properties `$name` and `$lifetime` as well as the constant
`REGION_KEY_SEPARATOR` and the method `getCacheEntryKey()` are
`private` now.
* The method `getCache()` has been removed.
## BC Break: Remove `Doctrine\ORM\Mapping\Driver\PHPDriver`
Use `StaticPHPDriver` instead when you want to programmatically configure
entity metadata.
## BC BREAK: Remove `Doctrine\ORM\EntityManagerInterface#transactional()`
This method has been replaced by `Doctrine\ORM\EntityManagerInterface#wrapInTransaction()`.
## BC BREAK: Removed support for schema emulation.
The ORM no longer attempts to emulate schemas on SQLite.
## BC BREAK: Remove `Setup::registerAutoloadDirectory()`
Use Composer's autoloader instead.
## BC BREAK: Remove YAML mapping drivers.
If your code relies on `YamlDriver` or `SimpleYamlDriver`, you **MUST** migrate to
attribute, annotation or XML drivers instead.
You can use the `orm:convert-mapping` command to convert your metadata mapping to XML
_before_ upgrading to 3.0:
```sh
php doctrine orm:convert-mapping xml /path/to/mapping-path-converted-to-xml
```
## BC BREAK: Remove code generators and related console commands
These console commands have been removed:
* `orm:convert-d1-schema`
* `orm:convert-mapping`
* `orm:generate:entities`
* `orm:generate-repositories`
These classes have been deprecated:
* `Doctrine\ORM\Tools\ConvertDoctrine1Schema`
* `Doctrine\ORM\Tools\EntityGenerator`
* `Doctrine\ORM\Tools\EntityRepositoryGenerator`
The entire `Doctrine\ORM\Tools\Export` namespace has been removed as well.
## BC BREAK: Removed `Doctrine\ORM\Version`
Use Composer's runtime API if you _really_ need to check the version of the ORM package at runtime.
## BC BREAK: EntityRepository::count() signature change
The argument `$criteria` of `Doctrine\ORM\EntityRepository::count()` is now
optional. Overrides in child classes should be made compatible.
## BC BREAK: changes in exception hierarchy
- `Doctrine\ORM\ORMException` has been removed
- `Doctrine\ORM\Exception\ORMException` is now an interface
## Variadic methods now use native variadics
The following methods were using `func_get_args()` to simulate a variadic argument:
- `Doctrine\ORM\Query\Expr#andX()`
- `Doctrine\ORM\Query\Expr#orX()`
- `Doctrine\ORM\QueryBuilder#select()`
- `Doctrine\ORM\QueryBuilder#addSelect()`
- `Doctrine\ORM\QueryBuilder#where()`
- `Doctrine\ORM\QueryBuilder#andWhere()`
- `Doctrine\ORM\QueryBuilder#orWhere()`
- `Doctrine\ORM\QueryBuilder#groupBy()`
- `Doctrine\ORM\QueryBuilder#andGroupBy()`
- `Doctrine\ORM\QueryBuilder#having()`
- `Doctrine\ORM\QueryBuilder#andHaving()`
- `Doctrine\ORM\QueryBuilder#orHaving()`
A variadic argument is now actually used in their signatures signature (`...$x`).
Signatures of overridden methods should be changed accordingly
## Minor BC BREAK: removed `Doctrine\ORM\EntityManagerInterface#copy()`
Method `Doctrine\ORM\EntityManagerInterface#copy()` never got its implementation and is removed in 3.0.
## BC BREAK: Removed classes related to UUID and TABLE generator strategies
The following classes have been removed:
- `Doctrine\ORM\Id\TableGenerator`
- `Doctrine\ORM\Id\UuidGenerator`
Using the `UUID` strategy for generating identifiers is not supported anymore.
## BC BREAK: Removed `Query::iterate()`
The deprecated method `Query::iterate()` has been removed along with the
following classes and methods:
- `AbstractHydrator::iterate()`
- `AbstractHydrator::hydrateRow()`
- `IterableResult`
Use `toIterable()` instead.
# Upgrade to 2.19
## Deprecate calling `ClassMetadata::getAssociationMappedByTargetField()` with the owning side of an association
Calling
`Doctrine\ORM\Mapping\ClassMetadata::getAssociationMappedByTargetField()` with
the owning side of an association returns `null`, which is undocumented, and
wrong according to the phpdoc of the parent method.
If you do not know whether you are on the owning or inverse side of an association,
you can use `Doctrine\ORM\Mapping\ClassMetadata::isAssociationInverseSide()`
to find out.
## Deprecate `Doctrine\ORM\Query\Lexer::T_*` constants
Use `Doctrine\ORM\Query\TokenType::T_*` instead.
# Upgrade to 2.17
## Deprecate annotations classes for named queries
The following classes have been deprecated:
* `Doctrine\ORM\Mapping\NamedNativeQueries`
* `Doctrine\ORM\Mapping\NamedNativeQuery`
* `Doctrine\ORM\Mapping\NamedQueries`
* `Doctrine\ORM\Mapping\NamedQuery`
## Deprecate `Doctrine\ORM\Query\Exec\AbstractSqlExecutor::_sqlStatements`
Use `Doctrine\ORM\Query\Exec\AbstractSqlExecutor::sqlStatements` instead.
## Undeprecate `Doctrine\ORM\Proxy\Autoloader`
It will be a full-fledged class, no longer extending
`Doctrine\Common\Proxy\Autoloader` in 3.0.x.
## Deprecated: reliance on the non-optimal defaults that come with the `AUTO` identifier generation strategy
When the `AUTO` identifier generation strategy was introduced, the best
strategy at the time was selected for each database platform.
A lot of time has passed since then, and with ORM 3.0.0 and DBAL 4.0.0, support
for better strategies will be added.
Because of that, it is now deprecated to rely on the historical defaults when
they differ from what we will be recommended in the future.
Instead, you should pick a strategy for each database platform you use, and it
will be used when using `AUTO`. As of now, only PostgreSQL is affected by this.
It is recommended that PostgreSQL users configure their existing and new
applications to use `SEQUENCE` until `doctrine/dbal` 4.0.0 is released:
```php
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\ORM\Configuration;
assert($configuration instanceof Configuration);
$configuration->setIdentityGenerationPreferences([
PostgreSQLPlatform::CLASS => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
]);
```
When DBAL 4 is released, `AUTO` will result in `IDENTITY`, and the above
configuration should be removed to migrate to it.
## Deprecate `EntityManagerInterface::getPartialReference()`
This method does not have a replacement and will be removed in 3.0.
## Deprecate not-enabling lazy-ghosts
Not enabling lazy ghost objects is deprecated. In ORM 3.0, they will be always enabled.
Ensure `Doctrine\ORM\Configuration::setLazyGhostObjectEnabled(true)` is called to enable them.
# Upgrade to 2.16
## Deprecated accepting duplicate IDs in the identity map
For any given entity class and ID value, there should be only one object instance
representing the entity.
In https://github.com/doctrine/orm/pull/10785, a check was added that will guard this
in the identity map. The most probable cause for violations of this rule are collisions
of application-provided IDs.
In ORM 2.16.0, the check was added by throwing an exception. In ORM 2.16.1, this will be
changed to a deprecation notice. ORM 3.0 will make it an exception again. Use
`\Doctrine\ORM\Configuration::setRejectIdCollisionInIdentityMap()` if you want to opt-in
to the new mode.
## Potential changes to the order in which `INSERT`s are executed
In https://github.com/doctrine/orm/pull/10547, the commit order computation was improved
to fix a series of bugs where a correct (working) commit order was previously not found.
Also, the new computation may get away with fewer queries being executed: By inserting
referred-to entities first and using their ID values for foreign key fields in subsequent
`INSERT` statements, additional `UPDATE` statements that were previously necessary can be
avoided.
When using database-provided, auto-incrementing IDs, this may lead to IDs being assigned
to entities in a different order than it was previously the case.
## Deprecated returning post insert IDs from `EntityPersister::executeInserts()`
Persisters implementing `\Doctrine\ORM\Persisters\Entity\EntityPersister` should no longer
return an array of post insert IDs from their `::executeInserts()` method. Make the
persister call `Doctrine\ORM\UnitOfWork::assignPostInsertId()` instead.
## Changing the way how reflection-based mapping drivers report fields, deprecated the "old" mode
In ORM 3.0, a change will be made regarding how the `AttributeDriver` reports field mappings.
This change is necessary to be able to detect (and reject) some invalid mapping configurations.
To avoid surprises during 2.x upgrades, the new mode is opt-in. It can be activated on the
`AttributeDriver` and `AnnotationDriver` by setting the `$reportFieldsWhereDeclared`
constructor parameter to `true`. It will cause `MappingException`s to be thrown when invalid
configurations are detected.
Not enabling the new mode will cause a deprecation notice to be raised. In ORM 3.0,
only the new mode will be available.
# Upgrade to 2.15
## Deprecated configuring `JoinColumn` on the inverse side of one-to-one associations
For one-to-one associations, the side using the `mappedBy` attribute is the inverse side.
The owning side is the entity with the table containing the foreign key. Using `JoinColumn`
configuration on the _inverse_ side now triggers a deprecation notice and will be an error
in 3.0.
## Deprecated overriding fields or associations not declared in mapped superclasses
As stated in the documentation, fields and associations may only be overridden when being inherited
from mapped superclasses. Overriding them for parent entity classes now triggers a deprecation notice
and will be an error in 3.0.
## Deprecated undeclared entity inheritance
As soon as an entity class inherits from another entity class, inheritance has to
be declared by adding the appropriate configuration for the root entity.
## Deprecated stubs for "concrete table inheritance"
This third way of mapping class inheritance was never implemented. Code stubs are
now deprecated and will be removed in 3.0.
* `\Doctrine\ORM\Mapping\ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS` constant
* `\Doctrine\ORM\Mapping\ClassMetadataInfo::isInheritanceTypeTablePerClass()` method
* Using `TABLE_PER_CLASS` as the value for the `InheritanceType` attribute or annotation
or in XML configuration files.
# Upgrade to 2.14
## Deprecated `Doctrine\ORM\Persisters\Exception\UnrecognizedField::byName($field)` method.
@@ -1100,7 +1951,7 @@ The EntityRepository now has an interface Doctrine\Persistence\ObjectRepository.
The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory the operation of the new reader should be backwards compatible, but it has to be setup differently to work that way:
// new call to the AnnotationRegistry
\Doctrine\Common\Annotations\AnnotationRegistry::registerFile('/doctrine-src/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
\Doctrine\Common\Annotations\AnnotationRegistry::registerFile('/doctrine-src/src/Mapping/Driver/DoctrineAnnotations.php');
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env php
<?php
include(__DIR__ . '/doctrine.php');

View File

@@ -1,43 +0,0 @@
<?php
fwrite(
STDERR,
'[Warning] The use of this script is discouraged. See'
. ' https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/tools.html#doctrine-console'
. ' for instructions on bootstrapping the console runner.'
. PHP_EOL
);
echo PHP_EOL . PHP_EOL;
require_once 'Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Symfony');
$classLoader->register();
$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php';
$helperSet = null;
if (file_exists($configFile)) {
if ( ! is_readable($configFile)) {
trigger_error(
'Configuration file [' . $configFile . '] does not have read permission.', E_USER_ERROR
);
}
require $configFile;
foreach ($GLOBALS as $helperSetCandidate) {
if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) {
$helperSet = $helperSetCandidate;
break;
}
}
}
$helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet();
\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet);

View File

@@ -1,9 +0,0 @@
@echo off
if "%PHPBIN%" == "" set PHPBIN=@php_bin@
if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH
GOTO RUN
:USE_PEAR_PATH
set PHPBIN=%PHP_PEAR_PHP_BIN%
:RUN
"%PHPBIN%" "@bin_dir@\doctrine" %*

View File

@@ -1,62 +0,0 @@
<?php
use Symfony\Component\Console\Helper\HelperSet;
use Doctrine\ORM\Tools\Console\ConsoleRunner;
fwrite(
STDERR,
'[Warning] The use of this script is discouraged. See'
. ' https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/tools.html#doctrine-console'
. ' for instructions on bootstrapping the console runner.'
. PHP_EOL
);
echo PHP_EOL . PHP_EOL;
$autoloadFiles = [
__DIR__ . '/../vendor/autoload.php',
__DIR__ . '/../../../autoload.php'
];
foreach ($autoloadFiles as $autoloadFile) {
if (file_exists($autoloadFile)) {
require_once $autoloadFile;
break;
}
}
$directories = [getcwd(), getcwd() . DIRECTORY_SEPARATOR . 'config'];
$configFile = null;
foreach ($directories as $directory) {
$configFile = $directory . DIRECTORY_SEPARATOR . 'cli-config.php';
if (file_exists($configFile)) {
break;
}
}
if ( ! file_exists($configFile)) {
ConsoleRunner::printCliConfigTemplate();
exit(1);
}
if ( ! is_readable($configFile)) {
echo 'Configuration file [' . $configFile . '] does not have read permission.' . "\n";
exit(1);
}
$commands = [];
$helperSet = require $configFile;
if ( ! ($helperSet instanceof HelperSet)) {
foreach ($GLOBALS as $helperSetCandidate) {
if ($helperSetCandidate instanceof HelperSet) {
$helperSet = $helperSetCandidate;
break;
}
}
}
ConsoleRunner::run($helperSet, $commands);

View File

@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
convertDeprecationsToExceptions="true"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="error_reporting" value="-1" />
@@ -14,6 +13,9 @@
<var name="db_port" value="3306"/>
<var name="db_user" value="root" />
<var name="db_dbname" value="doctrine_tests" />
<var name="db_default_table_option_charset" value="utf8mb4" />
<var name="db_default_table_option_collation" value="utf8mb4_unicode_ci" />
<var name="db_default_table_option_engine" value="InnoDB" />
<!-- necessary change for some CLI/console output test assertions -->
<env name="COLUMNS" value="120"/>
@@ -25,11 +27,11 @@
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
</whitelist>
</filter>
<source>
<include>
<directory suffix=".php">../../../src</directory>
</include>
</source>
<groups>
<exclude>

View File

@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
convertDeprecationsToExceptions="true"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="error_reporting" value="-1" />
@@ -14,6 +13,9 @@
<var name="db_port" value="3306"/>
<var name="db_user" value="root" />
<var name="db_dbname" value="doctrine_tests" />
<var name="db_default_table_option_charset" value="utf8mb4" />
<var name="db_default_table_option_collation" value="utf8mb4_unicode_ci" />
<var name="db_default_table_option_engine" value="InnoDB" />
<!-- necessary change for some CLI/console output test assertions -->
<env name="COLUMNS" value="120"/>
@@ -25,12 +27,11 @@
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
</whitelist>
</filter>
<source>
<include>
<directory suffix=".php">../../../src</directory>
</include>
</source>
<groups>
<exclude>

View File

@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
convertDeprecationsToExceptions="true"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="error_reporting" value="-1" />
@@ -25,11 +24,11 @@
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
</whitelist>
</filter>
<source>
<include>
<directory suffix=".php">../../../src</directory>
</include>
</source>
<groups>
<exclude>

View File

@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
convertDeprecationsToExceptions="true"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="error_reporting" value="-1" />
@@ -23,11 +22,11 @@
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
</whitelist>
</filter>
<source>
<include>
<directory suffix=".php">../../../src</directory>
</include>
</source>
<groups>
<exclude>

View File

@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
convertDeprecationsToExceptions="true"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="error_reporting" value="-1" />
@@ -25,11 +24,11 @@
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
</whitelist>
</filter>
<source>
<include>
<directory suffix=".php">../../../src</directory>
</include>
</source>
<groups>
<exclude>

View File

@@ -3,9 +3,8 @@
xsi:noNamespaceSchemaLocation="../../../vendor/phpunit/phpunit/phpunit.xsd"
colors="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
convertDeprecationsToExceptions="true"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="error_reporting" value="-1" />
@@ -23,11 +22,11 @@
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
</whitelist>
</filter>
<source>
<include>
<directory suffix=".php">../../../src</directory>
</include>
</source>
<groups>
<exclude>

View File

@@ -20,56 +20,45 @@
"sort-packages": true
},
"require": {
"php": "^7.1 || ^8.0",
"php": "^8.1",
"composer-runtime-api": "^2",
"ext-ctype": "*",
"doctrine/cache": "^1.12.1 || ^2.1.1",
"doctrine/collections": "^1.5 || ^2.0",
"doctrine/common": "^3.0.3",
"doctrine/dbal": "^2.13.1 || ^3.2",
"doctrine/collections": "^2.2",
"doctrine/dbal": "^3.8.2 || ^4",
"doctrine/deprecations": "^0.5.3 || ^1",
"doctrine/event-manager": "^1.2 || ^2",
"doctrine/inflector": "^1.4 || ^2.0",
"doctrine/instantiator": "^1.3",
"doctrine/lexer": "^1.2.3 || ^2",
"doctrine/persistence": "^2.4 || ^3",
"doctrine/instantiator": "^1.3 || ^2",
"doctrine/lexer": "^3",
"doctrine/persistence": "^3.3.1",
"psr/cache": "^1 || ^2 || ^3",
"symfony/console": "^4.2 || ^5.0 || ^6.0",
"symfony/polyfill-php72": "^1.23",
"symfony/polyfill-php80": "^1.16"
"symfony/console": "^5.4 || ^6.0 || ^7.0",
"symfony/var-exporter": "^6.3.9 || ^7.0"
},
"require-dev": {
"doctrine/annotations": "^1.13 || ^2",
"doctrine/coding-standard": "^9.0.2 || ^11.0",
"phpbench/phpbench": "^0.16.10 || ^1.0",
"phpstan/phpstan": "~1.4.10 || 1.10.6",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6",
"doctrine/coding-standard": "^12.0",
"phpbench/phpbench": "^1.0",
"phpstan/phpstan": "1.11.1",
"phpunit/phpunit": "^10.4.0",
"psr/log": "^1 || ^2 || ^3",
"squizlabs/php_codesniffer": "3.7.2",
"symfony/cache": "^4.4 || ^5.4 || ^6.0",
"symfony/var-exporter": "^4.4 || ^5.4 || ^6.2",
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"vimeo/psalm": "4.30.0 || 5.9.0"
},
"conflict": {
"doctrine/annotations": "<1.13 || >= 3.0"
"symfony/cache": "^5.4 || ^6.2 || ^7.0",
"vimeo/psalm": "5.24.0"
},
"suggest": {
"ext-dom": "Provides support for XSD validation for XML mapping files",
"symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0",
"symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
"symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0"
},
"autoload": {
"psr-4": { "Doctrine\\ORM\\": "lib/Doctrine/ORM" }
"psr-4": { "Doctrine\\ORM\\": "src" }
},
"autoload-dev": {
"psr-4": {
"Doctrine\\Tests\\": "tests/Doctrine/Tests",
"Doctrine\\StaticAnalysis\\": "tests/Doctrine/StaticAnalysis",
"Doctrine\\Performance\\": "tests/Doctrine/Performance"
"Doctrine\\Tests\\": "tests/Tests",
"Doctrine\\StaticAnalysis\\": "tests/StaticAnalysis",
"Doctrine\\Performance\\": "tests/Performance"
}
},
"bin": ["bin/doctrine"],
"archive": {
"exclude": ["!vendor", "tests", "*phpunit.xml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor", "*.swp"]
}

4
docs/.gitignore vendored
View File

@@ -1,4 +0,0 @@
en/_exts/configurationblock.pyc
build
en/_build
.idea

3
docs/.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "en/_theme"]
path = en/_theme
url = https://github.com/doctrine/doctrine-sphinx-theme.git

View File

@@ -35,14 +35,12 @@ class ConfigurationBlock(Directive):
'html': 'HTML',
'xml': 'XML',
'php': 'PHP',
'yaml': 'YAML',
'jinja': 'Twig',
'html+jinja': 'Twig',
'jinja+html': 'Twig',
'php+html': 'PHP',
'html+php': 'PHP',
'ini': 'INI',
'php-annotations': 'Annotations',
}
def run(self):

View File

@@ -140,11 +140,6 @@ Now we're going to create the ``point`` type and implement all required methods.
return $value;
}
public function canRequireSQLConversion()
{
return true;
}
public function convertToPHPValueSQL($sqlExpr, AbstractPlatform $platform)
{
return sprintf('AsText(%s)', $sqlExpr);

View File

@@ -36,71 +36,50 @@ Our entities look like:
namespace Bank\Entities;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
#[ORM\Entity]
class Account
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id;
/**
* @ORM\Column(type="string", unique=true)
*/
private string $no;
/**
* @ORM\OneToMany(targetEntity="Entry", mappedBy="account", cascade={"persist"})
*/
private array $entries;
/**
* @ORM\Column(type="integer")
*/
private int $maxCredit = 0;
public function __construct(string $no, int $maxCredit = 0)
{
$this->no = $no;
$this->maxCredit = $maxCredit;
$this->entries = new \Doctrine\Common\Collections\ArrayCollection();
#[ORM\OneToMany(targetEntity: Entry::class, mappedBy: 'account', cascade: ['persist'])]
private Collection $entries;
public function __construct(
#[ORM\Column(type: 'string', unique: true)]
private string $no,
#[ORM\Column(type: 'integer')]
private int $maxCredit = 0,
) {
$this->entries = new ArrayCollection();
}
}
/**
* @ORM\Entity
*/
#[ORM\Entity]
class Entry
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id;
/**
* @ORM\ManyToOne(targetEntity="Account", inversedBy="entries")
*/
private Account $account;
/**
* @ORM\Column(type="integer")
*/
private int $amount;
public function __construct(Account $account, int $amount)
{
$this->account = $account;
$this->amount = $amount;
public function __construct(
#[ORM\ManyToOne(targetEntity: Account::class, inversedBy: 'entries')]
private Account $account,
#[ORM\Column(type: 'integer')]
private int $amount,
) {
// more stuff here, from/to whom, stated reason, execution date and such
}
public function getAmount(): Amount
{
return $this->amount;
@@ -193,9 +172,8 @@ relation with this method:
public function addEntry(int $amount): void
{
$this->assertAcceptEntryAllowed($amount);
$e = new Entry($this, $amount);
$this->entries[] = $e;
$this->entries[] = new Entry($this, $amount);
}
}
@@ -211,20 +189,20 @@ Now look at the following test-code for our entities:
{
public function testAddEntry()
{
$account = new Account("123456", $maxCredit = 200);
$account = new Account("123456", maxCredit: 200);
$this->assertEquals(0, $account->getBalance());
$account->addEntry(500);
$this->assertEquals(500, $account->getBalance());
$account->addEntry(-700);
$this->assertEquals(-200, $account->getBalance());
}
public function testExceedMaxLimit()
{
$account = new Account("123456", $maxCredit = 200);
$account = new Account("123456", maxCredit: 200);
$this->expectException(Exception::class);
$account->addEntry(-1000);
}
@@ -285,22 +263,19 @@ entries collection) we want to add an aggregate field called
<?php
class Account
{
/**
* @ORM\Column(type="integer")
*/
#[ORM\Column(type: 'integer')]
private int $balance = 0;
public function getBalance(): int
{
return $this->balance;
}
public function addEntry(int $amount): void
{
$this->assertAcceptEntryAllowed($amount);
$e = new Entry($this, $amount);
$this->entries[] = $e;
$this->entries[] = new Entry($this, $amount);
$this->balance += $amount;
}
}
@@ -331,13 +306,13 @@ potentially lead to inconsistent state. See this example:
// The Account $accId has a balance of 0 and a max credit limit of 200:
// request 1 account
$account1 = $em->find(Account::class, $accId);
// request 2 account
$account2 = $em->find(Account::class, $accId);
$account1->addEntry(-200);
$account2->addEntry(-200);
// now request 1 and 2 both flush the changes.
The aggregate field ``Account::$balance`` is now -200, however the
@@ -357,10 +332,8 @@ Optimistic locking is as easy as adding a version column:
class Account
{
/**
* @ORM\Column(type="integer")
* @ORM\Version
*/
#[ORM\Column(type: 'integer')]
#[ORM\Version]
private int $version;
}

View File

@@ -99,12 +99,12 @@ discuss it step by step:
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER); // (2)
$parser->match(Lexer::T_OPEN_PARENTHESIS); // (3)
$parser->match(TokenType::T_IDENTIFIER); // (2)
$parser->match(TokenType::T_OPEN_PARENTHESIS); // (3)
$this->firstDateExpression = $parser->ArithmeticPrimary(); // (4)
$parser->match(Lexer::T_COMMA); // (5)
$parser->match(TokenType::T_COMMA); // (5)
$this->secondDateExpression = $parser->ArithmeticPrimary(); // (6)
$parser->match(Lexer::T_CLOSE_PARENTHESIS); // (3)
$parser->match(TokenType::T_CLOSE_PARENTHESIS); // (3)
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
@@ -183,23 +183,23 @@ I'll skip the blah and show the code for this function:
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$parser->match(TokenType::T_IDENTIFIER);
$parser->match(TokenType::T_OPEN_PARENTHESIS);
$this->firstDateExpression = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA);
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(TokenType::T_COMMA);
$parser->match(TokenType::T_IDENTIFIER);
$this->intervalExpression = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(TokenType::T_IDENTIFIER);
/** @var Lexer $lexer */
$lexer = $parser->getLexer();
$this->unit = $lexer->token['value'];
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
$parser->match(TokenType::T_CLOSE_PARENTHESIS);
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)

View File

@@ -1,7 +1,7 @@
Implementing ArrayAccess for Domain Objects
===========================================
.. sectionauthor:: Roman Borschel (roman@code-factory.org)
.. sectionauthor:: Roman Borschel <roman@code-factory.org>
This recipe will show you how to implement ArrayAccess for your
domain objects in order to allow more uniform access, for example

View File

@@ -1,75 +0,0 @@
Implementing the Notify ChangeTracking Policy
=============================================
.. sectionauthor:: Roman Borschel (roman@code-factory.org)
The NOTIFY change-tracking policy is the most effective
change-tracking policy provided by Doctrine but it requires some
boilerplate code. This recipe will show you how this boilerplate
code should look like. We will implement it on a
`Layer Supertype <https://martinfowler.com/eaaCatalog/layerSupertype.html>`_
for all our domain objects.
.. note::
The notify change tracking policy is deprecated and will be removed in ORM 3.0.
(`Details <https://github.com/doctrine/orm/issues/8383>`_)
Implementing NotifyPropertyChanged
----------------------------------
The NOTIFY policy is based on the assumption that the entities
notify interested listeners of changes to their properties. For
that purpose, a class that wants to use this policy needs to
implement the ``NotifyPropertyChanged`` interface from the
``Doctrine\Common`` namespace.
.. code-block:: php
<?php
use Doctrine\Persistence\NotifyPropertyChanged;
use Doctrine\Persistence\PropertyChangedListener;
abstract class DomainObject implements NotifyPropertyChanged
{
private $listeners = array();
public function addPropertyChangedListener(PropertyChangedListener $listener) {
$this->listeners[] = $listener;
}
/** Notifies listeners of a change. */
protected function onPropertyChanged($propName, $oldValue, $newValue) {
if ($this->listeners) {
foreach ($this->listeners as $listener) {
$listener->propertyChanged($this, $propName, $oldValue, $newValue);
}
}
}
}
Then, in each property setter of concrete, derived domain classes,
you need to invoke onPropertyChanged as follows to notify
listeners:
.. code-block:: php
<?php
// Mapping not shown, either in attributes, annotations, xml or yaml as usual
class MyEntity extends DomainObject
{
private $data;
// ... other fields as usual
public function setData($data) {
if ($data != $this->data) { // check: is it actually modified?
$this->onPropertyChanged('data', $this->data, $data);
$this->data = $data;
}
}
}
The check whether the new value is different from the old one is
not mandatory but recommended. That way you can avoid unnecessary
updates and also have full control over when you consider a
property changed.

View File

@@ -43,13 +43,13 @@ entities:
.. code-block:: php
<?php
/** @Entity */
#[Entity]
class Article
{
const STATUS_VISIBLE = 'visible';
const STATUS_INVISIBLE = 'invisible';
/** @Column(type="string") */
#[Column(type: "string")]
private $status;
public function setStatus($status)
@@ -67,10 +67,10 @@ the **columnDefinition** attribute.
.. code-block:: php
<?php
/** @Entity */
#[Entity]
class Article
{
/** @Column(type="string", columnDefinition="ENUM('visible', 'invisible')") */
#[Column(type: "string", columnDefinition: "ENUM('visible', 'invisible')")]
private $status;
}
@@ -131,10 +131,10 @@ Then in your entity you can just use this type:
.. code-block:: php
<?php
/** @Entity */
#[Entity]
class Article
{
/** @Column(type="enumvisibility") */
#[Column(type: "enumvisibility")]
private $status;
}
@@ -196,4 +196,3 @@ With this base class you can define an enum as easily as:
protected $name = 'enumvisibility';
protected $values = array('visible', 'invisible');
}

View File

@@ -47,10 +47,8 @@ A Customer entity
use Acme\CustomerModule\Entity\Customer as BaseCustomer;
use Acme\InvoiceModule\Model\InvoiceSubjectInterface;
/**
* @ORM\Entity
* @ORM\Table(name="customer")
*/
#[ORM\Entity]
#[ORM\Table(name: 'customer')]
class Customer extends BaseCustomer implements InvoiceSubjectInterface
{
// In our example, any methods defined in the InvoiceSubjectInterface
@@ -69,19 +67,12 @@ An Invoice entity
use Doctrine\ORM\Mapping AS ORM;
use Acme\InvoiceModule\Model\InvoiceSubjectInterface;
/**
* Represents an Invoice.
*
* @ORM\Entity
* @ORM\Table(name="invoice")
*/
#[ORM\Entity]
#[ORM\Table(name: 'invoice')]
class Invoice
{
/**
* @ORM\ManyToOne(targetEntity="Acme\InvoiceModule\Model\InvoiceSubjectInterface")
* @var InvoiceSubjectInterface
*/
protected $subject;
#[ORM\ManyToOne(targetEntity: InvoiceSubjectInterface::class)]
protected InvoiceSubjectInterface $subject;
}
An InvoiceSubjectInterface
@@ -127,7 +118,7 @@ the targetEntity resolution will occur reliably:
// Add the ResolveTargetEntityListener
$evm->addEventListener(Doctrine\ORM\Events::loadClassMetadata, $rtel);
$connection = \Doctrine\DBAL\DriverManager::createConnection($connectionOptions, $config, $evm);
$connection = \Doctrine\DBAL\DriverManager::getConnection($connectionOptions, $config, $evm);
$em = new \Doctrine\ORM\EntityManager($connection, $config, $evm);
Final Thoughts

View File

@@ -155,7 +155,7 @@ As you can see, we have a method "setBlockEntity" which ties a potential strateg
* that is used for this blockitem. (This string (!) value will be persisted by Doctrine ORM)
*
* This is a doctrine field, so make sure that you use a
#[Column] attribute or setup your yaml or xml files correctly
#[Column] attribute or setup your xml files correctly
* @var string
*/
protected $strategyClassName;

View File

@@ -11,7 +11,7 @@ What we offer are hooks to execute any kind of validation.
.. note::
You don't need to validate your entities in the lifecycle
events. Its only one of many options. Of course you can also
events. It is only one of many options. Of course you can also
perform validations in value setters or any other method of your
entities that are used in your code.
@@ -58,6 +58,10 @@ First Attributes:
.. code-block:: php
<?php
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\HasLifecycleCallbacks;
use Doctrine\ORM\Mapping\PrePersist;
use Doctrine\ORM\Mapping\PreUpdate;
#[Entity]
#[HasLifecycleCallbacks]
@@ -67,23 +71,6 @@ First Attributes:
public function assertCustomerAllowedBuying() {}
}
As Annotations:
.. code-block:: php
<?php
/**
* @Entity
* @HasLifecycleCallbacks
*/
class Order
{
/**
* @PrePersist @PreUpdate
*/
public function assertCustomerAllowedBuying() {}
}
In XML Mappings:
.. code-block:: xml

View File

@@ -162,15 +162,13 @@ requiring timezoned datetimes:
<?php
namespace Shipping;
/**
* @Entity
*/
#[Entity]
class Event
{
/** @Column(type="datetime") */
#[Column(type: 'datetime')]
private $created;
/** @Column(type="string") */
#[Column(type: 'string')]
private $timezone;
/**

View File

@@ -1,4 +1,4 @@
Welcome to Doctrine 2 ORM's documentation!
Welcome to Doctrine ORM's documentation!
==========================================
The Doctrine documentation is comprised of tutorials, a reference section and
@@ -18,8 +18,8 @@ Doctrine ORM don't panic. You can get help from different sources:
- Report a bug on `GitHub <https://github.com/doctrine/orm/issues>`_.
- On `StackOverflow <https://stackoverflow.com/questions/tagged/doctrine-orm>`_
If you need more structure over the different topics you can browse the :doc:`table
of contents <toc>`.
If you need more structure over the different topics you can browse the table
of contents.
Getting Started
---------------
@@ -34,32 +34,30 @@ Mapping Objects onto a Database
-------------------------------
* **Mapping**:
:doc:`Objects <reference/basic-mapping>` |
:doc:`Associations <reference/association-mapping>` |
:doc:`Objects <reference/basic-mapping>` \|
:doc:`Associations <reference/association-mapping>` \|
:doc:`Inheritance <reference/inheritance-mapping>`
* **Drivers**:
:doc:`Docblock Annotations <reference/annotations-reference>` |
:doc:`Attributes <reference/attributes-reference>` |
:doc:`XML <reference/xml-mapping>` |
:doc:`YAML <reference/yaml-mapping>` |
:doc:`Attributes <reference/attributes-reference>` \|
:doc:`XML <reference/xml-mapping>` \|
:doc:`PHP <reference/php-mapping>`
Working with Objects
--------------------
* **Basic Reference**:
:doc:`Entities <reference/working-with-objects>` |
:doc:`Associations <reference/working-with-associations>` |
:doc:`Entities <reference/working-with-objects>` \|
:doc:`Associations <reference/working-with-associations>` \|
:doc:`Events <reference/events>`
* **Query Reference**:
:doc:`DQL <reference/dql-doctrine-query-language>` |
:doc:`QueryBuilder <reference/query-builder>` |
:doc:`DQL <reference/dql-doctrine-query-language>` \|
:doc:`QueryBuilder <reference/query-builder>` \|
:doc:`Native SQL <reference/native-sql>`
* **Internals**:
:doc:`Internals explained <reference/unitofwork>` |
:doc:`Internals explained <reference/unitofwork>` \|
:doc:`Associations <reference/unitofwork-associations>`
Advanced Topics
@@ -75,7 +73,6 @@ Advanced Topics
* :doc:`TypedFieldMapper <reference/typedfieldmapper>`
* :doc:`Improving Performance <reference/improving-performance>`
* :doc:`Caching <reference/caching>`
* :doc:`Partial Objects <reference/partial-objects>`
* :doc:`Change Tracking Policies <reference/change-tracking-policies>`
* :doc:`Best Practices <reference/best-practices>`
* :doc:`Metadata Drivers <reference/metadata-drivers>`
@@ -96,26 +93,25 @@ Tutorials
Changelogs
----------
* `Upgrade <https://github.com/doctrine/doctrine2/blob/master/UPGRADE.md>`_
* `Upgrade <https://github.com/doctrine/orm/blob/HEAD/UPGRADE.md>`_
Cookbook
--------
* **Patterns**:
:doc:`Aggregate Fields <cookbook/aggregate-fields>` |
:doc:`Decorator Pattern <cookbook/decorator-pattern>` |
:doc:`Aggregate Fields <cookbook/aggregate-fields>` \|
:doc:`Decorator Pattern <cookbook/decorator-pattern>` \|
:doc:`Strategy Pattern <cookbook/strategy-cookbook-introduction>`
* **DQL Extension Points**:
:doc:`DQL Custom Walkers <cookbook/dql-custom-walkers>` |
:doc:`DQL Custom Walkers <cookbook/dql-custom-walkers>` \|
:doc:`DQL User-Defined-Functions <cookbook/dql-user-defined-functions>`
* **Implementation**:
:doc:`Array Access <cookbook/implementing-arrayaccess-for-domain-objects>` |
:doc:`Notify ChangeTracking Example <cookbook/implementing-the-notify-changetracking-policy>` |
:doc:`Working with DateTime <cookbook/working-with-datetime>` |
:doc:`Validation <cookbook/validation-of-entities>` |
:doc:`Entities in the Session <cookbook/entities-in-session>` |
:doc:`Array Access <cookbook/implementing-arrayaccess-for-domain-objects>` \|
:doc:`Working with DateTime <cookbook/working-with-datetime>` \|
:doc:`Validation <cookbook/validation-of-entities>` \|
:doc:`Entities in the Session <cookbook/entities-in-session>` \|
:doc:`Keeping your Modules independent <cookbook/resolve-target-entity-listener>`
* **Hidden Gems**
@@ -124,5 +120,3 @@ Cookbook
* **Custom Datatypes**
:doc:`MySQL Enums <cookbook/mysql-enums>`
:doc:`Advanced Field Value Conversion <cookbook/advanced-field-value-conversion-using-custom-mapping-types>`
.. include:: toc.rst

View File

@@ -29,7 +29,7 @@ steps of configuration.
$config = new Configuration;
$config->setMetadataCache($metadataCache);
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities']);
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities'], true);
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCache($queryCache);
$config->setProxyDir('/path/to/myproject/lib/MyProject/Proxies');
@@ -111,21 +111,16 @@ Gets or sets the metadata driver implementation that is used by
Doctrine to acquire the object-relational metadata for your
classes.
There are currently 5 available implementations:
There are currently 3 available implementations:
- ``Doctrine\ORM\Mapping\Driver\AttributeDriver``
- ``Doctrine\ORM\Mapping\Driver\XmlDriver``
- ``Doctrine\ORM\Mapping\Driver\DriverChain``
- ``Doctrine\ORM\Mapping\Driver\AnnotationDriver`` (deprecated and will
be removed in ``doctrine/orm`` 3.0)
- ``Doctrine\ORM\Mapping\Driver\YamlDriver`` (deprecated and will be
removed in ``doctrine/orm`` 3.0)
Throughout the most part of this manual the AttributeDriver is
used in the examples. For information on the usage of the
AnnotationDriver, XmlDriver or YamlDriver please refer to the dedicated
chapters ``Annotation Reference``, ``XML Mapping`` and ``YAML Mapping``.
XmlDriver please refer to the dedicated chapter ``XML Mapping``.
The attribute driver can be injected in the ``Doctrine\ORM\Configuration``:
@@ -134,7 +129,7 @@ The attribute driver can be injected in the ``Doctrine\ORM\Configuration``:
<?php
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities']);
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities'], true);
$config->setMetadataDriverImpl($driverImpl);
The path information to the entities is required for the attribute
@@ -155,9 +150,9 @@ Metadata Cache (***RECOMMENDED***)
Gets or sets the cache adapter to use for caching metadata
information, that is, all the information you supply via attributes,
annotations, xml or yaml, so that they do not need to be parsed and
loaded from scratch on every single request which is a waste of
resources. The cache implementation must implement the PSR-6
xml, so that they do not need to be parsed and loaded from scratch on
every single request which is a waste of resources. The cache
implementation must implement the PSR-6
``Psr\Cache\CacheItemPoolInterface`` interface.
Usage of a metadata cache is highly recommended.
@@ -311,10 +306,12 @@ Reference Proxies
The method ``EntityManager#getReference($entityName, $identifier)``
lets you obtain a reference to an entity for which the identifier
is known, without loading that entity from the database. This is
useful, for example, as a performance enhancement, when you want to
establish an association to an entity for which you have the
identifier. You could simply do this:
is known, without necessarily loading that entity from the database.
This is useful, for example, as a performance enhancement, when you
want to establish an association to an entity for which you have the
identifier.
Consider the following example:
.. code-block:: php
@@ -324,15 +321,33 @@ identifier. You could simply do this:
$item = $em->getReference('MyProject\Model\Item', $itemId);
$cart->addItem($item);
Here, we added an Item to a Cart without loading the Item from the
database. If you access any state that isn't yet available in the
Item instance, the proxying mechanism would fully initialize the
object's state transparently from the database. Here
$item is actually an instance of the proxy class that was generated
for the Item class but your code does not need to care. In fact it
**should not care**. Proxy objects should be transparent to your
Whether the object being returned from ``EntityManager#getReference()``
is a proxy or a direct instance of the entity class may depend on different
factors, including whether the entity has already been loaded into memory
or entity inheritance being used. But your code does not need to care
and in fact it **should not care**. Proxy objects should be transparent to your
code.
When using the ``EntityManager#getReference()`` method, you need to be aware
of a few peculiarities.
At the best case, the ORM can avoid querying the database at all. But, that
also means that this method will not throw an exception when an invalid value
for the ``$identifier`` parameter is passed. ``$identifier`` values are
not checked and there is no guarantee that the requested entity instance even
exists the method will still return a proxy object.
Its only when the proxy has to be fully initialized or associations cannot
be written to the database that invalid ``$identifier`` values may lead to
exceptions.
The ``EntityManager#getReference()`` is mostly useful when you only
need a reference to some entity to make an association, like in the example
above. In that case, it can save you from loading data from the database
that you don't need. But remember as soon as you read any property values
besides those making up the ID, a database request will be made to initialize
all fields.
Association proxies
~~~~~~~~~~~~~~~~~~~
@@ -388,7 +403,7 @@ means that you have to register a special autoloader for these classes:
.. code-block:: php
<?php
use Doctrine\Common\Proxy\Autoloader;
use Doctrine\ORM\Proxy\Autoloader;
$proxyDir = "/path/to/proxies";
$proxyNamespace = "MyProxies";
@@ -405,7 +420,7 @@ Multiple Metadata Sources
When using different components using Doctrine ORM you may end up
with them using two different metadata drivers, for example XML and
YAML. You can use the MappingDriverChain Metadata implementations to
PHP. You can use the MappingDriverChain Metadata implementations to
aggregate these drivers based on namespaces:
.. code-block:: php
@@ -415,7 +430,7 @@ aggregate these drivers based on namespaces:
$chain = new MappingDriverChain();
$chain->addDriver($xmlDriver, 'Doctrine\Tests\Models\Company');
$chain->addDriver($yamlDriver, 'Doctrine\Tests\ORM\Mapping');
$chain->addDriver($phpDriver, 'Doctrine\Tests\ORM\Mapping');
Based on the namespace of the entity the loading of entities is
delegated to the appropriate driver. The chain semantics come from

File diff suppressed because it is too large Load Diff

View File

@@ -18,34 +18,40 @@ well.
Requirements
------------
Doctrine ORM requires a minimum of PHP 7.1. For greatly improved
Doctrine ORM requires a minimum of PHP 8.1. For greatly improved
performance it is also recommended that you use APC with PHP.
Doctrine ORM Packages
-------------------
Doctrine ORM is divided into three main packages.
Doctrine ORM is divided into four main packages.
- Common
- DBAL (includes Common)
- ORM (includes DBAL+Common)
- `Collections <https://www.doctrine-project.org/projects/doctrine-collections/en/stable/index.html>`_
- `Event Manager <https://www.doctrine-project.org/projects/doctrine-event-manager/en/stable/index.html>`_
- `Persistence <https://www.doctrine-project.org/projects/doctrine-persistence/en/stable/index.html>`_
- `DBAL <https://www.doctrine-project.org/projects/doctrine-dbal/en/stable/index.html>`_
- ORM (depends on DBAL+Persistence+Collections)
This manual mainly covers the ORM package, sometimes touching parts
of the underlying DBAL and Common packages. The Doctrine code base
of the underlying DBAL and Persistence packages. The Doctrine code base
is split in to these packages for a few reasons and they are to...
- ...make things more maintainable and decoupled
- ...allow you to use the code in Doctrine Common without the ORM
or DBAL
- ...allow you to use the code in Doctrine Persistence and Collections
without the ORM or DBAL
- ...allow you to use the DBAL without the ORM
The Common Package
~~~~~~~~~~~~~~~~~~
Collection, Event Manager and Persistence
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Common package contains highly reusable components that have no
dependencies beyond the package itself (and PHP, of course). The
root namespace of the Common package is ``Doctrine\Common``.
The Collection, Event Manager and Persistence packages contain highly
reusable components that have no dependencies beyond the packages
themselves (and PHP, of course). The root namespace of the Persistence
package is ``Doctrine\Persistence``. The root namespace of the
Collection package is ``Doctrine\Common\Collections``, for historical
reasons. The root namespace of the Event Manager package is just
``Doctrine\Common``, also for historical reasons.
The DBAL Package
~~~~~~~~~~~~~~~~
@@ -102,7 +108,7 @@ persistent entity state and mapping information for its subclasses,
but which is not itself an entity.
Mapped superclasses are explained in greater detail in the chapter
on :doc:`inheritance mapping <reference/inheritance-mapping>`.
on :doc:`inheritance mapping </reference/inheritance-mapping>`.
Transient Classes
~~~~~~~~~~~~~~~~~
@@ -199,5 +205,3 @@ typical implementation of the
to keep track of all the things that need to be done the next time
``flush`` is invoked. You usually do not directly interact with a
``UnitOfWork`` but with the ``EntityManager`` instead.

View File

@@ -56,27 +56,6 @@ A many-to-one association is the most common association between objects. Exampl
// ...
}
.. code-block:: annotation
<?php
/** @Entity */
class User
{
// ...
/**
* @ManyToOne(targetEntity="Address")
* @JoinColumn(name="address_id", referencedColumnName="id")
*/
private Address|null $address = null;
}
/** @Entity */
class Address
{
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -87,18 +66,6 @@ A many-to-one association is the most common association between objects. Exampl
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToOne:
address:
targetEntity: Address
joinColumn:
name: address_id
referencedColumnName: id
.. note::
The above ``#[JoinColumn]`` is optional as it would default
@@ -154,30 +121,6 @@ references one ``Shipment`` entity.
// ...
}
.. code-block:: annotation
<?php
/** @Entity */
class Product
{
// ...
/**
* One Product has One Shipment.
* @OneToOne(targetEntity="Shipment")
* @JoinColumn(name="shipment_id", referencedColumnName="id")
*/
private Shipment|null $shipment = null;
// ...
}
/** @Entity */
class Shipment
{
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -188,17 +131,6 @@ references one ``Shipment`` entity.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
joinColumn:
name: shipment_id
referencedColumnName: id
Note that the ``#[JoinColumn]`` is not really necessary in this example,
as the defaults would be the same.
@@ -259,38 +191,6 @@ object.
// ...
}
.. code-block:: annotation
<?php
/** @Entity */
class Customer
{
// ...
/**
* One Customer has One Cart.
* @OneToOne(targetEntity="Cart", mappedBy="customer")
*/
private Cart|null $cart = null;
// ...
}
/** @Entity */
class Cart
{
// ...
/**
* One Cart has One Customer.
* @OneToOne(targetEntity="Customer", inversedBy="cart")
* @JoinColumn(name="customer_id", referencedColumnName="id")
*/
private Customer|null $customer = null;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -304,22 +204,6 @@ object.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Customer:
oneToOne:
cart:
targetEntity: Cart
mappedBy: customer
Cart:
oneToOne:
customer:
targetEntity: Customer
inversedBy: cart
joinColumn:
name: customer_id
referencedColumnName: id
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -428,41 +312,6 @@ bidirectional many-to-one.
// ...
}
.. code-block:: annotation
<?php
use Doctrine\Common\Collections\ArrayCollection;
/** @Entity */
class Product
{
// ...
/**
* One product has many features. This is the inverse side.
* @var Collection<int, Feature>
* @OneToMany(targetEntity="Feature", mappedBy="product")
*/
private Collection $features;
// ...
public function __construct() {
$this->features = new ArrayCollection();
}
}
/** @Entity */
class Feature
{
// ...
/**
* Many features have one product. This is the owning side.
* @ManyToOne(targetEntity="Product", inversedBy="features")
* @JoinColumn(name="product_id", referencedColumnName="id")
*/
private Product|null $product = null;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -476,24 +325,6 @@ bidirectional many-to-one.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToMany:
features:
targetEntity: Feature
mappedBy: product
Feature:
type: entity
manyToOne:
product:
targetEntity: Product
inversedBy: features
joinColumn:
name: product_id
referencedColumnName: id
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -556,39 +387,6 @@ The following example sets up such a unidirectional one-to-many association:
// ...
}
.. code-block:: annotation
<?php
/** @Entity */
class User
{
// ...
/**
* Many Users have Many Phonenumbers.
* @ManyToMany(targetEntity="Phonenumber")
* @JoinTable(name="users_phonenumbers",
* joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="phonenumber_id", referencedColumnName="id", unique=true)}
* )
* @var Collection<int, Phonenumber>
*/
private Collection $phonenumbers;
public function __construct()
{
$this->phonenumbers = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
/** @Entity */
class Phonenumber
{
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -606,24 +404,6 @@ The following example sets up such a unidirectional one-to-many association:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
phonenumbers:
targetEntity: Phonenumber
joinTable:
name: users_phonenumbers
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
phonenumber_id:
referencedColumnName: id
unique: true
Generates the following MySQL Schema:
.. code-block:: sql
@@ -684,33 +464,6 @@ database perspective is known as an adjacency list approach.
}
}
.. code-block:: annotation
<?php
/** @Entity */
class Category
{
// ...
/**
* One Category has Many Categories.
* @OneToMany(targetEntity="Category", mappedBy="parent")
* @var Collection<int, Category>
*/
private Collection $children;
/**
* Many Categories have One Category.
* @ManyToOne(targetEntity="Category", inversedBy="children")
* @JoinColumn(name="parent_id", referencedColumnName="id")
*/
private Category|null $parent = null;
// ...
public function __construct() {
$this->children = new \Doctrine\Common\Collections\ArrayCollection();
}
}
.. code-block:: xml
<doctrine-mapping>
@@ -720,19 +473,6 @@ database perspective is known as an adjacency list approach.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Category:
type: entity
oneToMany:
children:
targetEntity: Category
mappedBy: parent
manyToOne:
parent:
targetEntity: Category
inversedBy: children
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -787,38 +527,6 @@ entities:
// ...
}
.. code-block:: annotation
<?php
/** @Entity */
class User
{
// ...
/**
* Many Users have Many Groups.
* @ManyToMany(targetEntity="Group")
* @JoinTable(name="users_groups",
* joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id")}
* )
* @var Collection<int, Group>
*/
private Collection $groups;
// ...
public function __construct() {
$this->groups = new \Doctrine\Common\Collections\ArrayCollection();
}
}
/** @Entity */
class Group
{
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -836,22 +544,6 @@ entities:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
targetEntity: Group
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
Generated MySQL Schema:
.. code-block:: sql
@@ -881,6 +573,15 @@ Generated MySQL Schema:
replaced by one-to-many/many-to-one associations between the 3
participating classes.
.. note::
For many-to-many associations, the ORM takes care of managing rows
in the join table connecting both sides. Due to the way it deals
with entity removals, database-level constraints may not work the
way one might intuitively assume. Thus, be sure not to miss the section
on :ref:`join table management <remove_object_many_to_many_join_tables>`.
Many-To-Many, Bidirectional
---------------------------
@@ -930,47 +631,6 @@ one is bidirectional.
// ...
}
.. code-block:: annotation
<?php
/** @Entity */
class User
{
// ...
/**
* Many Users have Many Groups.
* @ManyToMany(targetEntity="Group", inversedBy="users")
* @JoinTable(name="users_groups")
* @var Collection<int, Group>
*/
private Collection $groups;
public function __construct() {
$this->groups = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
/** @Entity */
class Group
{
// ...
/**
* Many Groups have Many Users.
* @ManyToMany(targetEntity="User", mappedBy="groups")
* @var Collection<int, User>
*/
private Collection $users;
public function __construct() {
$this->users = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -992,33 +652,18 @@ one is bidirectional.
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
targetEntity: Group
inversedBy: users
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
Group:
type: entity
manyToMany:
users:
targetEntity: User
mappedBy: groups
The MySQL schema is exactly the same as for the Many-To-Many
uni-directional case above.
.. note::
For many-to-many associations, the ORM takes care of managing rows
in the join table connecting both sides. Due to the way it deals
with entity removals, database-level constraints may not work the
way one might intuitively assume. Thus, be sure not to miss the section
on :ref:`join table management <remove_object_many_to_many_join_tables>`.
Owning and Inverse Side on a ManyToMany Association
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1154,12 +799,6 @@ As an example, consider this mapping:
#[OneToOne(targetEntity: Shipment::class)]
private Shipment|null $shipment = null;
.. code-block:: annotation
<?php
/** @OneToOne(targetEntity="Shipment") */
private Shipment|null $shipment = null;
.. code-block:: xml
<doctrine-mapping>
@@ -1168,14 +807,6 @@ As an example, consider this mapping:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
This is essentially the same as the following, more verbose,
mapping:
@@ -1189,16 +820,6 @@ mapping:
#[JoinColumn(name: 'shipment_id', referencedColumnName: 'id')]
private Shipment|null $shipment = null;
.. code-block:: annotation
<?php
/**
* One Product has One Shipment.
* @OneToOne(targetEntity="Shipment")
* @JoinColumn(name="shipment_id", referencedColumnName="id")
*/
private Shipment|null $shipment = null;
.. code-block:: xml
<doctrine-mapping>
@@ -1209,17 +830,6 @@ mapping:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
joinColumn:
name: shipment_id
referencedColumnName: id
The @JoinTable definition used for many-to-many mappings has
similar defaults. As an example, consider this mapping:
@@ -1237,20 +847,6 @@ similar defaults. As an example, consider this mapping:
// ...
}
.. code-block:: annotation
<?php
class User
{
// ...
/**
* @ManyToMany(targetEntity="Group")
* @var Collection<int, Group>
*/
private Collection $groups;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -1259,14 +855,6 @@ similar defaults. As an example, consider this mapping:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
targetEntity: Group
This is essentially the same as the following, more verbose, mapping:
.. configuration-block::
@@ -1282,32 +870,13 @@ This is essentially the same as the following, more verbose, mapping:
* @var Collection<int, Group>
*/
#[JoinTable(name: 'User_Group')]
#[JoinColumn(name: 'User_id', referencedColumnName: 'id')]
#[InverseJoinColumn(name: 'Group_id', referencedColumnName: 'id')]
#[JoinColumn(name: 'user_id', referencedColumnName: 'id')]
#[InverseJoinColumn(name: 'group_id', referencedColumnName: 'id')]
#[ManyToMany(targetEntity: Group::class)]
private Collection $groups;
// ...
}
.. code-block:: annotation
<?php
class User
{
// ...
/**
* Many Users have Many Groups.
* @ManyToMany(targetEntity="Group")
* @JoinTable(name="User_Group",
* joinColumns={@JoinColumn(name="User_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="Group_id", referencedColumnName="id")}
* )
* @var Collection<int, Group>
*/
private Collection $groups;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -1315,32 +884,16 @@ This is essentially the same as the following, more verbose, mapping:
<many-to-many field="groups" target-entity="Group">
<join-table name="User_Group">
<join-columns>
<join-column id="User_id" referenced-column-name="id" />
<join-column id="user_id" referenced-column-name="id" />
</join-columns>
<inverse-join-columns>
<join-column id="Group_id" referenced-column-name="id" />
<join-column id="group_id" referenced-column-name="id" />
</inverse-join-columns>
</join-table>
</many-to-many>
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
targetEntity: Group
joinTable:
name: User_Group
joinColumns:
User_id:
referencedColumnName: id
inverseJoinColumns:
Group_id:
referencedColumnName: id
In that case, the name of the join table defaults to a combination
of the simple, unqualified class names of the participating
classes, separated by an underscore character. The names of the
@@ -1361,12 +914,6 @@ attribute on ``JoinColumn`` will be inherited from PHP type. So that:
#[OneToOne]
private Shipment $shipment;
.. code-block:: annotation
<?php
/** @OneToOne */
private Shipment $shipment;
.. code-block:: xml
<doctrine-mapping>
@@ -1375,13 +922,6 @@ attribute on ``JoinColumn`` will be inherited from PHP type. So that:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToOne:
shipment: ~
Is essentially the same as following:
.. configuration-block::
@@ -1414,18 +954,6 @@ Is essentially the same as following:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
joinColumn:
name: shipment_id
referencedColumnName: id
nullable: false
If you accept these defaults, you can reduce the mapping code to a
minimum.

View File

@@ -4,8 +4,9 @@ Attributes Reference
PHP 8 adds native support for metadata with its "Attributes" feature.
Doctrine ORM provides support for mapping metadata using PHP attributes as of version 2.9.
The attributes metadata support is closely modelled after the already existing
annotation metadata supported since the first version 2.0.
The attributes metadata support is closely modelled after the already
existing and now removed annotation metadata supported since the first
version 2.0.
Index
-----
@@ -310,7 +311,6 @@ Example:
Entity,
ChangeTrackingPolicy("DEFERRED_IMPLICIT"),
ChangeTrackingPolicy("DEFERRED_EXPLICIT"),
ChangeTrackingPolicy("NOTIFY")
]
class User {}
@@ -368,6 +368,7 @@ Optional parameters:
- **length**: By default this is 255.
- **columnDefinition**: By default this is null the definition according to the type will be used. This option allows to override it.
- **enumType**: By default this is `null`. Allows to map discriminatorColumn value to PHP enum
- **options**: See "options" attribute on :ref:`#[Column] <attrref_column>`.
.. _attrref_discriminatormap:
@@ -484,9 +485,8 @@ used as default.
Optional parameters:
- **strategy**: Set the name of the identifier generation strategy.
Valid values are ``AUTO``, ``SEQUENCE``, ``IDENTITY``, ``UUID``
(deprecated), ``CUSTOM`` and ``NONE``.
If not specified, the default value is ``AUTO``.
Valid values are ``AUTO``, ``SEQUENCE``, ``IDENTITY``, ``CUSTOM`` and
``NONE``. If not specified, the default value is ``AUTO``.
Example:
@@ -539,13 +539,13 @@ has meaning in the ``SchemaTool`` schema generation context.
Required parameters:
- **name**: Name of the Index
- **fields**: Array of fields. Exactly one of **fields, columns** is required.
- **columns**: Array of columns. Exactly one of **fields, columns** is required.
Optional parameters:
- **name**: Name of the Index. If not provided, a generated name will be assigned.
- **options**: Array of platform specific options:
- ``where``: SQL WHERE condition to be used for partial indexes. It will
@@ -711,10 +711,6 @@ details of the database join table. If you do not specify
``#[JoinTable]`` on these relations reasonable mapping defaults apply
using the affected table and the column names.
A notable difference to the annotation metadata support, ``#[JoinColumn]``
and ``#[InverseJoinColumn]`` can be specified at the property level and are not
nested within the ``#[JoinTable]`` attribute.
Required attribute:
- **name**: Database name of the join-table
@@ -930,7 +926,7 @@ Example:
#[OneToMany(
targetEntity: "Phonenumber",
mappedBy: "user",
cascade: ["persist", "remove", "merge"],
cascade: ["persist", "remove"],
orphanRemoval: true)
]
public $phonenumbers;
@@ -1103,11 +1099,12 @@ context.
Required parameters:
- **name**: Name of the Index
- **columns**: Array of columns.
- **fields**: Array of fields (the names of the properties, used in the entity class).
- **columns**: Array of columns (the names of the columns, used in the schema).
Optional parameters:
- **name**: Name of the Index. If not provided, a generated name will be assigned.
- **options**: Array of platform specific options:
- ``where``: SQL WHERE condition to be used for partial indexes. It will

View File

@@ -47,18 +47,14 @@ mapping metadata:
- :doc:`Attributes <attributes-reference>`
- :doc:`XML <xml-mapping>`
- :doc:`PHP code <php-mapping>`
- :doc:`Docblock Annotations <annotations-reference>` (deprecated and
will be removed in ``doctrine/orm`` 3.0)
- :doc:`YAML <yaml-mapping>` (deprecated and will be removed in ``doctrine/orm`` 3.0.)
This manual will usually show mapping metadata via attributes, though
many examples also show the equivalent configuration in annotations,
YAML and XML.
many examples also show the equivalent configuration in XML.
.. note::
All metadata drivers perform equally. Once the metadata of a class has been
read from the source (attributes, annotations, XML, etc.) it is stored in an instance
read from the source (attributes, XML, etc.) it is stored in an instance
of the ``Doctrine\ORM\Mapping\ClassMetadata`` class which are
stored in the metadata cache. If you're not using a metadata cache (not
recommended!) then the XML driver is the fastest.
@@ -78,17 +74,6 @@ Marking our ``Message`` class as an entity for Doctrine is straightforward:
// ...
}
.. code-block:: annotation
<?php
use Doctrine\ORM\Mapping\Entity;
/** @Entity */
class Message
{
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -97,12 +82,6 @@ Marking our ``Message`` class as an entity for Doctrine is straightforward:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
# ...
With no additional information, Doctrine expects the entity to be saved
into a table with the same name as the class in our case ``Message``.
You can change this by configuring information about the table:
@@ -122,21 +101,6 @@ You can change this by configuring information about the table:
// ...
}
.. code-block:: annotation
<?php
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Table;
/**
* @Entity
* @Table(name="message")
*/
class Message
{
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -145,13 +109,6 @@ You can change this by configuring information about the table:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
table: message
# ...
Now the class ``Message`` will be saved and fetched from the table ``message``.
Property Mapping
@@ -183,23 +140,6 @@ specified, ``string`` is used as the default.
private $postedAt;
}
.. code-block:: annotation
<?php
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Column;
/** @Entity */
class Message
{
/** @Column(type="integer") */
private $id;
/** @Column(length=140) */
private $text;
/** @Column(type="datetime", name="posted_at") */
private $postedAt;
}
.. code-block:: xml
<doctrine-mapping>
@@ -210,19 +150,6 @@ specified, ``string`` is used as the default.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
fields:
id:
type: integer
text:
length: 140
postedAt:
type: datetime
column: posted_at
When we don't explicitly specify a column name via the ``name`` option, Doctrine
assumes the field name is also the column name. So in this example:
@@ -301,50 +228,12 @@ and a custom ``Doctrine\ORM\Mapping\TypedFieldMapper`` implementation.
Doctrine Mapping Types
----------------------
The ``type`` option used in the ``@Column`` accepts any of the existing
Doctrine types or even your own custom types. A Doctrine type defines
The ``type`` option used in the ``@Column`` accepts any of the
`existing Doctrine DBAL types <https://docs.doctrine-project.org/projects/doctrine-dbal/en/stable/reference/types.html#reference>`_
or :doc:`your own custom mapping types
<../cookbook/custom-mapping-types>`. A Doctrine type defines
the conversion between PHP and SQL types, independent from the database vendor
you are using. All Mapping Types that ship with Doctrine are fully portable
between the supported database systems.
As an example, the Doctrine Mapping Type ``string`` defines the
mapping from a PHP string to a SQL VARCHAR (or VARCHAR2 etc.
depending on the RDBMS brand). Here is a quick overview of the
built-in mapping types:
- ``string``: Type that maps a SQL VARCHAR to a PHP string.
- ``integer``: Type that maps a SQL INT to a PHP integer.
- ``smallint``: Type that maps a database SMALLINT to a PHP
integer.
- ``bigint``: Type that maps a database BIGINT to a PHP string.
- ``boolean``: Type that maps a SQL boolean or equivalent (TINYINT) to a PHP boolean.
- ``decimal``: Type that maps a SQL DECIMAL to a PHP string.
- ``date``: Type that maps a SQL DATETIME to a PHP DateTime
object.
- ``time``: Type that maps a SQL TIME to a PHP DateTime object.
- ``datetime``: Type that maps a SQL DATETIME/TIMESTAMP to a PHP
DateTime object.
- ``datetimetz``: Type that maps a SQL DATETIME/TIMESTAMP to a PHP
DateTime object with timezone.
- ``text``: Type that maps a SQL CLOB to a PHP string.
- ``object``: Type that maps a SQL CLOB to a PHP object using
``serialize()`` and ``unserialize()``
- ``array``: Type that maps a SQL CLOB to a PHP array using
``serialize()`` and ``unserialize()``
- ``simple_array``: Type that maps a SQL CLOB to a PHP array using
``implode()`` and ``explode()``, with a comma as delimiter. *IMPORTANT*
Only use this type if you are sure that your values cannot contain a ",".
- ``json_array``: Type that maps a SQL CLOB to a PHP array using
``json_encode()`` and ``json_decode()``
- ``float``: Type that maps a SQL Float (Double Precision) to a
PHP double. *IMPORTANT*: Works only with locale settings that use
decimal points as separator.
- ``guid``: Type that maps a database GUID/UUID to a PHP string. Defaults to
varchar but uses a specific type if the platform supports it.
- ``blob``: Type that maps a SQL BLOB to a PHP resource stream
A cookbook article shows how to define :doc:`your own custom mapping types
<../cookbook/custom-mapping-types>`.
you are using.
.. note::
@@ -385,20 +274,6 @@ the field that serves as the identifier with the ``#[Id]`` attribute.
// ...
}
.. code-block:: annotation
<?php
class Message
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue
*/
private int|null $id = null;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -410,22 +285,27 @@ the field that serves as the identifier with the ``#[Id]`` attribute.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
id:
id:
type: integer
generator:
strategy: AUTO
fields:
# fields here
In most cases using the automatic generator strategy (``#[GeneratedValue]``) is
what you want. It defaults to the identifier generation mechanism your current
database vendor prefers: AUTO_INCREMENT with MySQL, sequences with PostgreSQL
and Oracle and so on.
what you want, but for backwards-compatibility reasons it might not. It
defaults to the identifier generation mechanism your current database
vendor preferred at the time that strategy was introduced:
``AUTO_INCREMENT`` with MySQL, sequences with PostgreSQL and Oracle and
so on.
If you are using `doctrine/dbal` 4, we now recommend using ``IDENTITY``
for PostgreSQL, and ``AUTO`` resolves to it because of that.
You can stick with ``SEQUENCE`` while still using the ``AUTO``
strategy, by configuring what it defaults to.
.. code-block:: php
<?php
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\ORM\Configuration;
$config = new Configuration();
$config->setIdentityGenerationPreferences([
PostgreSQLPlatform::class => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
]);
.. _identifier-generation-strategies:
@@ -442,25 +322,24 @@ Here is the list of possible generation strategies:
- ``AUTO`` (default): Tells Doctrine to pick the strategy that is
preferred by the used database platform. The preferred strategies
are IDENTITY for MySQL, SQLite, MsSQL and SQL Anywhere and SEQUENCE
for Oracle and PostgreSQL. This strategy provides full portability.
- ``SEQUENCE``: Tells Doctrine to use a database sequence for ID
generation. This strategy does currently not provide full
portability. Sequences are supported by Oracle, PostgreSql and
SQL Anywhere.
are ``IDENTITY`` for MySQL, SQLite, MsSQL and SQL Anywhere and, for
historical reasons, ``SEQUENCE`` for Oracle and PostgreSQL. This
strategy provides full portability.
- ``IDENTITY``: Tells Doctrine to use special identity columns in
the database that generate a value on insertion of a row. This
strategy does currently not provide full portability and is
supported by the following platforms: MySQL/SQLite/SQL Anywhere
(AUTO\_INCREMENT), MSSQL (IDENTITY) and PostgreSQL (SERIAL).
- ``UUID`` (deprecated): Tells Doctrine to use the built-in Universally
Unique Identifier generator. This strategy provides full portability.
(``AUTO_INCREMENT``), MSSQL (``IDENTITY``) and PostgreSQL (``SERIAL``).
- ``SEQUENCE``: Tells Doctrine to use a database sequence for ID
generation. This strategy does currently not provide full
portability. Sequences are supported by Oracle, PostgreSql and
SQL Anywhere.
- ``NONE``: Tells Doctrine that the identifiers are assigned (and
thus generated) by your code. The assignment must take place before
a new entity is passed to ``EntityManager#persist``. NONE is the
same as leaving off the ``#[GeneratedValue]`` entirely.
- ``CUSTOM``: With this option, you can use the ``#[CustomIdGenerator]`` attribute.
It will allow you to pass a :doc:`class of your own to generate the identifiers.<_annref_customidgenerator>`
It will allow you to pass a :ref:`class of your own to generate the identifiers. <attrref_customidgenerator>`
Sequence Generator
^^^^^^^^^^^^^^^^^^
@@ -483,20 +362,6 @@ besides specifying the sequence's name:
// ...
}
.. code-block:: annotation
<?php
class Message
{
/**
* @Id
* @GeneratedValue(strategy="SEQUENCE")
* @SequenceGenerator(sequenceName="message_seq", initialValue=1, allocationSize=100)
*/
protected int|null $id = null;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -508,20 +373,6 @@ besides specifying the sequence's name:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
id:
id:
type: integer
generator:
strategy: SEQUENCE
sequenceGenerator:
sequenceName: message_seq
allocationSize: 100
initialValue: 1
The initial value specifies at which value the sequence should
start.

View File

@@ -18,14 +18,20 @@ especially what the strategies presented here provide help with.
.. note::
Having an SQL logger enabled when processing batches can have a serious impact on performance and resource usage.
To avoid that you should remove the corresponding middleware.
To remove all middlewares, you can use this line:
Having an SQL logger enabled when processing batches can have a
serious impact on performance and resource usage.
To avoid that, you should use a PSR logger implementation that can be
disabled at runtime.
For example, with Monolog, you can use ``Logger::pushHandler()``
to push a ``NullHandler`` to the logger instance, and then pop it
when you need to enable logging again.
With DBAL 2, you can disable the SQL logger like below:
.. code-block:: php
<?php
$em->getConnection()->getConfiguration()->setMiddlewares([]); // DBAL 3
$em->getConnection()->getConfiguration()->setSQLLogger(null); // DBAL 2
$em->getConnection()->getConfiguration()->setSQLLogger(null);
Bulk Inserts
------------
@@ -86,7 +92,7 @@ with the batching strategy that was already used for bulk inserts:
<?php
$batchSize = 20;
$i = 1;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
foreach ($q->toIterable() as $user) {
$user->increaseCredit();
@@ -145,7 +151,7 @@ The following example shows how to do this:
<?php
$batchSize = 20;
$i = 1;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
foreach($q->toIterable() as $row) {
$em->remove($row);
@@ -188,6 +194,3 @@ problems using the following approach:
Iterating results is not possible with queries that
fetch-join a collection-valued association. The nature of such SQL
result sets is not suitable for incremental hydration.

View File

@@ -43,7 +43,7 @@ should use events judiciously.
Use cascades judiciously
------------------------
Automatic cascades of the persist/remove/merge/etc. operations are
Automatic cascades of the persist/remove/etc. operations are
very handy but should be used wisely. Do NOT simply add all
cascades to all associations. Think about which cascades actually
do make sense for you for a particular association, given the

View File

@@ -109,7 +109,7 @@ Metadata Cache
~~~~~~~~~~~~~~
Your class metadata can be parsed from a few different sources like
YAML, XML, Attributes, Annotations etc. Instead of parsing this
XML, Attributes, etc. Instead of parsing this
information on each request we should cache it using one of the cache
drivers.

View File

@@ -5,7 +5,7 @@ Change tracking is the process of determining what has changed in
managed entities since the last time they were synchronized with
the database.
Doctrine provides 3 different change tracking policies, each having
Doctrine provides 2 different change tracking policies, each having
its particular advantages and disadvantages. The change tracking
policy can be defined on a per-class basis (or more precisely,
per-hierarchy).
@@ -56,122 +56,3 @@ This policy can be configured as follows:
{
// ...
}
Notify
~~~~~~
.. note::
The notify change tracking policy is deprecated and will be removed in ORM 3.0.
(`Details <https://github.com/doctrine/orm/issues/8383>`_)
This policy is based on the assumption that the entities notify
interested listeners of changes to their properties. For that
purpose, a class that wants to use this policy needs to implement
the ``NotifyPropertyChanged`` interface from the Doctrine
namespace. As a guideline, such an implementation can look as
follows:
.. code-block:: php
<?php
use Doctrine\Persistence\NotifyPropertyChanged,
Doctrine\Persistence\PropertyChangedListener;
#[Entity]
#[ChangeTrackingPolicy('NOTIFY')]
class MyEntity implements NotifyPropertyChanged
{
// ...
private array $_listeners = array();
public function addPropertyChangedListener(PropertyChangedListener $listener): void
{
$this->_listeners[] = $listener;
}
}
Then, in each property setter of this class or derived classes, you
need to notify all the ``PropertyChangedListener`` instances. As an
example we add a convenience method on ``MyEntity`` that shows this
behaviour:
.. code-block:: php
<?php
// ...
class MyEntity implements NotifyPropertyChanged
{
// ...
protected function _onPropertyChanged($propName, $oldValue, $newValue): void
{
if ($this->_listeners) {
foreach ($this->_listeners as $listener) {
$listener->propertyChanged($this, $propName, $oldValue, $newValue);
}
}
}
public function setData($data): void
{
if ($data != $this->data) {
$this->_onPropertyChanged('data', $this->data, $data);
$this->data = $data;
}
}
}
You have to invoke ``_onPropertyChanged`` inside every method that
changes the persistent state of ``MyEntity``.
The check whether the new value is different from the old one is
not mandatory but recommended. That way you also have full control
over when you consider a property changed.
If your entity contains an embeddable, you will need to notify
separately for each property in the embeddable when it changes
for example:
.. code-block:: php
<?php
// ...
class MyEntity implements NotifyPropertyChanged
{
public function setEmbeddable(MyValueObject $embeddable): void
{
if (!$embeddable->equals($this->embeddable)) {
// notice the entityField.embeddableField notation for referencing the property
$this->_onPropertyChanged('embeddable.prop1', $this->embeddable->getProp1(), $embeddable->getProp1());
$this->_onPropertyChanged('embeddable.prop2', $this->embeddable->getProp2(), $embeddable->getProp2());
$this->embeddable = $embeddable;
}
}
}
This would update all the fields of the embeddable, you may wish to
implement a diff method on your embedded object which returns only
the changed fields.
The negative point of this policy is obvious: You need implement an
interface and write some plumbing code. But also note that we tried
hard to keep this notification functionality abstract. Strictly
speaking, it has nothing to do with the persistence layer and the
Doctrine ORM or DBAL. You may find that property notification
events come in handy in many other scenarios as well. As mentioned
earlier, the ``Doctrine\Common`` namespace is not that evil and
consists solely of very small classes and interfaces that have
almost no external dependencies (none to the DBAL and none to the
ORM) and that you can easily take with you should you want to swap
out the persistence layer. This change tracking policy does not
introduce a dependency on the Doctrine DBAL/ORM or the persistence
layer.
The positive point and main advantage of this policy is its
effectiveness. It has the best performance characteristics of the 3
policies with larger units of work and a flush() operation is very
cheap when nothing has changed.

View File

@@ -60,11 +60,6 @@ access point to ORM functionality provided by Doctrine.
$connection = DriverManager::getConnection($dbParams, $config);
$entityManager = new EntityManager($connection, $config);
.. note::
The ``ORMSetup`` class has been introduced with ORM 2.12. It's predecessor ``Setup`` is deprecated and will
be removed in version 3.0.
Or if you prefer XML:
.. code-block:: php
@@ -75,23 +70,6 @@ Or if you prefer XML:
$connection = DriverManager::getConnection($dbParams, $config);
$entityManager = new EntityManager($connection, $config);
Or if you prefer YAML:
.. code-block:: php
<?php
$paths = ['/path/to/yml-mappings'];
$config = ORMSetup::createYAMLMetadataConfiguration($paths, $isDevMode);
$connection = DriverManager::getConnection($dbParams, $config);
$entityManager = new EntityManager($connection, $config);
.. note::
If you want to use yml mapping you should add yaml dependency to your `composer.json`:
::
"symfony/yaml": "*"
Inside the ``ORMSetup`` methods several assumptions are made:
- If ``$isDevMode`` is true caching is done in memory with the ``ArrayAdapter``. Proxy objects are recreated on every request.
@@ -104,7 +82,7 @@ Inside the ``ORMSetup`` methods several assumptions are made:
In order to have ``ORMSetup`` configure the cache automatically, the library ``symfony/cache``
has to be installed as a dependency.
If you want to configure Doctrine in more detail, take a look at the :doc:`Advanced Configuration <reference/advanced-configuration>` section.
If you want to configure Doctrine in more detail, take a look at the :doc:`Advanced Configuration </reference/advanced-configuration>` section.
.. note::

View File

@@ -464,6 +464,11 @@ hierarchies:
$query = $em->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyEmployee');
$query = $em->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1');
$query = $em->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u NOT INSTANCE OF ?1');
$query->setParameter(0, $em->getClassMetadata(CompanyEmployee::class));
.. note::
To use a class as parameter, you have to bind its class metadata:
``$query->setParameter(0, $em->getClassMetadata(CompanyEmployee::class);``.
Get all users visible on a given website that have chosen certain gender:
@@ -518,33 +523,6 @@ when the DQL is switched to an arbitrary join.
- HAVING is applied to the results of a query after
aggregation (GROUP BY)
Partial Object Syntax
^^^^^^^^^^^^^^^^^^^^^
By default when you run a DQL query in Doctrine and select only a
subset of the fields for a given entity, you do not receive objects
back. Instead, you receive only arrays as a flat rectangular result
set, similar to how you would if you were just using SQL directly
and joining some data.
If you want to select partial objects you can use the ``partial``
DQL keyword:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT partial u.{id, username} FROM CmsUser u');
$users = $query->getResult(); // array of partially loaded CmsUser objects
You use the partial syntax when joining as well:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT partial u.{id, username}, partial a.{id, name} FROM CmsUser u JOIN u.articles a');
$users = $query->getResult(); // array of partially loaded CmsUser objects
"NEW" Operator Syntax
^^^^^^^^^^^^^^^^^^^^^
@@ -807,7 +785,7 @@ classes have to implement the base class :
namespace MyProject\Query\AST;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\TokenType;
class MysqlFloor extends FunctionNode
{
@@ -822,12 +800,12 @@ classes have to implement the base class :
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$parser->match(TokenType::T_IDENTIFIER);
$parser->match(TokenType::T_OPEN_PARENTHESIS);
$this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
$parser->match(TokenType::T_CLOSE_PARENTHESIS);
}
}
@@ -998,7 +976,7 @@ The Query class
---------------
An instance of the ``Doctrine\ORM\Query`` class represents a DQL
query. You create a Query instance be calling
query. You create a Query instance by calling
``EntityManager#createQuery($dql)``, passing the DQL query string.
Alternatively you can create an empty ``Query`` instance and invoke
``Query#setDQL($dql)`` afterwards. Here are some examples:
@@ -1015,58 +993,146 @@ Alternatively you can create an empty ``Query`` instance and invoke
$q = $em->createQuery();
$q->setDQL('select u from MyProject\Model\User u');
Query Result Formats
~~~~~~~~~~~~~~~~~~~~
Query Result Formats (Hydration Modes)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The format in which the result of a DQL SELECT query is returned
can be influenced by a so-called ``hydration mode``. A hydration
mode specifies a particular way in which a SQL result set is
transformed. Each hydration mode has its own dedicated method on
the Query class. Here they are:
The way in which the SQL result set of a DQL SELECT query is transformed
to PHP is determined by the so-called "hydration mode".
``getResult()``
^^^^^^^^^^^^^^^
- ``Query#getResult()``: Retrieves a collection of objects. The
result is either a plain collection of objects (pure) or an array
where the objects are nested in the result rows (mixed).
- ``Query#getSingleResult()``: Retrieves a single object. If the
result contains more than one object, an ``NonUniqueResultException``
is thrown. If the result contains no objects, an ``NoResultException``
is thrown. The pure/mixed distinction does not apply.
- ``Query#getOneOrNullResult()``: Retrieve a single object. If the
result contains more than one object, a ``NonUniqueResultException``
is thrown. If no object is found null will be returned.
- ``Query#getArrayResult()``: Retrieves an array graph (a nested
array) that is largely interchangeable with the object graph
generated by ``Query#getResult()`` for read-only purposes.
Retrieves a collection of objects. The result is either a plain collection of objects (pure) or an array
where the objects are nested in the result rows (mixed):
.. note::
.. code-block:: php
An array graph can differ from the corresponding object
graph in certain scenarios due to the difference of the identity
semantics between arrays and objects.
<?php
use Doctrine\ORM\AbstractQuery;
$query = $em->createQuery('SELECT u FROM User u');
$users = $query->getResult();
// same as:
$users = $query->getResult(AbstractQuery::HYDRATE_OBJECT);
- Objects fetched in a FROM clause are returned as a Set, that means every
object is only ever included in the resulting array once. This is the case
even when using JOIN or GROUP BY in ways that return the same row for an
object multiple times. If the hydrator sees the same object multiple times,
then it makes sure it is only returned once.
- ``Query#getScalarResult()``: Retrieves a flat/rectangular result
set of scalar values that can contain duplicate data. The
pure/mixed distinction does not apply.
- ``Query#getSingleScalarResult()``: Retrieves a single scalar
value from the result returned by the dbms. If the result contains
more than a single scalar value, an exception is thrown. The
pure/mixed distinction does not apply.
- If an object is already in memory from a previous query of any kind, then
then the previous object is used, even if the database may contain more
recent data. This even happens if the previous object is still an unloaded proxy.
Instead of using these methods, you can alternatively use the
general-purpose method
``Query#execute(array $params = [], $hydrationMode = Query::HYDRATE_OBJECT)``.
Using this method you can directly supply the hydration mode as the
second parameter via one of the Query constants. In fact, the
methods mentioned earlier are just convenient shortcuts for the
execute method. For example, the method ``Query#getResult()``
internally invokes execute, passing in ``Query::HYDRATE_OBJECT`` as
the hydration mode.
``getArrayResult()``
^^^^^^^^^^^^^^^^^^^^
The use of the methods mentioned earlier is generally preferred as
it leads to more concise code.
Retrieves an array graph (a nested array) for read-only purposes.
.. note::
An array graph can differ from the corresponding object
graph in certain scenarios due to the difference of the identity
semantics between arrays and objects.
.. code-block:: php
<?php
$users = $query->getArrayResult();
// same as:
$users = $query->getResult(AbstractQuery::HYDRATE_ARRAY);
``getScalarResult()``
^^^^^^^^^^^^^^^^^^^^^
Retrieves a flat/rectangular result set of scalar values that can contain duplicate data. The
pure/mixed distinction does not apply.
.. code-block:: php
<?php
$users = $query->getScalarResult();
// same as:
$users = $query->getResult(AbstractQuery::HYDRATE_SCALAR);
Fields from classes are prefixed by the DQL alias in the result.
A query of the kind `SELECT u.name ...` returns a key `u_name` in the result rows.
``getSingleScalarResult()``
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Retrieves a single scalar value from the result returned by the database. If the result contains
more than a single scalar value, a ``NonUniqueResultException`` is thrown. The pure/mixed distinction does not apply.
.. code-block:: php
<?php
$query = $em->createQuery('SELECT COUNT(u.id) FROM User u');
$numUsers = $query->getSingleScalarResult();
// same as:
$numUsers = $query->getResult(AbstractQuery::HYDRATE_SINGLE_SCALAR);
``getSingleColumnResult()``
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Retrieves an array from a one-dimensional array of scalar values:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT a.id FROM User u');
$ids = $query->getSingleColumnResult();
// same as:
$ids = $query->getResult(AbstractQuery::HYDRATE_SCALAR_COLUMN);
``getSingleResult()``
^^^^^^^^^^^^^^^^^^^^^
Retrieves a single object. If the result contains more than one object, a ``NonUniqueResultException``
is thrown. If the result contains no objects, a ``NoResultException`` is thrown. The pure/mixed distinction does not apply.
``getOneOrNullResult()``
^^^^^^^^^^^^^^^^^^^^^^^^
Retrieves a single object. If the result contains more than one object, a ``NonUniqueResultException``
is thrown. If no object is found, ``null`` will be returned.
Custom Hydration Modes
^^^^^^^^^^^^^^^^^^^^^^
You can easily add your own custom hydration modes by first
creating a class which extends ``AbstractHydrator``:
.. code-block:: php
<?php
namespace MyProject\Hydrators;
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
class CustomHydrator extends AbstractHydrator
{
protected function _hydrateAll()
{
return $this->_stmt->fetchAllAssociative();
}
}
Next you just need to add the class to the ORM configuration:
.. code-block:: php
<?php
$em->getConfiguration()->addCustomHydrationMode('CustomHydrator', 'MyProject\Hydrators\CustomHydrator');
Now the hydrator is ready to be used in your queries:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT u FROM CmsUser u');
$results = $query->getResult('CustomHydrator');
Pure and Mixed Results
~~~~~~~~~~~~~~~~~~~~~~
@@ -1170,166 +1236,6 @@ will return the rows iterating the different top-level entities.
[2] => Object (User)
[3] => Object (Group)
Hydration Modes
~~~~~~~~~~~~~~~
Each of the Hydration Modes makes assumptions about how the result
is returned to user land. You should know about all the details to
make best use of the different result formats:
The constants for the different hydration modes are:
- ``Query::HYDRATE_OBJECT``
- ``Query::HYDRATE_ARRAY``
- ``Query::HYDRATE_SCALAR``
- ``Query::HYDRATE_SINGLE_SCALAR``
- ``Query::HYDRATE_SCALAR_COLUMN``
Object Hydration
^^^^^^^^^^^^^^^^
Object hydration hydrates the result set into the object graph:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT u FROM CmsUser u');
$users = $query->getResult(Query::HYDRATE_OBJECT);
Sometimes the behavior in the object hydrator can be confusing, which is
why we are listing as many of the assumptions here for reference:
- Objects fetched in a FROM clause are returned as a Set, that means every
object is only ever included in the resulting array once. This is the case
even when using JOIN or GROUP BY in ways that return the same row for an
object multiple times. If the hydrator sees the same object multiple times,
then it makes sure it is only returned once.
- If an object is already in memory from a previous query of any kind, then
then the previous object is used, even if the database may contain more
recent data. Data from the database is discarded. This even happens if the
previous object is still an unloaded proxy.
This list might be incomplete.
Array Hydration
^^^^^^^^^^^^^^^
You can run the same query with array hydration and the result set
is hydrated into an array that represents the object graph:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT u FROM CmsUser u');
$users = $query->getResult(Query::HYDRATE_ARRAY);
You can use the ``getArrayResult()`` shortcut as well:
.. code-block:: php
<?php
$users = $query->getArrayResult();
Scalar Hydration
^^^^^^^^^^^^^^^^
If you want to return a flat rectangular result set instead of an
object graph you can use scalar hydration:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT u FROM CmsUser u');
$users = $query->getResult(Query::HYDRATE_SCALAR);
echo $users[0]['u_id'];
The following assumptions are made about selected fields using
Scalar Hydration:
1. Fields from classes are prefixed by the DQL alias in the result.
A query of the kind 'SELECT u.name ..' returns a key 'u_name' in
the result rows.
Single Scalar Hydration
^^^^^^^^^^^^^^^^^^^^^^^
If you have a query which returns just a single scalar value you can use
single scalar hydration:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT COUNT(a.id) FROM CmsUser u LEFT JOIN u.articles a WHERE u.username = ?1 GROUP BY u.id');
$query->setParameter(1, 'jwage');
$numArticles = $query->getResult(Query::HYDRATE_SINGLE_SCALAR);
You can use the ``getSingleScalarResult()`` shortcut as well:
.. code-block:: php
<?php
$numArticles = $query->getSingleScalarResult();
Scalar Column Hydration
^^^^^^^^^^^^^^^^^^^^^^^
If you have a query which returns a one-dimensional array of scalar values
you can use scalar column hydration:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT a.id FROM CmsUser u');
$ids = $query->getResult(Query::HYDRATE_SCALAR_COLUMN);
You can use the ``getSingleColumnResult()`` shortcut as well:
.. code-block:: php
<?php
$ids = $query->getSingleColumnResult();
Custom Hydration Modes
^^^^^^^^^^^^^^^^^^^^^^
You can easily add your own custom hydration modes by first
creating a class which extends ``AbstractHydrator``:
.. code-block:: php
<?php
namespace MyProject\Hydrators;
use Doctrine\DBAL\FetchMode;
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
class CustomHydrator extends AbstractHydrator
{
protected function _hydrateAll()
{
return $this->_stmt->fetchAll(FetchMode::FETCH_ASSOC);
}
}
Next you just need to add the class to the ORM configuration:
.. code-block:: php
<?php
$em->getConfiguration()->addCustomHydrationMode('CustomHydrator', 'MyProject\Hydrators\CustomHydrator');
Now the hydrator is ready to be used in your queries:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT u FROM CmsUser u');
$results = $query->getResult('CustomHydrator');
Iterating Large Result Sets
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1337,8 +1243,8 @@ There are situations when a query you want to execute returns a
very large result-set that needs to be processed. All the
previously described hydration modes completely load a result-set
into memory which might not be feasible with large result sets. See
the `Batch Processing <batch-processing.html>`_ section on details how
to iterate large result sets.
the :doc:`Batch Processing </reference/batch-processing>` section on
details how to iterate large result sets.
Functions
~~~~~~~~~
@@ -1382,7 +1288,7 @@ Result Cache API:
$query->setResultCacheDriver(new ApcCache());
$query->useResultCache(true)
->setResultCacheLifeTime($seconds = 3600);
->setResultCacheLifeTime(3600);
$result = $query->getResult(); // cache miss
@@ -1393,7 +1299,7 @@ Result Cache API:
$result = $query->getResult(); // saved in given result cache id.
// or call useResultCache() with all parameters:
$query->useResultCache(true, $seconds = 3600, 'my_query_result');
$query->useResultCache(true, 3600, 'my_query_result');
$result = $query->getResult(); // cache hit!
// Introspection
@@ -1418,15 +1324,6 @@ exist mostly internal query hints that are not be consumed in
userland. However the following few hints are to be used in
userland:
- ``Query::HINT_FORCE_PARTIAL_LOAD`` - Allows to hydrate objects
although not all their columns are fetched. This query hint can be
used to handle memory consumption problems with large result-sets
that contain char or binary data. Doctrine has no way of implicitly
reloading this data. Partially loaded objects have to be passed to
``EntityManager::refresh()`` if they are to be reloaded fully from
the database. This query hint is deprecated and will be removed
in the future (`Details <https://github.com/doctrine/orm/issues/8471>`_)
- ``Query::HINT_REFRESH`` - This query is used internally by
``EntityManager::refresh()`` and can be used in userland as well.
If you specify this hint and a query returns the data for an entity
@@ -1458,7 +1355,7 @@ several methods to interact with it:
- ``Query::setQueryCacheDriver($driver)`` - Allows to set a Cache
instance
- ``Query::setQueryCacheLifeTime($seconds = 3600)`` - Set lifetime
- ``Query::setQueryCacheLifeTime($seconds)`` - Set lifetime
of the query caching.
- ``Query::expireQueryCache($bool)`` - Enforce the expiring of the
query cache if set to true.
@@ -1583,8 +1480,8 @@ Identifiers
/* Alias Identification declaration (the "u" of "FROM User u") */
AliasIdentificationVariable :: = identifier
/* identifier that must be a class name (the "User" of "FROM User u"), possibly as a fully qualified class name or namespace-aliased */
AbstractSchemaName ::= fully_qualified_name | aliased_name | identifier
/* identifier that must be a class name (the "User" of "FROM User u"), possibly as a fully qualified class name */
AbstractSchemaName ::= fully_qualified_name | identifier
/* Alias ResultVariable declaration (the "total" of "COUNT(*) AS total") */
AliasResultVariable = identifier
@@ -1679,10 +1576,8 @@ Select Expressions
.. code-block:: php
SelectExpression ::= (IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression | NewObjectExpression) [["AS"] ["HIDDEN"] AliasResultVariable]
SelectExpression ::= (IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | "(" Subselect ")" | CaseExpression | NewObjectExpression) [["AS"] ["HIDDEN"] AliasResultVariable]
SimpleSelectExpression ::= (StateFieldPathExpression | IdentificationVariable | FunctionDeclaration | AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable]
PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet
PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}"
NewObjectExpression ::= "NEW" AbstractSchemaName "(" NewObjectArg {"," NewObjectArg}* ")"
NewObjectArg ::= ScalarExpression | "(" Subselect ")"

View File

@@ -131,47 +131,60 @@ There are two ways to set up an event handler:
* For *all events* you can create a Lifecycle Event Listener or Subscriber class and register
it by calling ``$eventManager->addEventListener()`` or ``eventManager->addEventSubscriber()``,
see
:ref:`Listening and subscribing to Lifecycle Events<listening-and-subscribing-to-lifecycle-events>`
:ref:`Listening and subscribing to Lifecycle Events <listening-and-subscribing-to-lifecycle-events>`
* For *some events* (see table below), you can create a *Lifecycle Callback* method in the
entity, see :ref:`Lifecycle Callbacks<lifecycle-callbacks>`.
entity, see :ref:`Lifecycle Callbacks <lifecycle-callbacks>`.
.. _reference-events-lifecycle-events:
Events Overview
---------------
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| Event | Dispatched by | Lifecycle | Passed |
| | | Callback | Argument |
+=================================================================+=======================+===========+=====================================+
| :ref:`preRemove<reference-events-pre-remove>` | ``$em->remove()`` | Yes | `PreRemoveEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postRemove<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `PostRemoveEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`prePersist<reference-events-pre-persist>` | ``$em->persist()`` | Yes | `PrePersistEventArgs`_ |
| | on *initial* persist | | |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postPersist<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `PostPersistEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`preUpdate<reference-events-pre-update>` | ``$em->flush()`` | Yes | `PreUpdateEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postUpdate<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `PostUpdateEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postLoad<reference-events-post-load>` | Loading from database | Yes | `PostLoadEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`loadClassMetadata<reference-events-load-class-metadata>` | Loading of mapping | No | `LoadClassMetadataEventArgs`_ |
| | metadata | | |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| ``onClassMetadataNotFound`` | ``MappingException`` | No | `OnClassMetadataNotFoundEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`preFlush<reference-events-pre-flush>` | ``$em->flush()`` | Yes | `PreFlushEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`onFlush<reference-events-on-flush>` | ``$em->flush()`` | No | `OnFlushEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postFlush<reference-events-post-flush>` | ``$em->flush()`` | No | `PostFlushEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`onClear<reference-events-on-clear>` | ``$em->clear()`` | No | `OnClearEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| Event | Dispatched by | Lifecycle | Passed |
| | | Callback | Argument |
+==================================================================+=======================+===========+=====================================+
| :ref:`preRemove <reference-events-pre-remove>` | ``$em->remove()`` | Yes | `PreRemoveEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postRemove <reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `PostRemoveEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`prePersist <reference-events-pre-persist>` | ``$em->persist()`` | Yes | `PrePersistEventArgs`_ |
| | on *initial* persist | | |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postPersist <reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `PostPersistEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`preUpdate <reference-events-pre-update>` | ``$em->flush()`` | Yes | `PreUpdateEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postUpdate <reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `PostUpdateEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postLoad <reference-events-post-load>` | Loading from database | Yes | `PostLoadEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`loadClassMetadata <reference-events-load-class-metadata>` | Loading of mapping | No | `LoadClassMetadataEventArgs`_ |
| | metadata | | |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| ``onClassMetadataNotFound`` | ``MappingException`` | No | `OnClassMetadataNotFoundEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`preFlush <reference-events-pre-flush>` | ``$em->flush()`` | Yes | `PreFlushEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`onFlush <reference-events-on-flush>` | ``$em->flush()`` | No | `OnFlushEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postFlush <reference-events-post-flush>` | ``$em->flush()`` | No | `PostFlushEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`onClear <reference-events-on-clear>` | ``$em->clear()`` | No | `OnClearEventArgs`_ |
+------------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
.. warning::
Making changes to entities and calling ``EntityManager::flush()`` from within
event handlers dispatched by ``EntityManager::flush()`` itself is strongly
discouraged, and might be deprecated and eventually prevented in the future.
The reason is that it causes re-entrance into ``UnitOfWork::commit()`` while a commit
is currently being processed. The ``UnitOfWork`` was never designed to support this,
and its behavior in this situation is not covered by any tests.
This may lead to entity or collection updates being missed, applied only in parts and
changes being lost at the end of the commit phase.
Naming convention
~~~~~~~~~~~~~~~~~
@@ -215,6 +228,10 @@ specific to a particular entity class's lifecycle.
<?php
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\HasLifecycleCallbacks;
use Doctrine\ORM\Mapping\PrePersist;
use Doctrine\ORM\Mapping\PreUpdate;
#[Entity]
#[HasLifecycleCallbacks]
@@ -243,48 +260,14 @@ specific to a particular entity class's lifecycle.
$this->value = 'changed from preUpdate callback!';
}
}
.. code-block:: annotation
<?php
use Doctrine\ORM\Event\PrePersistEventArgs;
/**
* @Entity
* @HasLifecycleCallbacks
*/
class User
{
// ...
/** @Column(type="string", length=255) */
public $value;
/** @PrePersist */
public function doStuffOnPrePersist(PrePersistEventArgs $eventArgs)
{
$this->createdAt = date('Y-m-d H:i:s');
}
/** @PrePersist */
public function doOtherStuffOnPrePersist()
{
$this->value = 'changed from prePersist callback!';
}
/** @PreUpdate */
public function doStuffOnPreUpdate(PreUpdateEventArgs $eventArgs)
{
$this->value = 'changed from preUpdate callback!';
}
}
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://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">
<!-- ... -->
<lifecycle-callbacks>
@@ -294,17 +277,6 @@ specific to a particular entity class's lifecycle.
</lifecycle-callbacks>
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
fields:
# ...
value:
type: string(255)
lifecycleCallbacks:
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ]
preUpdate: [ doStuffOnPreUpdate ]
Lifecycle Callbacks Event Argument
----------------------------------
@@ -341,7 +313,7 @@ behaviors across different entity classes.
Note that they require much more detailed knowledge about the inner
workings of the ``EntityManager`` and ``UnitOfWork`` classes. Please
read the :ref:`Implementing Event Listeners<reference-events-implementing-listeners>` section
read the :ref:`Implementing Event Listeners <reference-events-implementing-listeners>` section
carefully if you are trying to write your own listener.
For event subscribers, there are no surprises. They declare the
@@ -453,13 +425,12 @@ prePersist
There are two ways for the ``prePersist`` event to be triggered:
- One is obviously when you call ``EntityManager::persist()``. The
event is also called for all :ref:`cascaded associations<transitive-persistence>`.
- The other is inside the
``flush()`` method when changes to associations are computed and
this association is marked as :ref:`cascade: persist<transitive-persistence>`. Any new entity found
during this operation is also persisted and ``prePersist`` called
on it. This is called :ref:`persistence by reachability<persistence-by-reachability>`.
- One is when you call ``EntityManager::persist()``. The
event is also called for all :ref:`cascaded associations <transitive-persistence>`.
- The other is inside the ``flush()`` method when changes to associations are computed and
this association is marked as :ref:`cascade: persist <transitive-persistence>`. Any new entity found
during this operation is also persisted and ``prePersist`` called
on it. This is called :ref:`persistence by reachability <persistence-by-reachability>`.
In both cases you get passed a ``PrePersistEventArgs`` instance
which has access to the entity and the entity manager.
@@ -483,7 +454,7 @@ preRemove
The ``preRemove`` event is called on every entity immediately when it is passed
to the ``EntityManager::remove()`` method. It is cascaded for all
associations that are marked as :ref:`cascade: remove<transitive-persistence>`
associations that are marked as :ref:`cascade: remove <transitive-persistence>`
It is not called for a DQL ``DELETE`` statement.
@@ -531,7 +502,7 @@ entities and their associations have been computed. This means, the
- Collections scheduled for removal
To make use of the ``onFlush`` event you have to be familiar with the
internal :ref:`UnitOfWork<unit-of-work>` API, which grants you access to the previously
internal :ref:`UnitOfWork <unit-of-work>` API, which grants you access to the previously
mentioned sets. See this example:
.. code-block:: php
@@ -696,22 +667,33 @@ Restrictions for this event:
postUpdate, postRemove, postPersist
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These three post* events are called inside ``EntityManager::flush()``.
These three ``post*`` events are called inside ``EntityManager::flush()``.
Changes in here are not relevant to the persistence in the
database, but you can use these events to alter non-persistable items,
like non-mapped fields, logging or even associated classes that are
not directly mapped by Doctrine.
- The ``postUpdate`` event occurs after the database
update operations to entity data. It is not called for a DQL
``UPDATE`` statement.
- The ``postPersist`` event occurs for an entity after
the entity has been made persistent. It will be invoked after the
database insert operations. Generated primary key values are
available in the postPersist event.
update operations to entity data, but before the database transaction
has been committed. It is not called for a DQL ``UPDATE`` statement.
- The ``postPersist`` event occurs for an entity after the entity has
been made persistent. It will be invoked after all database insert
operations for new entities have been performed, but before the database
transaction has been committed. Generated primary key values will be
available for all entities at the time this event is triggered.
- The ``postRemove`` event occurs for an entity after the
entity has been deleted. It will be invoked after the database
delete operations. It is not called for a DQL ``DELETE`` statement.
entity has been deleted. It will be invoked after all database
delete operations for entity rows have been executed, but before the
database transaction has been committed. This event is not called for
a DQL ``DELETE`` statement.
.. note::
At the time ``postPersist`` is called, there may still be collection and/or
"extra" updates pending. The database may not yet be completely in
sync with the entity states in memory, not even for the new entities. Similarly,
also at the time ``postUpdate`` and ``postRemove`` are called, in-memory collections
may still be in a "dirty" state or still contain removed entities.
.. warning::
@@ -767,16 +749,6 @@ An entity listener is a lifecycle listener class used for an entity.
{
// ....
}
.. code-block:: annotation
<?php
namespace MyProject\Entity;
/** @Entity @EntityListeners({"UserListener"}) */
class User
{
// ....
}
.. code-block:: xml
<doctrine-mapping>
@@ -787,13 +759,6 @@ An entity listener is a lifecycle listener class used for an entity.
<!-- .... -->
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Entity\User:
type: entity
entityListeners:
UserListener:
# ....
.. _reference-entity-listeners:
@@ -866,45 +831,6 @@ you need to map the listener method using the event type mapping:
public function postLoadHandler(User $user, PostLoadEventArgs $event): void { // ... }
}
.. code-block:: annotation
<?php
use Doctrine\ORM\Event\PostLoadEventArgs;
use Doctrine\ORM\Event\PostPersistEventArgs;
use Doctrine\ORM\Event\PostRemoveEventArgs;
use Doctrine\ORM\Event\PostUpdateEventArgs;
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Event\PreRemoveEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
class UserListener
{
/** @PrePersist */
public function prePersistHandler(User $user, PrePersistEventArgs $event): void { // ... }
/** @PostPersist */
public function postPersistHandler(User $user, PostPersistEventArgs $event): void { // ... }
/** @PreUpdate */
public function preUpdateHandler(User $user, PreUpdateEventArgs $event): void { // ... }
/** @PostUpdate */
public function postUpdateHandler(User $user, PostUpdateEventArgs $event): void { // ... }
/** @PostRemove */
public function postRemoveHandler(User $user, PostRemoveEventArgs $event): void { // ... }
/** @PreRemove */
public function preRemoveHandler(User $user, PreRemoveEventArgs $event): void { // ... }
/** @PreFlush */
public function preFlushHandler(User $user, PreFlushEventArgs $event): void { // ... }
/** @PostLoad */
public function postLoadHandler(User $user, PostLoadEventArgs $event): void { // ... }
}
.. code-block:: xml
<doctrine-mapping>
@@ -927,24 +853,6 @@ you need to map the listener method using the event type mapping:
<!-- .... -->
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Entity\User:
type: entity
entityListeners:
UserListener:
preFlush: [preFlushHandler]
postLoad: [postLoadHandler]
postPersist: [postPersistHandler]
prePersist: [prePersistHandler]
postUpdate: [postUpdateHandler]
preUpdate: [preUpdateHandler]
postRemove: [postRemoveHandler]
preRemove: [preRemoveHandler]
# ....
.. note::
@@ -967,7 +875,8 @@ Specifying an entity listener instance :
// User.php
/** @Entity @EntityListeners({"UserListener"}) */
#[Entity]
#[EntityListeners(["UserListener"])
class User
{
// ....
@@ -1025,7 +934,7 @@ Load ClassMetadata Event
``loadClassMetadata`` - The ``loadClassMetadata`` event occurs after the
mapping metadata for a class has been loaded from a mapping source
(attributes/annotations/xml/yaml) in to a ``Doctrine\ORM\Mapping\ClassMetadata`` instance.
(attributes/xml) in to a ``Doctrine\ORM\Mapping\ClassMetadata`` instance.
You can hook in to this process and manipulate the instance.
This event is not a lifecycle callback.
@@ -1116,16 +1025,16 @@ and the EntityManager.
}
}
.. _PrePersistEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PrePersistEventArgs.php
.. _PreRemoveEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PreRemoveEventArgs.php
.. _PreUpdateEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php
.. _PostPersistEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PostPersistEventArgs.php
.. _PostRemoveEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PostRemoveEventArgs.php
.. _PostUpdateEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PostUpdateEventArgs.php
.. _PostLoadEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PostLoadEventArgs.php
.. _PreFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PreFlushEventArgs.php
.. _PostFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PostFlushEventArgs.php
.. _OnFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/OnFlushEventArgs.php
.. _OnClearEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/OnClearEventArgs.php
.. _LoadClassMetadataEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php
.. _OnClassMetadataNotFoundEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php
.. _PrePersistEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PrePersistEventArgs.php
.. _PreRemoveEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PreRemoveEventArgs.php
.. _PreUpdateEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PreUpdateEventArgs.php
.. _PostPersistEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PostPersistEventArgs.php
.. _PostRemoveEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PostRemoveEventArgs.php
.. _PostUpdateEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PostUpdateEventArgs.php
.. _PostLoadEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PostLoadEventArgs.php
.. _PreFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PreFlushEventArgs.php
.. _PostFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/PostFlushEventArgs.php
.. _OnFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/OnFlushEventArgs.php
.. _OnClearEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/OnClearEventArgs.php
.. _LoadClassMetadataEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/LoadClassMetadataEventArgs.php
.. _OnClassMetadataNotFoundEventArgs: https://github.com/doctrine/orm/blob/HEAD/src/Event/OnClassMetadataNotFoundEventArgs.php

View File

@@ -13,11 +13,10 @@ Database Schema
How do I set the charset and collation for MySQL tables?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can't set these values with attributes, annotations or inside yml or
xml mapping files. To make a database work with the default charset and
collation you should configure MySQL to use it as default charset, or
create the database with charset and collation details. This way they
get inherited to all newly created database tables and columns.
In your mapping configuration, the column definition (for example, the
``#[Column]`` attribute) has an ``options`` parameter where you can specify
the ``charset`` and ``collation``. The default values are ``utf8`` and
``utf8_unicode_ci``, respectively.
Entity Classes
--------------
@@ -102,7 +101,7 @@ The many-to-many association is only supporting foreign keys in the table defini
To work with many-to-many tables containing extra columns you have to use the
foreign keys as primary keys feature of Doctrine ORM.
See :doc:`the tutorial on composite primary keys for more information<../tutorials/composite-primary-keys>`.
See :doc:`the tutorial on composite primary keys for more information <../tutorials/composite-primary-keys>`.
How can i paginate fetch-joined collections?

View File

@@ -93,3 +93,34 @@ object.
want to refresh or reload an object after having modified a filter or the
FilterCollection, then you should clear the EntityManager and re-fetch your
entities, having the new rules for filtering applied.
Suspending/Restoring Filters
----------------------------
When a filter is disabled, the instance is fully deleted and all the filter
parameters previously set are lost. Then, if you enable it again, a new filter
is created without the previous filter parameters. If you want to keep a filter
(in order to use it later) but temporary disable it, you'll need to use the
``FilterCollection#suspend($name)`` and ``FilterCollection#restore($name)``
methods instead.
.. code-block:: php
<?php
$filter = $em->getFilters()->enable("locale");
$filter->setParameter('locale', 'en');
// Temporary suspend the filter
$filter = $em->getFilters()->suspend("locale");
// Do things
// Then restore it, the locale parameter will still be set
$filter = $em->getFilters()->restore("locale");
.. warning::
If you enable a previously disabled filter, doctrine will create a new
one without keeping any of the previously parameter set with
``SQLFilter#setParameter()`` or ``SQLFilter#getParameterList()``. If you
want to restore the previously disabled filter instead, you must use the
``FilterCollection#restore($name)`` method.

View File

@@ -91,7 +91,7 @@ Apply Best Practices
A lot of the points mentioned in the Best Practices chapter will
also positively affect the performance of Doctrine.
See :doc:`Best Practices <reference/best-practices>`
See :doc:`Best Practices </reference/best-practices>`
Change Tracking policies
------------------------

View File

@@ -15,27 +15,37 @@ 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).
(through Single Table Inheritance or Class Table Inheritance). They
are not query-able, and need not have an ``#[Id]`` property.
No database table will be created for a mapped superclass itself,
only for entity classes inheriting from it. Also, a mapped superclass
need not have an ``#[Id]`` property.
only for entity classes inheriting from it. That implies that a
mapped superclass cannot be the ``targetEntity`` in associations.
In other words, a mapped superclass can use unidirectional One-To-One
and Many-To-One associations where it is the owning side.
Many-To-Many associations are only possible if the mapped
superclass is only used in exactly one entity at the moment. For further
support of inheritance, the single or joined table inheritance features
have to be used.
.. note::
A mapped superclass cannot be an entity, it is not query-able and
persistent relationships defined by a mapped superclass must be
unidirectional (with an owning side only). This means that One-To-Many
associations are not possible on a mapped superclass at all.
Furthermore Many-To-Many associations are only possible if the
mapped superclass is only used in exactly one entity at the moment.
For further support of inheritance, the single or
joined table inheritance features have to be used.
One-To-Many associations are not generally possible on a mapped
superclass, since they require the "many" side to hold the foreign
key.
It is, however, possible to use the :doc:`ResolveTargetEntityListener </cookbook/resolve-target-entity-listener>`
to replace references to a mapped superclass with an entity class at runtime.
As long as there is only one entity subclass inheriting from the mapped
superclass and all references to the mapped superclass are resolved to that
entity class at runtime, the mapped superclass *can* use One-To-Many associations
and be named as the ``targetEntity`` on the owning sides.
.. warning::
At least when using attributes or annotations to specify your mapping,
it _seems_ as if you could inherit from a base class that is neither
it *seems* as if you could inherit from a base class that is neither
an entity nor a mapped superclass, but has properties with mapping configuration
on them that would also be used in the inheriting class.
@@ -50,7 +60,7 @@ need not have an ``#[Id]`` property.
You may be tempted to use traits to mix mapped fields or relationships
into your entity classes to circumvent some of the limitations of
mapped superclasses. Before doing that, please read the section on traits
in the :doc:`Limitations and Known Issues <reference/limitations-and-known-issues>` chapter.
in the :doc:`Limitations and Known Issues </reference/limitations-and-known-issues>` chapter.
Example:
@@ -198,44 +208,6 @@ Example:
// ...
}
.. code-block:: annotation
<?php
namespace MyProject\Model;
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* @Entity
*/
class Employee extends Person
{
// ...
}
.. code-block:: yaml
MyProject\Model\Person:
type: entity
inheritanceType: SINGLE_TABLE
discriminatorColumn:
name: discr
type: string
discriminatorMap:
person: Person
employee: Employee
MyProject\Model\Employee:
type: entity
In this example, the ``#[DiscriminatorMap]`` specifies that in the
discriminator column, a value of "person" identifies a row as being of type
@@ -370,7 +342,7 @@ It is not supported to use overrides in entity inheritance scenarios.
.. note::
When using traits, make sure not to miss the warnings given in the
:doc:`Limitations and Known Issues<reference/limitations-and-known-issues>` chapter.
:doc:`Limitations and Known Issues </reference/limitations-and-known-issues>` chapter.
Association Override
@@ -429,58 +401,6 @@ Example:
{
}
.. code-block:: annotation
<?php
// user mapping
namespace MyProject\Model;
/**
* @MappedSuperclass
*/
class User
{
// other fields mapping
/**
* @ManyToMany(targetEntity="Group", inversedBy="users")
* @JoinTable(name="users_groups",
* joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id")}
* )
* @var Collection<int, Group>
*/
protected Collection $groups;
/**
* @ManyToOne(targetEntity="Address")
* @JoinColumn(name="address_id", referencedColumnName="id")
*/
protected Address|null $address = null;
}
// admin mapping
namespace MyProject\Model;
/**
* @Entity
* @AssociationOverrides({
* @AssociationOverride(name="groups",
* joinTable=@JoinTable(
* name="users_admingroups",
* joinColumns=@JoinColumn(name="adminuser_id"),
* inverseJoinColumns=@JoinColumn(name="admingroup_id")
* )
* ),
* @AssociationOverride(name="address",
* joinColumns=@JoinColumn(
* name="adminaddress_id", referencedColumnName="id"
* )
* )
* })
*/
class Admin extends User
{
}
.. code-block:: xml
<!-- user mapping -->
@@ -490,7 +410,6 @@ Example:
<many-to-many field="groups" target-entity="Group" inversed-by="users">
<cascade>
<cascade-persist/>
<cascade-merge/>
<cascade-detach/>
</cascade>
<join-table name="users_groups">
@@ -527,51 +446,6 @@ Example:
</association-overrides>
</entity>
</doctrine-mapping>
.. code-block:: yaml
# user mapping
MyProject\Model\User:
type: mappedSuperclass
# other fields mapping
manyToOne:
address:
targetEntity: Address
joinColumn:
name: address_id
referencedColumnName: id
cascade: [ persist, merge ]
manyToMany:
groups:
targetEntity: Group
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
cascade: [ persist, merge, detach ]
# admin mapping
MyProject\Model\Admin:
type: entity
associationOverride:
address:
joinColumn:
adminaddress_id:
name: adminaddress_id
referencedColumnName: id
groups:
joinTable:
name: users_admingroups
joinColumns:
adminuser_id:
referencedColumnName: id
inverseJoinColumns:
admingroup_id:
referencedColumnName: id
Things to note:
@@ -635,51 +509,6 @@ Could be used by an entity that extends a mapped superclass to override a field
{
}
.. code-block:: annotation
<?php
// user mapping
namespace MyProject\Model;
/**
* @MappedSuperclass
*/
class User
{
/** @Id @GeneratedValue @Column(type="integer", name="user_id", length=150) */
protected int|null $id = null;
/** @Column(name="user_name", nullable=true, unique=false, length=250) */
protected string $name;
// other fields mapping
}
// guest mapping
namespace MyProject\Model;
/**
* @Entity
* @AttributeOverrides({
* @AttributeOverride(name="id",
* column=@Column(
* name = "guest_id",
* type = "integer",
* length = 140
* )
* ),
* @AttributeOverride(name="name",
* column=@Column(
* name = "guest_name",
* nullable = false,
* unique = true,
* length = 240
* )
* )
* })
*/
class Guest extends User
{
}
.. code-block:: xml
<!-- user mapping -->
@@ -692,7 +521,6 @@ Could be used by an entity that extends a mapped superclass to override a field
<many-to-one field="address" target-entity="Address">
<cascade>
<cascade-persist/>
<cascade-merge/>
</cascade>
<join-column name="address_id" referenced-column-name="id"/>
</many-to-one>
@@ -713,42 +541,6 @@ Could be used by an entity that extends a mapped superclass to override a field
</attribute-overrides>
</entity>
</doctrine-mapping>
.. code-block:: yaml
# user mapping
MyProject\Model\User:
type: mappedSuperclass
id:
id:
type: integer
column: user_id
length: 150
generator:
strategy: AUTO
fields:
name:
type: string
column: user_name
length: 250
nullable: true
unique: false
#other fields mapping
# guest mapping
MyProject\Model\Guest:
type: entity
attributeOverride:
id:
column: guest_id
type: integer
length: 140
name:
column: guest_name
type: string
length: 240
nullable: false
unique: true
Things to note:

View File

@@ -1,4 +1,4 @@
Installation
============
The installation chapter has moved to :doc:`Installation and Configuration <reference/configuration>`_.
The installation chapter has moved to :doc:`Installation and Configuration </reference/configuration>`.

View File

@@ -1,10 +1,10 @@
Limitations and Known Issues
============================
We try to make using Doctrine2 a very pleasant experience.
We try to make using Doctrine ORM a very pleasant experience.
Therefore we think it is very important to be honest about the
current limitations to our users. Much like every other piece of
software Doctrine2 is not perfect and far from feature complete.
software the ORM is not perfect and far from feature complete.
This section should give you an overview of current limitations of
Doctrine ORM as well as critical known issues that you should know
about.
@@ -65,15 +65,6 @@ Where the ``attribute_name`` column contains the key and
The feature request for persistence of primitive value arrays
`is described in the DDC-298 ticket <https://github.com/doctrine/orm/issues/3743>`_.
Cascade Merge with Bi-directional Associations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are two bugs now that concern the use of cascade merge in combination with bi-directional associations.
Make sure to study the behavior of cascade merge if you are using it:
- `DDC-875 <https://github.com/doctrine/orm/issues/5398>`_ Merge can sometimes add the same entity twice into a collection
- `DDC-763 <https://github.com/doctrine/orm/issues/5277>`_ Cascade merge on associated entities can insert too many rows through "Persistence by Reachability"
Custom Persisters
~~~~~~~~~~~~~~~~~
@@ -145,7 +136,7 @@ more than two years after the initial Doctrine 2 release and the time where
core components were designed.
In fact, this documentation mentions traits only in the context of
:doc:`overriding field association mappings in subclasses <tutorials/override-field-association-mappings-in-subclasses>`.
:doc:`overriding field association mappings in subclasses </tutorials/override-field-association-mappings-in-subclasses>`.
Coverage of traits in test cases is practically nonexistent.
Thus, you should at least be aware that when using traits in your entity and
@@ -162,19 +153,31 @@ that, some precedence and conflict resolution rules apply.
When it comes to loading mapping configuration, the annotation and attribute drivers
rely on PHP reflection to inspect class properties including their docblocks.
As long as the results are consistent with what a solution _without_ traits would
As long as the results are consistent with what a solution *without* traits would
have produced, this is probably fine.
However, to mention known limitations, it is currently not possible to use "class"
level `annotations <https://github.com/doctrine/orm/pull/1517>` or
`attributes <https://github.com/doctrine/orm/issues/8868>` on traits, and attempts to
improve parser support for traits as `here <https://github.com/doctrine/annotations/pull/102>`
or `there <https://github.com/doctrine/annotations/pull/63>` have been abandoned
level `annotations <https://github.com/doctrine/orm/pull/1517>`_ or
`attributes <https://github.com/doctrine/orm/issues/8868>`_ on traits, and attempts to
improve parser support for traits as `here <https://github.com/doctrine/annotations/pull/102>`_
or `there <https://github.com/doctrine/annotations/pull/63>`_ have been abandoned
due to complexity.
XML mapping configuration probably needs to completely re-configure or otherwise
copy-and-paste configuration for fields used from traits.
Mapping multiple private fields of the same name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When two classes, say a mapped superclass and an entity inheriting from it,
both contain a ``private`` field of the same name, this will lead to a ``MappingException``.
Since the fields are ``private``, both are technically separate and can contain
different values at the same time. However, the ``ClassMetadata`` configuration used
internally by the ORM currently refers to fields by their name only, without taking the
class containing the field into consideration. This makes it impossible to keep separate
mapping configuration for both fields.
Known Issues
------------

View File

@@ -16,13 +16,6 @@ metadata:
- **Attributes** (AttributeDriver)
- **PHP Code in files or static functions** (PhpDriver)
There are also two deprecated ways to do this:
- **Class DocBlock Annotations** (AnnotationDriver)
- **YAML files** (YamlDriver)
They will be removed in 3.0, make sure to avoid them.
Something important to note about the above drivers is they are all
an intermediate step to the same end result. The mapping
information is populated to ``Doctrine\ORM\Mapping\ClassMetadata``
@@ -44,11 +37,7 @@ an entity.
$em->getConfiguration()->setMetadataCacheImpl(new ApcuCache());
If you want to use one of the included core metadata drivers you need to
configure it. If you pick the annotation driver despite it being
deprecated, you will additionally need to install
``doctrine/annotations``. All the drivers are in the
``Doctrine\ORM\Mapping\Driver`` namespace:
All the drivers are in the ``Doctrine\ORM\Mapping\Driver`` namespace:
.. code-block:: php
@@ -123,12 +112,12 @@ the ``FileDriver`` implementation for you to extend from:
class MyMetadataDriver extends FileDriver
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected $_fileExtension = '.dcm.ext';
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function loadMetadataForClass($className, ClassMetadata $metadata)
{
@@ -138,7 +127,7 @@ the ``FileDriver`` implementation for you to extend from:
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
protected function _loadMappingFile($file)
{

View File

@@ -110,28 +110,28 @@ You need to create a class which implements ``Doctrine\ORM\Mapping\NamingStrateg
<?php
class MyAppNamingStrategy implements NamingStrategy
{
public function classToTableName($className)
public function classToTableName(string $className): string
{
return 'MyApp_' . substr($className, strrpos($className, '\\') + 1);
}
public function propertyToColumnName($propertyName)
public function propertyToColumnName(string $propertyName): string
{
return $propertyName;
}
public function referenceColumnName()
public function referenceColumnName(): string
{
return 'id';
}
public function joinColumnName($propertyName, $className = null)
public function joinColumnName(string $propertyName, ?string $className = null): string
{
return $propertyName . '_' . $this->referenceColumnName();
}
public function joinTableName($sourceEntity, $targetEntity, $propertyName = null)
public function joinTableName(string $sourceEntity, string $targetEntity, string $propertyName): string
{
return strtolower($this->classToTableName($sourceEntity) . '_' .
$this->classToTableName($targetEntity));
}
public function joinKeyColumnName($entityName, $referencedColumnName = null)
public function joinKeyColumnName(string $entityName, ?string $referencedColumnName): string
{
return strtolower($this->classToTableName($entityName) . '_' .
($referencedColumnName ?: $this->referenceColumnName()));

View File

@@ -250,6 +250,40 @@ The first parameter is the name of the column in the SQL result set
and the second parameter is the result alias under which the value
of the column will be placed in the transformed Doctrine result.
Special case: DTOs
...................
You can also use ``ResultSetMapping`` to map the results of a native SQL
query to a DTO (Data Transfer Object). This is done by adding scalar
results for each argument of the DTO's constructor, then filling the
``newObjectMappings`` property of the ``ResultSetMapping`` with
information about where to map each scalar result:
.. code-block:: php
<?php
$rsm = new ResultSetMapping();
$rsm->addScalarResult('name', 1, 'string');
$rsm->addScalarResult('email', 2, 'string');
$rsm->addScalarResult('city', 3, 'string');
$rsm->newObjectMappings['name'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0, // a result can contain many DTOs, this is the index of the DTO to map to
'argIndex' => 0, // each scalar result can be mapped to a different argument of the DTO constructor
];
$rsm->newObjectMappings['email'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0,
'argIndex' => 1,
];
$rsm->newObjectMappings['city'] = [
'className' => CmsUserDTO::class,
'objIndex' => 0,
'argIndex' => 2,
];
Meta results
~~~~~~~~~~~~
@@ -431,477 +465,3 @@ above would result in partial objects if any objects in the result
are actually a subtype of User. When using DQL, Doctrine
automatically includes the necessary joins for this mapping
strategy but with native SQL it is your responsibility.
Named Native Query
------------------
.. note::
Named Native Queries are deprecated as of version 2.9 and will be removed in ORM 3.0
You can also map a native query using a named native query mapping.
To achieve that, you must describe the SQL resultset structure
using named native query (and sql resultset mappings if is a several resultset mappings).
Like named query, a named native query can be defined at class level or in a XML or YAML file.
A resultSetMapping parameter is defined in @NamedNativeQuery,
it represents the name of a defined @SqlResultSetMapping.
.. configuration-block::
.. code-block:: php
<?php
namespace MyProject\Model;
/**
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "fetchMultipleJoinsEntityResults",
* resultSetMapping= "mappingMultipleJoinsEntityResults",
* query = "SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username"
* ),
* })
* @SqlResultSetMappings({
* @SqlResultSetMapping(
* name = "mappingMultipleJoinsEntityResults",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__",
* fields = {
* @FieldResult(name = "id", column="u_id"),
* @FieldResult(name = "name", column="u_name"),
* @FieldResult(name = "status", column="u_status"),
* }
* ),
* @EntityResult(
* entityClass = "Address",
* fields = {
* @FieldResult(name = "id", column="a_id"),
* @FieldResult(name = "zip", column="a_zip"),
* @FieldResult(name = "country", column="a_country"),
* }
* )
* },
* columns = {
* @ColumnResult("numphones")
* }
* )
*})
*/
class User
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @Column(type="string", length=50, nullable=true) */
public $status;
/** @Column(type="string", length=255, unique=true) */
public $username;
/** @Column(type="string", length=255) */
public $name;
/** @OneToMany(targetEntity="Phonenumber") */
public $phonenumbers;
/** @OneToOne(targetEntity="Address") */
public $address;
// ....
}
.. code-block:: xml
<doctrine-mapping>
<entity name="MyProject\Model\User">
<named-native-queries>
<named-native-query name="fetchMultipleJoinsEntityResults" result-set-mapping="mappingMultipleJoinsEntityResults">
<query>SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username</query>
</named-native-query>
</named-native-queries>
<sql-result-set-mappings>
<sql-result-set-mapping name="mappingMultipleJoinsEntityResults">
<entity-result entity-class="__CLASS__">
<field-result name="id" column="u_id"/>
<field-result name="name" column="u_name"/>
<field-result name="status" column="u_status"/>
</entity-result>
<entity-result entity-class="Address">
<field-result name="id" column="a_id"/>
<field-result name="zip" column="a_zip"/>
<field-result name="country" column="a_country"/>
</entity-result>
<column-result name="numphones"/>
</sql-result-set-mapping>
</sql-result-set-mappings>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\User:
type: entity
namedNativeQueries:
fetchMultipleJoinsEntityResults:
name: fetchMultipleJoinsEntityResults
resultSetMapping: mappingMultipleJoinsEntityResults
query: SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username
sqlResultSetMappings:
mappingMultipleJoinsEntityResults:
name: mappingMultipleJoinsEntityResults
columnResult:
0:
name: numphones
entityResult:
0:
entityClass: __CLASS__
fieldResult:
0:
name: id
column: u_id
1:
name: name
column: u_name
2:
name: status
column: u_status
1:
entityClass: Address
fieldResult:
0:
name: id
column: a_id
1:
name: zip
column: a_zip
2:
name: country
column: a_country
Things to note:
- The resultset mapping declares the entities retrieved by this native query.
- Each field of the entity is bound to a SQL alias (or column name).
- All fields of the entity including the ones of subclasses
and the foreign key columns of related entities have to be present in the SQL query.
- Field definitions are optional provided that they map to the same
column name as the one declared on the class property.
- ``__CLASS__`` is an alias for the mapped class
In the above example,
the ``fetchJoinedAddress`` named query use the joinMapping result set mapping.
This mapping returns 2 entities, User and Address, each property is declared and associated to a column name,
actually the column name retrieved by the query.
Let's now see an implicit declaration of the property / column.
.. configuration-block::
.. code-block:: php
<?php
namespace MyProject\Model;
/**
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "findAll",
* resultSetMapping = "mappingFindAll",
* query = "SELECT * FROM addresses"
* ),
* })
* @SqlResultSetMappings({
* @SqlResultSetMapping(
* name = "mappingFindAll",
* entities= {
* @EntityResult(
* entityClass = "Address"
* )
* }
* )
* })
*/
class Address
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @Column() */
public $country;
/** @Column() */
public $zip;
/** @Column()*/
public $city;
// ....
}
.. code-block:: xml
<doctrine-mapping>
<entity name="MyProject\Model\Address">
<named-native-queries>
<named-native-query name="findAll" result-set-mapping="mappingFindAll">
<query>SELECT * FROM addresses</query>
</named-native-query>
</named-native-queries>
<sql-result-set-mappings>
<sql-result-set-mapping name="mappingFindAll">
<entity-result entity-class="Address"/>
</sql-result-set-mapping>
</sql-result-set-mappings>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\Address:
type: entity
namedNativeQueries:
findAll:
resultSetMapping: mappingFindAll
query: SELECT * FROM addresses
sqlResultSetMappings:
mappingFindAll:
name: mappingFindAll
entityResult:
address:
entityClass: Address
In this example, we only describe the entity member of the result set mapping.
The property / column mappings is done using the entity mapping values.
In this case the model property is bound to the model_txt column.
If the association to a related entity involve a composite primary key,
a @FieldResult element should be used for each foreign key column.
The @FieldResult name is composed of the property name for the relationship,
followed by a dot ("."), followed by the name or the field or property of the primary key.
.. configuration-block::
.. code-block:: php
<?php
namespace MyProject\Model;
/**
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "fetchJoinedAddress",
* resultSetMapping= "mappingJoinedAddress",
* query = "SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ?"
* ),
* })
* @SqlResultSetMappings({
* @SqlResultSetMapping(
* name = "mappingJoinedAddress",
* entities= {
* @EntityResult(
* entityClass = "__CLASS__",
* fields = {
* @FieldResult(name = "id"),
* @FieldResult(name = "name"),
* @FieldResult(name = "status"),
* @FieldResult(name = "address.id", column = "a_id"),
* @FieldResult(name = "address.zip", column = "a_zip"),
* @FieldResult(name = "address.city", column = "a_city"),
* @FieldResult(name = "address.country", column = "a_country"),
* }
* )
* }
* )
* })
*/
class User
{
/** @Id @Column(type="integer") @GeneratedValue */
public $id;
/** @Column(type="string", length=50, nullable=true) */
public $status;
/** @Column(type="string", length=255, unique=true) */
public $username;
/** @Column(type="string", length=255) */
public $name;
/** @OneToOne(targetEntity="Address") */
public $address;
// ....
}
.. code-block:: xml
<doctrine-mapping>
<entity name="MyProject\Model\User">
<named-native-queries>
<named-native-query name="fetchJoinedAddress" result-set-mapping="mappingJoinedAddress">
<query>SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ?</query>
</named-native-query>
</named-native-queries>
<sql-result-set-mappings>
<sql-result-set-mapping name="mappingJoinedAddress">
<entity-result entity-class="__CLASS__">
<field-result name="id"/>
<field-result name="name"/>
<field-result name="status"/>
<field-result name="address.id" column="a_id"/>
<field-result name="address.zip" column="a_zip"/>
<field-result name="address.city" column="a_city"/>
<field-result name="address.country" column="a_country"/>
</entity-result>
</sql-result-set-mapping>
</sql-result-set-mappings>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\User:
type: entity
namedNativeQueries:
fetchJoinedAddress:
name: fetchJoinedAddress
resultSetMapping: mappingJoinedAddress
query: SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ?
sqlResultSetMappings:
mappingJoinedAddress:
entityResult:
0:
entityClass: __CLASS__
fieldResult:
0:
name: id
1:
name: name
2:
name: status
3:
name: address.id
column: a_id
4:
name: address.zip
column: a_zip
5:
name: address.city
column: a_city
6:
name: address.country
column: a_country
If you retrieve a single entity and if you use the default mapping,
you can use the resultClass attribute instead of resultSetMapping:
.. configuration-block::
.. code-block:: php
<?php
namespace MyProject\Model;
/**
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "find-by-id",
* resultClass = "Address",
* query = "SELECT * FROM addresses"
* ),
* })
*/
class Address
{
// ....
}
.. code-block:: xml
<doctrine-mapping>
<entity name="MyProject\Model\Address">
<named-native-queries>
<named-native-query name="find-by-id" result-class="Address">
<query>SELECT * FROM addresses WHERE id = ?</query>
</named-native-query>
</named-native-queries>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\Address:
type: entity
namedNativeQueries:
findAll:
name: findAll
resultClass: Address
query: SELECT * FROM addresses
In some of your native queries, you'll have to return scalar values,
for example when building report queries.
You can map them in the @SqlResultsetMapping through @ColumnResult.
You actually can even mix, entities and scalar returns in the same native query (this is probably not that common though).
.. configuration-block::
.. code-block:: php
<?php
namespace MyProject\Model;
/**
* @NamedNativeQueries({
* @NamedNativeQuery(
* name = "count",
* resultSetMapping= "mappingCount",
* query = "SELECT COUNT(*) AS count FROM addresses"
* )
* })
* @SqlResultSetMappings({
* @SqlResultSetMapping(
* name = "mappingCount",
* columns = {
* @ColumnResult(
* name = "count"
* )
* }
* )
* })
*/
class Address
{
// ....
}
.. code-block:: xml
<doctrine-mapping>
<entity name="MyProject\Model\Address">
<named-native-query name="count" result-set-mapping="mappingCount">
<query>SELECT COUNT(*) AS count FROM addresses</query>
</named-native-query>
<sql-result-set-mappings>
<sql-result-set-mapping name="mappingCount">
<column-result name="count"/>
</sql-result-set-mapping>
</sql-result-set-mappings>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\Address:
type: entity
namedNativeQueries:
count:
name: count
resultSetMapping: mappingCount
query: SELECT COUNT(*) AS count FROM addresses
sqlResultSetMappings:
mappingCount:
name: mappingCount
columnResult:
count:
name: count

View File

@@ -1,98 +0,0 @@
Partial Objects
===============
.. note::
Creating Partial Objects through DQL is deprecated and
will be removed in the future, use data transfer object
support in DQL instead. (`Details
<https://github.com/doctrine/orm/issues/8471>`_)
A partial object is an object whose state is not fully initialized
after being reconstituted from the database and that is
disconnected from the rest of its data. The following section will
describe why partial objects are problematic and what the approach
of Doctrine2 to this problem is.
.. note::
The partial object problem in general does not apply to
methods or queries where you do not retrieve the query result as
objects. Examples are: ``Query#getArrayResult()``,
``Query#getScalarResult()``, ``Query#getSingleScalarResult()``,
etc.
.. warning::
Use of partial objects is tricky. Fields that are not retrieved
from the database will not be updated by the UnitOfWork even if they
get changed in your objects. You can only promote a partial object
to a fully-loaded object by calling ``EntityManager#refresh()``
or a DQL query with the refresh flag.
What is the problem?
--------------------
In short, partial objects are problematic because they are usually
objects with broken invariants. As such, code that uses these
partial objects tends to be very fragile and either needs to "know"
which fields or methods can be safely accessed or add checks around
every field access or method invocation. The same holds true for
the internals, i.e. the method implementations, of such objects.
You usually simply assume the state you need in the method is
available, after all you properly constructed this object before
you pushed it into the database, right? These blind assumptions can
quickly lead to null reference errors when working with such
partial objects.
It gets worse with the scenario of an optional association (0..1 to
1). When the associated field is NULL, you don't know whether this
object does not have an associated object or whether it was simply
not loaded when the owning object was loaded from the database.
These are reasons why many ORMs do not allow partial objects at all
and instead you always have to load an object with all its fields
(associations being proxied). One secure way to allow partial
objects is if the programming language/platform allows the ORM tool
to hook deeply into the object and instrument it in such a way that
individual fields (not only associations) can be loaded lazily on
first access. This is possible in Java, for example, through
bytecode instrumentation. In PHP though this is not possible, so
there is no way to have "secure" partial objects in an ORM with
transparent persistence.
Doctrine, by default, does not allow partial objects. That means,
any query that only selects partial object data and wants to
retrieve the result as objects (i.e. ``Query#getResult()``) will
raise an exception telling you that partial objects are dangerous.
If you want to force a query to return you partial objects,
possibly as a performance tweak, you can use the ``partial``
keyword as follows:
.. code-block:: php
<?php
$q = $em->createQuery("select partial u.{id,name} from MyApp\Domain\User u");
You can also get a partial reference instead of a proxy reference by
calling:
.. code-block:: php
<?php
$reference = $em->getPartialReference('MyApp\Domain\User', 1);
Partial references are objects with only the identifiers set as they
are passed to the second argument of the ``getPartialReference()`` method.
All other fields are null.
When should I force partial objects?
------------------------------------
Mainly for optimization purposes, but be careful of premature
optimization as partial objects lead to potentially more fragile
code.

View File

@@ -1,97 +1,20 @@
PHP Mapping
===========
Doctrine ORM also allows you to provide the ORM metadata in the form
of plain PHP code using the ``ClassMetadata`` API. You can write
the code in PHP files or inside of a static function named
``loadMetadata($class)`` on the entity class itself.
PHP Files
---------
.. note::
PHPDriver is deprecated and will be removed in 3.0, use StaticPHPDriver
instead.
If you wish to write your mapping information inside PHP files that
are named after the entity and included to populate the metadata
for an entity you can do so by using the ``PHPDriver``:
.. code-block:: php
<?php
$driver = new PHPDriver('/path/to/php/mapping/files');
$em->getConfiguration()->setMetadataDriverImpl($driver);
Now imagine we had an entity named ``Entities\User`` and we wanted
to write a mapping file for it using the above configured
``PHPDriver`` instance:
.. code-block:: php
<?php
namespace Entities;
class User
{
private $id;
private $username;
}
To write the mapping information you just need to create a file
named ``Entities.User.php`` inside of the
``/path/to/php/mapping/files`` folder:
.. code-block:: php
<?php
// /path/to/php/mapping/files/Entities.User.php
$metadata->mapField(array(
'id' => true,
'fieldName' => 'id',
'type' => 'integer'
));
$metadata->mapField(array(
'fieldName' => 'username',
'type' => 'string',
'options' => array(
'fixed' => true,
'comment' => "User's login name"
)
));
$metadata->mapField(array(
'fieldName' => 'login_count',
'type' => 'integer',
'nullable' => false,
'options' => array(
'unsigned' => true,
'default' => 0
)
));
Now we can easily retrieve the populated ``ClassMetadata`` instance
where the ``PHPDriver`` includes the file and the
``ClassMetadataFactory`` caches it for later retrieval:
.. code-block:: php
<?php
$class = $em->getClassMetadata('Entities\User');
// or
$class = $em->getMetadataFactory()->getMetadataFor('Entities\User');
Doctrine ORM also allows you to provide the ORM metadata in the form of plain
PHP code using the ``ClassMetadata`` API. You can write the code in inside of a
static function named ``loadMetadata($class)`` on the entity class itself.
Static Function
---------------
In addition to the PHP files you can also specify your mapping
information inside of a static function defined on the entity class
itself. This is useful for cases where you want to keep your entity
and mapping information together but don't want to use attributes or
annotations. For this you just need to use the ``StaticPHPDriver``:
In addition to other drivers using configuration languages you can also
programatically specify your mapping information inside of a static function
defined on the entity class itself.
This is useful for cases where you want to keep your entity and mapping
information together but don't want to use attributes. For this you just
need to use the ``StaticPHPDriver``:
.. code-block:: php
@@ -164,13 +87,11 @@ The API of the ClassMetadataBuilder has the following methods with a fluent inte
- ``setTable($name)``
- ``addIndex(array $columns, $indexName)``
- ``addUniqueConstraint(array $columns, $constraintName)``
- ``addNamedQuery($name, $dqlQuery)``
- ``setJoinedTableInheritance()``
- ``setSingleTableInheritance()``
- ``setDiscriminatorColumn($name, $type = 'string', $length = 255, $columnDefinition = null, $enumType = null)``
- ``setDiscriminatorColumn($name, $type = 'string', $length = 255, $columnDefinition = null, $enumType = null, $options = [])``
- ``addDiscriminatorMapClass($name, $class)``
- ``setChangeTrackingPolicyDeferredExplicit()``
- ``setChangeTrackingPolicyNotify()``
- ``addLifecycleEvent($methodName, $event)``
- ``addManyToOne($name, $targetEntity, $inversedBy = null)``
- ``addInverseOneToOne($name, $targetEntity, $mappedBy)``
@@ -272,7 +193,6 @@ Inheritance Getters
- ``isInheritanceTypeNone()``
- ``isInheritanceTypeJoined()``
- ``isInheritanceTypeSingleTable()``
- ``isInheritanceTypeTablePerClass()``
- ``isInheritedField($fieldName)``
- ``isInheritedAssociation($fieldName)``
@@ -282,7 +202,6 @@ Change Tracking Getters
- ``isChangeTrackingDeferredExplicit()``
- ``isChangeTrackingDeferredImplicit()``
- ``isChangeTrackingNotify()``
Field & Association Getters
~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -253,7 +253,7 @@ Calling ``setParameter()`` automatically infers which type you are setting as
value. This works for integers, arrays of strings/integers, DateTime instances
and for managed entities. If you want to set a type explicitly you can call
the third argument to ``setParameter()`` explicitly. It accepts either a DBAL
Doctrine\DBAL\ParameterType::* or a DBAL Type name for conversion.
``Doctrine\DBAL\ParameterType::*`` or a DBAL Type name for conversion.
.. note::
@@ -578,8 +578,6 @@ of DQL. It takes 3 parameters: ``$dqlPartName``, ``$dqlPart`` and
not (no effect on the ``where`` and ``having`` DQL query parts,
which always override all previously defined items)
-
.. code-block:: php
<?php

View File

@@ -295,34 +295,13 @@ level cache region.
// other properties and methods
}
.. code-block:: annotation
<?php
/**
* @Entity
* @Cache("NONSTRICT_READ_WRITE")
*/
class State
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
protected int|null $id = null;
/**
* @Column(unique=true)
*/
protected string $name;
// other properties and methods
}
.. code-block:: xml
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://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">
<cache usage="READ_ONLY" region="my_entity_region" />
<id name="id" type="integer" column="id">
@@ -332,24 +311,6 @@ level cache region.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Country:
type: entity
cache:
usage: READ_ONLY
region: my_entity_region
id:
id:
type: integer
id: true
generator:
strategy: IDENTITY
fields:
name:
type: string
Association cache definition
----------------------------
The most common use case is to cache entities. But we can also cache relationships.
@@ -386,48 +347,13 @@ It caches the primary keys of association and cache each element will be cached
// other properties and methods
}
.. code-block:: annotation
<?php
/**
* @Entity
* @Cache("NONSTRICT_READ_WRITE")
*/
class State
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
protected int|null $id = null;
/**
* @Column(unique=true)
*/
protected string $name;
/**
* @Cache("NONSTRICT_READ_WRITE")
* @ManyToOne(targetEntity="Country")
* @JoinColumn(name="country_id", referencedColumnName="id")
*/
protected Country|null $country;
/**
* @Cache("NONSTRICT_READ_WRITE")
* @OneToMany(targetEntity="City", mappedBy="state")
* @var Collection<int, City>
*/
protected Collection $cities;
// other properties and methods
}
.. code-block:: xml
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://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">
<cache usage="NONSTRICT_READ_WRITE" />
@@ -452,38 +378,6 @@ It caches the primary keys of association and cache each element will be cached
</entity>
</doctrine-mapping>
.. code-block:: yaml
State:
type: entity
cache:
usage: NONSTRICT_READ_WRITE
id:
id:
type: integer
id: true
generator:
strategy: IDENTITY
fields:
name:
type: string
manyToOne:
state:
targetEntity: Country
joinColumns:
country_id:
referencedColumnName: id
cache:
usage: NONSTRICT_READ_WRITE
oneToMany:
cities:
targetEntity:City
mappedBy: state
cache:
usage: NONSTRICT_READ_WRITE
.. note::
for this to work, the target entity must also be marked as cacheable.

View File

@@ -12,9 +12,8 @@ page only handles Security issues in the ORM.
- `DBAL Security Page <https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/security.html>`
If you find a Security bug in Doctrine, please report it on Jira and change the
Security Level to "Security Issues". It will be visible to Doctrine Core
developers and you only.
If you find a Security bug in Doctrine, please follow our
`Security reporting guidelines <https://www.doctrine-project.org/policies/security.html#reporting>`_.
User input and Doctrine ORM
---------------------------

View File

@@ -83,18 +83,8 @@ The following Commands are currently available:
cache drivers.
- ``orm:clear-cache:result`` Clear result cache of the various
cache drivers.
- ``orm:convert-d1-schema`` Converts Doctrine 1.X schema into a
Doctrine 2.X schema.
- ``orm:convert-mapping`` Convert mapping information between
supported formats.
- ``orm:ensure-production-settings`` Verify that Doctrine is
properly configured for a production environment.
- ``orm:generate-entities`` Generate entity classes and method
stubs from your mapping information.
- ``orm:generate-proxies`` Generates proxy classes for entity
classes.
- ``orm:generate-repositories`` Generate repository classes from
your mapping information.
- ``orm:run-dql`` Executes arbitrary DQL directly from the command
line.
- ``orm:schema-tool:create`` Processes the schema and either
@@ -107,14 +97,10 @@ The following Commands are currently available:
update the database schema of EntityManager Storage Connection or
generate the SQL output.
For these commands are also available aliases:
The following alias is defined:
- ``orm:convert:d1-schema`` is alias for ``orm:convert-d1-schema``.
- ``orm:convert:mapping`` is alias for ``orm:convert-mapping``.
- ``orm:generate:entities`` is alias for ``orm:generate-entities``.
- ``orm:generate:proxies`` is alias for ``orm:generate-proxies``.
- ``orm:generate:repositories`` is alias for ``orm:generate-repositories``.
.. note::
@@ -225,163 +211,6 @@ will output the SQL for the ran operation.
$ php bin/doctrine orm:schema-tool:create --dump-sql
Entity Generation
-----------------
Generate entity classes and method stubs from your mapping information.
.. code-block:: php
$ php bin/doctrine orm:generate-entities
$ php bin/doctrine orm:generate-entities --update-entities
$ php bin/doctrine orm:generate-entities --regenerate-entities
This command is not suited for constant usage. It is a little helper and does
not support all the mapping edge cases very well. You still have to put work
in your entities after using this command.
It is possible to use the EntityGenerator on code that you have already written. It will
not be lost. The EntityGenerator will only append new code to your
file and will not delete the old code. However this approach may still be prone
to error and we suggest you use code repositories such as GIT or SVN to make
backups of your code.
It makes sense to generate the entity code if you are using entities as Data
Access Objects only and don't put much additional logic on them. If you are
however putting much more logic on the entities you should refrain from using
the entity-generator and code your entities manually.
.. note::
Even if you specified Inheritance options in your
XML or YAML Mapping files the generator cannot generate the base and
child classes for you correctly, because it doesn't know which
class is supposed to extend which. You have to adjust the entity
code manually for inheritance to work!
Convert Mapping Information
---------------------------
Convert mapping information between supported formats.
This is an **execute one-time** command. It should not be necessary for
you to call this method multiple times, especially when using the ``--from-database``
flag.
Converting an existing database schema into mapping files only solves about 70-80%
of the necessary mapping information. Additionally the detection from an existing
database cannot detect inverse associations, inheritance types,
entities with foreign keys as primary keys and many of the
semantical operations on associations such as cascade.
.. note::
There is no need to convert YAML or XML mapping files to annotations
every time you make changes. All mapping drivers are first class citizens
in Doctrine 2 and can be used as runtime mapping for the ORM. See the
docs on XML and YAML Mapping for an example how to register this metadata
drivers as primary mapping source.
To convert some mapping information between the various supported
formats you can use the ``ClassMetadataExporter`` to get exporter
instances for the different formats:
.. code-block:: php
<?php
$cme = new \Doctrine\ORM\Tools\Export\ClassMetadataExporter();
Once you have a instance you can use it to get an exporter. For
example, the yml exporter:
.. code-block:: php
<?php
$exporter = $cme->getExporter('yml', '/path/to/export/yml');
Now you can export some ``ClassMetadata`` instances:
.. code-block:: php
<?php
$classes = array(
$em->getClassMetadata('Entities\User'),
$em->getClassMetadata('Entities\Profile')
);
$exporter->setMetadata($classes);
$exporter->export();
This functionality is also available from the command line to
convert your loaded mapping information to another format. The
``orm:convert-mapping`` command accepts two arguments, the type to
convert to and the path to generate it:
.. code-block:: php
$ php bin/doctrine orm:convert-mapping xml /path/to/mapping-path-converted-to-xml
Reverse Engineering
-------------------
You can use the ``DatabaseDriver`` to reverse engineer a database to an
array of ``ClassMetadata`` instances and generate YAML, XML, etc. from
them.
.. note::
Reverse Engineering is a **one-time** process that can get you started with a project.
Converting an existing database schema into mapping files only detects about 70-80%
of the necessary mapping information. Additionally the detection from an existing
database cannot detect inverse associations, inheritance types,
entities with foreign keys as primary keys and many of the
semantical operations on associations such as cascade.
First you need to retrieve the metadata instances with the
``DatabaseDriver``:
.. code-block:: php
<?php
$em->getConfiguration()->setMetadataDriverImpl(
new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
$em->getConnection()->getSchemaManager()
)
);
$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);
$metadata = $cmf->getAllMetadata();
Now you can get an exporter instance and export the loaded metadata
to yml:
.. code-block:: php
<?php
$cme = new \Doctrine\ORM\Tools\Export\ClassMetadataExporter();
$exporter = $cme->getExporter('yml', '/path/to/export/yml');
$exporter->setMetadata($metadata);
$exporter->export();
You can also reverse engineer a database using the
``orm:convert-mapping`` command:
.. code-block:: php
$ php bin/doctrine orm:convert-mapping --from-database yml /path/to/mapping-path-converted-to-yml
.. note::
Reverse Engineering is not always working perfectly
depending on special cases. It will only detect Many-To-One
relations (even if they are One-To-One) and will try to create
entities from Many-To-Many tables. It also has problems with naming
of foreign keys that have multiple column names. Any Reverse
Engineered Database-Schema needs considerable manual work to become
a useful domain model.
Runtime vs Development Mapping Validation
-----------------------------------------

View File

@@ -200,17 +200,6 @@ example we'll use an integer.
// ...
}
.. code-block:: annotation
<?php
class User
{
// ...
/** @Version @Column(type="integer") */
private int $version;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -219,15 +208,6 @@ example we'll use an integer.
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
fields:
version:
type: integer
version: true
Alternatively a datetime type can be used (which maps to a SQL
timestamp or datetime):
@@ -244,17 +224,6 @@ timestamp or datetime):
// ...
}
.. code-block:: annotation
<?php
class User
{
// ...
/** @Version @Column(type="datetime") */
private DateTime $version;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -263,15 +232,6 @@ timestamp or datetime):
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
fields:
version:
type: datetime
version: true
Version numbers (not timestamps) should however be preferred as
they can not potentially conflict in a highly concurrent
environment, unlike timestamps where this is a possibility,

View File

@@ -47,21 +47,6 @@ Then, an entity using the ``CustomIdObject`` typed field will be correctly assig
// ...
}
.. code-block:: annotation
<?php
/**
* @Entity
* @Table(name="cms_users_typed_with_custom_typed_field")
*/
class UserTypedWithCustomTypedField
{
/** @Column */
public CustomIdObject $customId;
// ...
}
.. code-block:: xml
<doctrine-mapping>
@@ -153,7 +138,7 @@ You need to create a class which implements ``Doctrine\ORM\Mapping\TypedFieldMap
final class CustomEnumTypedFieldMapper implements TypedFieldMapper
{
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function validateAndComplete(array $mapping, ReflectionProperty $field): array
{
@@ -176,4 +161,4 @@ You need to create a class which implements ``Doctrine\ORM\Mapping\TypedFieldMap
Note that this case checks whether the mapping is already assigned, and if yes, it skips it. This is up to your
implementation. You can make a "greedy" mapper which will always override the mapping with its own type, or one
that behaves like the ``DefaultTypedFieldMapper`` and does not modify the type once its set prior in the chain.
that behaves like the ``DefaultTypedFieldMapper`` and does not modify the type once its set prior in the chain.

View File

@@ -37,8 +37,8 @@ will still end up with the same reference:
public function testIdentityMapReference(): void
{
$objectA = $this->entityManager->getReference('EntityName', 1);
// check for proxyinterface
$this->assertInstanceOf('Doctrine\Persistence\Proxy', $objectA);
// check entity is not initialized
$this->assertTrue($this->entityManager->isUninitializedObject($objectA));
$objectB = $this->entityManager->find('EntityName', 1);
@@ -129,16 +129,10 @@ optimize the performance of the Flush Operation:
- Temporarily mark entities as read only. If you have a very large UnitOfWork
but know that a large set of entities has not changed, just mark them as read
only with ``$entityManager->getUnitOfWork()->markReadOnly($entity)``.
- Flush only a single entity with ``$entityManager->flush($entity)``.
- Use :doc:`Change Tracking Policies <change-tracking-policies>` to use more
explicit strategies of notifying the UnitOfWork what objects/properties
changed.
.. note::
Flush only a single entity with ``$entityManager->flush($entity)`` is deprecated and will be removed in ORM 3.0.
(`Details <https://github.com/doctrine/orm/issues/8459>`_)
Query Internals
---------------

View File

@@ -415,7 +415,7 @@ Transitive persistence / Cascade Operations
Doctrine ORM provides a mechanism for transitive persistence through cascading of certain operations.
Each association to another entity or a collection of
entities can be configured to automatically cascade the following operations to the associated entities:
``persist``, ``remove``, ``merge``, ``detach``, ``refresh`` or ``all``.
``persist``, ``remove``, ``detach``, ``refresh`` or ``all``.
The main use case for ``cascade: persist`` is to avoid "exposing" associated entities to your PHP application.
Continuing with the User-Comment example of this chapter, this is how the creation of a new user and a new
@@ -718,6 +718,7 @@ methods:
* ``andX($arg1, $arg2, ...)``
* ``orX($arg1, $arg2, ...)``
* ``not($expression)``
* ``eq($field, $value)``
* ``gt($field, $value)``
* ``lt($field, $value)``

View File

@@ -192,6 +192,11 @@ be properly synchronized with the database when
database in the most efficient way and a single, short transaction,
taking care of maintaining referential integrity.
.. note::
Do not make any assumptions in your code about the number of queries
it takes to flush changes, about the ordering of ``INSERT``, ``UPDATE``
and ``DELETE`` queries or the order in which entities will be processed.
Example:
@@ -286,17 +291,53 @@ as follows:
After an entity has been removed, its in-memory state is the same as
before the removal, except for generated identifiers.
Removing an entity will also automatically delete any existing
records in many-to-many join tables that link this entity. The
action taken depends on the value of the ``@joinColumn`` mapping
attribute "onDelete". Either Doctrine issues a dedicated ``DELETE``
statement for records of each join table or it depends on the
foreign key semantics of onDelete="CASCADE".
During the ``EntityManager#flush()`` operation, the removed entity
will also be removed from all collections in entities currently
loaded into memory.
.. _remove_object_many_to_many_join_tables:
Join-table management when removing from many-to-many collections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Regarding existing rows in many-to-many join tables that refer to
an entity being removed, the following applies.
When the entity being removed does not declare the many-to-many association
itself (that is, the many-to-many association is unidirectional and
the entity is on the inverse side), the ORM has no reasonable way to
detect associations targeting the entity's class. Thus, no ORM-level handling
of join-table rows is attempted and database-level constraints apply.
In case of database-level ``ON DELETE RESTRICT`` constraints, the
``EntityManager#flush()`` operation may abort and a ``ConstraintViolationException``
may be thrown. No in-memory collections will be modified in this case.
With ``ON DELETE CASCADE``, the RDBMS will take care of removing rows
from join tables.
When the entity being removed is part of bi-directional many-to-many
association, either as the owning or inverse side, the ORM will
delete rows from join tables before removing the entity itself. That means
database-level ``ON DELETE RESTRICT`` constraints on join tables are not
effective, since the join table rows are removed first. Removal of join table
rows happens through specialized methods in entity and collection persister
classes and take one query per entity and join table. In case the association
uses a ``@JoinColumn`` configuration with ``onDelete="CASCADE"``, instead
of using a dedicated ``DELETE`` query the database-level operation will be
relied upon.
.. note::
In case you rely on database-level ``ON DELETE RESTRICT`` constraints,
be aware that by making many-to-many associations bidirectional the
assumed protection may be lost.
Performance of different deletion strategies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Deleting an object with all its associated objects can be achieved
in multiple ways with very different performance impacts.
1. If an association is marked as ``CASCADE=REMOVE`` Doctrine ORM
will fetch this association. If its a Single association it will
pass this entity to
@@ -372,77 +413,6 @@ automatically without invoking the ``detach`` method:
The ``detach`` operation is usually not as frequently needed and
used as ``persist`` and ``remove``.
Merging entities
----------------
Merging entities refers to the merging of (usually detached)
entities into the context of an EntityManager so that they become
managed again. To merge the state of an entity into an
EntityManager use the ``EntityManager#merge($entity)`` method. The
state of the passed entity will be merged into a managed copy of
this entity and this copy will subsequently be returned.
Example:
.. code-block:: php
<?php
$detachedEntity = unserialize($serializedEntity); // some detached entity
$entity = $em->merge($detachedEntity);
// $entity now refers to the fully managed copy returned by the merge operation.
// The EntityManager $em now manages the persistence of $entity as usual.
The semantics of the merge operation, applied to an entity X, are
as follows:
- If X is a detached entity, the state of X is copied onto a
pre-existing managed entity instance X' of the same identity.
- If X is a new entity instance, a new managed copy X' will be
created and the state of X is copied onto this managed instance.
- If X is a removed entity instance, an InvalidArgumentException
will be thrown.
- If X is a managed entity, it is ignored by the merge operation,
however, the merge operation is cascaded to entities referenced by
relationships from X if these relationships have been mapped with
the cascade element value MERGE or ALL (see ":ref:`transitive-persistence`").
- For all entities Y referenced by relationships from X having the
cascade element value MERGE or ALL, Y is merged recursively as Y'.
For all such Y referenced by X, X' is set to reference Y'. (Note
that if X is managed then X is the same object as X'.)
- If X is an entity merged to X', with a reference to another
entity Y, where cascade=MERGE or cascade=ALL is not specified, then
navigation of the same association from X' yields a reference to a
managed object Y' with the same persistent identity as Y.
The ``merge`` operation will throw an ``OptimisticLockException``
if the entity being merged uses optimistic locking through a
version field and the versions of the entity being merged and the
managed copy don't match. This usually means that the entity has
been modified while being detached.
The ``merge`` operation is usually not as frequently needed and
used as ``persist`` and ``remove``. The most common scenario for
the ``merge`` operation is to reattach entities to an EntityManager
that come from some cache (and are therefore detached) and you want
to modify and persist such an entity.
.. warning::
If you need to perform multiple merges of entities that share certain subparts
of their object-graphs and cascade merge, then you have to call ``EntityManager#clear()`` between the
successive calls to ``EntityManager#merge()``. Otherwise you might end up with
multiple copies of the "same" object in the database, however with different ids.
.. note::
If you load some detached entities from a cache and you do
not need to persist or delete them or otherwise make use of them
without the need for persistence services there is no need to use
``merge``. I.e. you can simply pass detached objects from a cache
directly to the view.
Synchronization with the Database
---------------------------------
@@ -553,7 +523,7 @@ during development.
.. note::
Do not invoke ``flush`` after every change to an entity
or every single invocation of persist/remove/merge/... This is an
or every single invocation of persist/remove/... This is an
anti-pattern and unnecessarily reduces the performance of your
application. Instead, form units of work that operate on your
objects and call ``flush`` when you are done. While serving a
@@ -741,6 +711,23 @@ and these associations are mapped as EAGER, they will automatically
be loaded together with the entity being queried and is thus
immediately available to your application.
Eager Loading can also be configured at runtime through
``AbstractQuery::setFetchMode`` in DQL or Native Queries.
Eager loading for many-to-one and one-to-one associations is using either a
LEFT JOIN or a second query for fetching the related entity eagerly.
Eager loading for many-to-one associations uses a second query to load
the collections for several entities at the same time.
When many-to-many, one-to-one or one-to-many associations are eagerly loaded,
then the global batch size configuration is used to avoid IN(?) queries with
too many arguments. The default batch size is 100 and can be changed with
``Configuration::setEagerFetchBatchSize()``.
For eagerly loaded Many-To-Many associations one query has to be made for each
collection.
By Lazy Loading
~~~~~~~~~~~~~~~
@@ -804,7 +791,7 @@ By default the EntityManager returns a default implementation of
``Doctrine\ORM\EntityRepository`` when you call
``EntityManager#getRepository($entityClass)``. You can overwrite
this behaviour by specifying the class name of your own Entity
Repository in the Attribute, Annotation, XML or YAML metadata. In large
Repository in the Attribute or XML metadata. In large
applications that require lots of specialized DQL queries using a
custom repository is one recommended way of grouping these queries
in a central location.

View File

@@ -2,7 +2,8 @@ XML Mapping
===========
The XML mapping driver enables you to provide the ORM metadata in
form of XML documents.
form of XML documents. It requires the ``dom`` extension in order to be
able to validate your mapping documents against its XML Schema.
The XML driver is backed by an XML Schema document that describes
the structure of a mapping document. The most recent version of the
@@ -16,9 +17,9 @@ setup for the latest code in trunk.
.. code-block:: xml
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
...
@@ -102,9 +103,9 @@ of several common elements:
// Doctrine.Tests.ORM.Mapping.User.dcm.xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
@@ -691,7 +692,6 @@ specified by their respective tags:
- ``<cascade-persist />``
- ``<cascade-merge />``
- ``<cascade-remove />``
- ``<cascade-refresh />``
- ``<cascade-detach />``
@@ -769,9 +769,9 @@ entity relationship. You can define this in XML with the "association-key" attri
.. code-block:: xml
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Application\Model\ArticleAttribute">

View File

@@ -1,158 +0,0 @@
YAML Mapping
============
.. warning::
The YAML driver is deprecated and will be removed in version 3.0.
It is strongly recommended to switch to one of the other mappings.
The YAML mapping driver enables you to provide the ORM metadata in
form of YAML documents.
The YAML mapping document of a class is loaded on-demand the first
time it is requested and subsequently stored in the metadata cache.
In order to work, this requires certain conventions:
- Each entity/mapped superclass must get its own dedicated YAML
mapping document.
- The name of the mapping document must consist of the fully
qualified name of the class, where namespace separators are
replaced by dots (.).
- All mapping documents should get the extension ".dcm.yml" to
identify it as a Doctrine mapping file. This is more of a
convention and you are not forced to do this. You can change the
file extension easily enough.
.. code-block:: php
<?php
$driver->setFileExtension('.yml');
It is recommended to put all YAML mapping documents in a single
folder but you can spread the documents over several folders if you
want to. In order to tell the YamlDriver where to look for your
mapping documents, supply an array of paths as the first argument
of the constructor, like this:
.. code-block:: php
<?php
use Doctrine\ORM\Mapping\Driver\YamlDriver;
// $config instanceof Doctrine\ORM\Configuration
$driver = new YamlDriver(array('/path/to/files'));
$config->setMetadataDriverImpl($driver);
Simplified YAML Driver
~~~~~~~~~~~~~~~~~~~~~~
The Symfony project sponsored a driver that simplifies usage of the YAML Driver.
The changes between the original driver are:
- File Extension is .orm.yml
- Filenames are shortened, "MyProject\\Entities\\User" will become User.orm.yml
- You can add a global file and add multiple entities in this file.
Configuration of this client works a little bit different:
.. code-block:: php
<?php
$namespaces = array(
'/path/to/files1' => 'MyProject\Entities',
'/path/to/files2' => 'OtherProject\Entities'
);
$driver = new \Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver($namespaces);
$driver->setGlobalBasename('global'); // global.orm.yml
Example
-------
As a quick start, here is a small example document that makes use
of several common elements:
.. code-block:: yaml
# Doctrine.Tests.ORM.Mapping.User.dcm.yml
Doctrine\Tests\ORM\Mapping\User:
type: entity
repositoryClass: Doctrine\Tests\ORM\Mapping\UserRepository
table: cms_users
schema: schema_name # The schema the table lies in, for platforms that support schemas (Optional, >= 2.5)
readOnly: true
indexes:
name_index:
columns: [ name ]
id:
id:
type: integer
generator:
strategy: AUTO
fields:
name:
type: string
length: 50
email:
type: string
length: 32
column: user_email
unique: true
options:
fixed: true
comment: User's email address
loginCount:
type: integer
column: login_count
nullable: false
options:
unsigned: true
default: 0
oneToOne:
address:
targetEntity: Address
joinColumn:
name: address_id
referencedColumnName: id
onDelete: CASCADE
oneToMany:
phonenumbers:
targetEntity: Phonenumber
mappedBy: user
cascade: ["persist", "merge"]
manyToMany:
groups:
targetEntity: Group
joinTable:
name: cms_users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
lifecycleCallbacks:
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
postPersist: [ doStuffOnPostPersist ]
Be aware that class-names specified in the YAML files should be
fully qualified.
Reference
~~~~~~~~~~~~~~~~~~~~~~
Unique Constraints
------------------
It is possible to define unique constraints by the following declaration:
.. code-block:: yaml
# ECommerceProduct.orm.yml
ECommerceProduct:
type: entity
fields:
# definition of some fields
uniqueConstraints:
search_idx:
columns: [ name, email ]

View File

@@ -31,6 +31,7 @@
reference/inheritance-mapping
reference/working-with-objects
reference/working-with-associations
reference/typedfieldmapper
reference/events
reference/unitofwork
reference/unitofwork-associations
@@ -40,11 +41,8 @@
reference/query-builder
reference/native-sql
reference/change-tracking-policies
reference/partial-objects
reference/annotations-reference
reference/attributes-reference
reference/xml-mapping
reference/yaml-mapping
reference/php-mapping
reference/caching
reference/improving-performance
@@ -72,7 +70,6 @@
cookbook/dql-custom-walkers
cookbook/dql-user-defined-functions
cookbook/implementing-arrayaccess-for-domain-objects
cookbook/implementing-the-notify-changetracking-policy
cookbook/resolve-target-entity-listener
cookbook/sql-table-prefixes
cookbook/strategy-cookbook-introduction

View File

@@ -1,86 +0,0 @@
Welcome to Doctrine 2 ORM's documentation!
==========================================
Tutorials
---------
.. toctree::
:maxdepth: 1
tutorials/getting-started
tutorials/getting-started-database
tutorials/getting-started-models
tutorials/working-with-indexed-associations
tutorials/extra-lazy-associations
tutorials/composite-primary-keys
tutorials/ordered-associations
tutorials/override-field-association-mappings-in-subclasses
tutorials/pagination.rst
tutorials/embeddables.rst
Reference Guide
---------------
.. toctree::
:maxdepth: 1
:numbered:
reference/architecture
reference/configuration.rst
reference/faq
reference/basic-mapping
reference/association-mapping
reference/inheritance-mapping
reference/working-with-objects
reference/working-with-associations
reference/events
reference/unitofwork
reference/unitofwork-associations
reference/transactions-and-concurrency
reference/batch-processing
reference/dql-doctrine-query-language
reference/query-builder
reference/native-sql
reference/change-tracking-policies
reference/partial-objects
reference/annotations-reference
reference/attributes-reference
reference/xml-mapping
reference/yaml-mapping
reference/php-mapping
reference/caching
reference/improving-performance
reference/tools
reference/metadata-drivers
reference/best-practices
reference/limitations-and-known-issues
tutorials/pagination
reference/filters
reference/namingstrategy
reference/advanced-configuration
reference/second-level-cache
reference/security
Cookbook
--------
.. toctree::
:maxdepth: 1
cookbook/aggregate-fields
cookbook/custom-mapping-types
cookbook/decorator-pattern
cookbook/dql-custom-walkers
cookbook/dql-user-defined-functions
cookbook/implementing-arrayaccess-for-domain-objects
cookbook/implementing-the-notify-changetracking-policy
cookbook/resolve-target-entity-listener
cookbook/sql-table-prefixes
cookbook/strategy-cookbook-introduction
cookbook/validation-of-entities
cookbook/working-with-datetime
cookbook/mysql-enums
cookbook/advanced-field-value-conversion-using-custom-mapping-types
cookbook/entities-in-session

View File

@@ -50,44 +50,12 @@ and year of production as primary keys:
}
}
.. code-block:: annotation
<?php
namespace VehicleCatalogue\Model;
/**
* @Entity
*/
class Car
{
/** @Id @Column(type="string") */
private string $name;
/** @Id @Column(type="integer") */
private int $year;
public function __construct($name, $year)
{
$this->name = $name;
$this->year = $year;
}
public function getModelName(): string
{
return $this->name;
}
public function getYearOfProduction(): int
{
return $this->year;
}
}
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="VehicleCatalogue\Model\Car">
@@ -96,16 +64,6 @@ and year of production as primary keys:
</entity>
</doctrine-mapping>
.. code-block:: yaml
VehicleCatalogue\Model\Car:
type: entity
id:
name:
type: string
year:
type: integer
Now you can use this entity:
.. code-block:: php
@@ -160,7 +118,6 @@ The semantics of mapping identity through foreign entities are easy:
- Only allowed on Many-To-One or One-To-One associations.
- Plug an ``#[Id]`` attribute onto every association.
- Set an attribute ``association-key`` with the field name of the association in XML.
- Set a key ``associationKey:`` with the field name of the association in YAML.
Use-Case 1: Dynamic Attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -214,62 +171,11 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
}
}
.. code-block:: annotation
<?php
namespace Application\Model;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity
*/
class Article
{
/** @Id @Column(type="integer") @GeneratedValue */
private int|null $id = null;
/** @Column(type="string") */
private string $title;
/**
* @OneToMany(targetEntity="ArticleAttribute", mappedBy="article", cascade={"ALL"}, indexBy="attribute")
* @var Collection<int, ArticleAttribute>
*/
private Collection $attributes;
public function addAttribute($name, $value): void
{
$this->attributes[$name] = new ArticleAttribute($name, $value, $this);
}
}
/**
* @Entity
*/
class ArticleAttribute
{
/** @Id @ManyToOne(targetEntity="Article", inversedBy="attributes") */
private Article|null $article;
/** @Id @Column(type="string") */
private string $attribute;
/** @Column(type="string") */
private string $value;
public function __construct($name, $value, $article)
{
$this->attribute = $name;
$this->value = $value;
$this->article = $article;
}
}
.. code-block:: xml
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Application\Model\ArticleAttribute">
@@ -283,24 +189,6 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
</doctrine-mapping>
.. code-block:: yaml
Application\Model\ArticleAttribute:
type: entity
id:
article:
associationKey: true
attribute:
type: string
fields:
value:
type: string
manyToOne:
article:
targetEntity: Article
inversedBy: attributes
Use-Case 2: Simple Derived Identity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -328,26 +216,6 @@ One good example for this is a user-address relationship:
private User|null $user = null;
}
.. code-block:: yaml
User:
type: entity
id:
id:
type: integer
generator:
strategy: AUTO
Address:
type: entity
id:
user:
associationKey: true
oneToOne:
user:
targetEntity: User
Use-Case 3: Join-Table with Metadata
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -44,33 +44,6 @@ instead of simply adding the respective columns to the ``User`` class.
private string $country;
}
.. code-block:: annotation
<?php
/** @Entity */
class User
{
/** @Embedded(class = "Address") */
private Address $address;
}
/** @Embeddable */
class Address
{
/** @Column(type = "string") */
private string $street;
/** @Column(type = "string") */
private string $postalCode;
/** @Column(type = "string") */
private string $city;
/** @Column(type = "string") */
private string $country;
}
.. code-block:: xml
<doctrine-mapping>
@@ -86,22 +59,6 @@ instead of simply adding the respective columns to the ``User`` class.
</embeddable>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
embedded:
address:
class: Address
Address:
type: embeddable
fields:
street: { type: string }
postalCode: { type: string }
city: { type: string }
country: { type: string }
In terms of your database schema, Doctrine will automatically inline all
columns from the ``Address`` class into the table of the ``User`` class,
just as if you had declared them directly there.
@@ -147,32 +104,12 @@ The following example shows you how to set your prefix to ``myPrefix_``:
private Address $address;
}
.. code-block:: annotation
<?php
/** @Entity */
class User
{
/** @Embedded(class = "Address", columnPrefix = "myPrefix_") */
private $address;
}
.. code-block:: xml
<entity name="User">
<embedded name="address" class="Address" column-prefix="myPrefix_" />
</entity>
.. code-block:: yaml
User:
type: entity
embedded:
address:
class: Address
columnPrefix: myPrefix_
To have Doctrine drop the prefix and use the value object's property name
directly, set ``columnPrefix=false`` (``use-column-prefix="false"`` for XML):
@@ -189,32 +126,12 @@ directly, set ``columnPrefix=false`` (``use-column-prefix="false"`` for XML):
private Address $address;
}
.. code-block:: annotation
<?php
/** @Entity */
class User
{
/** @Embedded(class = "Address", columnPrefix = false) */
private Address $address;
}
.. code-block:: xml
<entity name="User">
<embedded name="address" class="Address" use-column-prefix="false" />
</entity>
.. code-block:: yaml
User:
type: entity
embedded:
address:
class: Address
columnPrefix: false
DQL
---

View File

@@ -65,29 +65,12 @@ switch to extra lazy as shown in these examples:
public Collection $users;
}
.. code-block:: annotation
<?php
namespace Doctrine\Tests\Models\CMS;
/**
* @Entity
*/
class CmsGroup
{
/**
* @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
* @var Collection<int, CmsUser>
*/
public Collection $users;
}
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\CMS\CmsGroup">
@@ -95,14 +78,3 @@ switch to extra lazy as shown in these examples:
<many-to-many field="users" target-entity="CmsUser" mapped-by="groups" fetch="EXTRA_LAZY" />
</entity>
</doctrine-mapping>
.. code-block:: yaml
Doctrine\Tests\Models\CMS\CmsGroup:
type: entity
# ...
manyToMany:
users:
targetEntity: CmsUser
mappedBy: groups
fetch: EXTRA_LAZY

View File

@@ -22,5 +22,5 @@ In this workflow you would modify the database schema first and then
regenerate the PHP code to use with this schema. You need a flexible
code-generator for this task.
We spinned off a subproject, Doctrine CodeGenerator, that will fill this gap and
We spun off a subproject, Doctrine CodeGenerator, that will fill this gap and
allow you to do *Database First* development.

View File

@@ -18,7 +18,7 @@ before. There are some prerequisites for the tutorial that have to be
installed:
- PHP (latest stable version)
- Composer Package Manager (`Install Composer
- Composer Package Manager (\ `Install Composer
<https://getcomposer.org/doc/00-intro.md>`_)
The code of this tutorial is `available on Github <https://github.com/doctrine/doctrine2-orm-tutorial>`_.
@@ -27,7 +27,7 @@ What is Doctrine?
-----------------
Doctrine ORM is an `object-relational mapper (ORM) <https://en.wikipedia.org/wiki/Object-relational_mapping>`_
for PHP 7.1+ that provides transparent persistence for PHP objects. It uses the Data Mapper
for PHP that provides transparent persistence for PHP objects. It uses the Data Mapper
pattern at the heart, aiming for a complete separation of your domain/business
logic from the persistence in a relational database management system.
@@ -82,10 +82,9 @@ that directory with the following contents:
{
"require": {
"doctrine/orm": "^2.11.0",
"doctrine/dbal": "^3.2",
"symfony/yaml": "^5.4",
"symfony/cache": "^5.4"
"doctrine/orm": "^3",
"doctrine/dbal": "^4",
"symfony/cache": "^7"
},
"autoload": {
"psr-0": {"": "src/"}
@@ -102,18 +101,13 @@ Install Doctrine using the Composer Dependency Management tool, by calling:
This will install the packages Doctrine Common, Doctrine DBAL, Doctrine ORM,
into the ``vendor`` directory.
Add the following directories:
::
Add the following directories::
doctrine2-tutorial
|-- config
| `-- xml
| `-- yaml
`-- src
.. note::
The YAML driver is deprecated and will be removed in version 3.0.
It is strongly recommended to switch to one of the other mappings.
.. note::
It is strongly recommended that you require ``doctrine/dbal`` in your
``composer.json`` as well, because using the ORM means mapping objects
@@ -148,19 +142,11 @@ step:
paths: array(__DIR__."/src"),
isDevMode: true,
);
// or if you prefer annotation, YAML or XML
// $config = ORMSetup::createAnnotationMetadataConfiguration(
// paths: array(__DIR__."/src"),
// isDevMode: true,
// );
// or if you prefer XML
// $config = ORMSetup::createXMLMetadataConfiguration(
// paths: array(__DIR__."/config/xml"),
// isDevMode: true,
//);
// $config = ORMSetup::createYAMLMetadataConfiguration(
// paths: array(__DIR__."/config/yaml"),
// isDevMode: true,
// );
// configuring the database connection
$connection = DriverManager::getConnection([
@@ -171,10 +157,6 @@ step:
// obtaining the entity manager
$entityManager = new EntityManager($connection, $config);
.. note::
The YAML driver is deprecated and will be removed in version 3.0.
It is strongly recommended to switch to one of the other mappings.
The ``require_once`` statement sets up the class autoloading for Doctrine and
its dependencies using Composer's autoloader.
@@ -322,7 +304,7 @@ data in your storage, and later in your application when the data is loaded agai
.. note::
This method, although very common, is inappropriate for Domain Driven
Design (`DDD <https://en.wikipedia.org/wiki/Domain-driven_design>`)
Design (\ `DDD <https://en.wikipedia.org/wiki/Domain-driven_design>`_)
where methods should represent real business operations and not simple
property change, And business invariants should be maintained both in the
application state (entities in this case) and in the database, with no
@@ -449,7 +431,7 @@ entity.
.. note::
A `DTO <https://en.wikipedia.org/wiki/Data_transfer_object>` is an object
A `DTO <https://en.wikipedia.org/wiki/Data_transfer_object>`_ is an object
that only carries data without any logic. Its only goal is to be transferred
from one service to another.
A ``DTO`` often represents data sent by a client and that has to be validated,
@@ -501,8 +483,8 @@ language describes how entities, their properties and references should be
persisted and what constraints should be applied to them.
Metadata for an Entity can be configured using attributes directly in
the Entity class itself, or in an external XML or YAML file. This
Getting Started guide will demonstrate metadata mappings using all three
the Entity class itself, or in an external XML file. This
Getting Started guide will demonstrate metadata mappings using both
methods, but you only need to choose one.
.. configuration-block::
@@ -528,40 +510,13 @@ methods, but you only need to choose one.
// .. (other code)
}
.. code-block:: annotation
<?php
// src/Product.php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="products")
*/
class Product
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
*/
private int|null $id = null;
/**
* @ORM\Column(type="string")
*/
private string $name;
// .. (other code)
}
.. code-block:: xml
<!-- config/xml/Product.dcm.xml -->
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://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="Product" table="products">
<id name="id" type="integer">
@@ -572,25 +527,6 @@ methods, but you only need to choose one.
</entity>
</doctrine-mapping>
.. note::
The YAML driver is deprecated and will be removed in version 3.0.
It is strongly recommended to switch to one of the other mappings.
.. code-block:: yaml
# config/yaml/Product.dcm.yml
Product:
type: entity
table: products
id:
id:
type: integer
generator:
strategy: AUTO
fields:
name:
type: string
The top-level ``entity`` definition specifies information about
the class and table name. The primitive type ``Product#name`` is
defined as a ``field`` attribute. The ``id`` property is defined with
@@ -736,7 +672,7 @@ classes. We'll store them in ``src/Bug.php`` and ``src/User.php``, respectively.
#[ORM\Id]
#[ORM\Column(type: 'integer')]
#[ORM\GeneratedValue]
private int $id;
private int|null $id;
#[ORM\Column(type: 'string')]
private string $description;
@@ -1083,66 +1019,13 @@ the ``Product`` before:
// ... (other code)
}
.. code-block:: annotation
<?php
// src/Bug.php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="bugs")
*/
class Bug
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
*/
private int|null $id = null;
/**
* @ORM\Column(type="string")
*/
private string $description;
/**
* @ORM\Column(type="datetime")
*/
private DateTime $created;
/**
* @ORM\Column(type="string")
*/
private string $status;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="assignedBugs")
*/
private User|null $engineer;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="reportedBugs")
*/
private User|null $reporter;
/**
* @ORM\ManyToMany(targetEntity="Product")
*/
private Collection $products;
// ... (other code)
}
.. code-block:: xml
<!-- config/xml/Bug.dcm.xml -->
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://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="Bug" table="bugs">
<id name="id" type="integer">
@@ -1160,61 +1043,27 @@ the ``Product`` before:
</entity>
</doctrine-mapping>
.. note::
The YAML driver is deprecated and will be removed in version 3.0.
It is strongly recommended to switch to one of the other mappings.
.. code-block:: yaml
# config/yaml/Bug.dcm.yml
Bug:
type: entity
table: bugs
id:
id:
type: integer
generator:
strategy: AUTO
fields:
description:
type: text
created:
type: datetime
status:
type: string
manyToOne:
reporter:
targetEntity: User
inversedBy: reportedBugs
engineer:
targetEntity: User
inversedBy: assignedBugs
manyToMany:
products:
targetEntity: Product
Here we have the entity, id and primitive type definitions.
For the "created" field we have used the ``datetime`` type,
which translates the YYYY-mm-dd HH:mm:ss database format
into a PHP DateTime instance and back.
After the field definitions, the two qualified references to the
user entity are defined. They are created by the ``many-to-one``
tag. The class name of the related entity has to be specified with
the ``target-entity`` attribute, which is enough information for
the database mapper to access the foreign-table. Since
user entity are defined. They are created by the ``ManyToOne``
attribute. The class name of the related entity has to be specified with
the ``targetEntity`` parameter, which is enough information for
the database mapper to access the foreign table. Since
``reporter`` and ``engineer`` are on the owning side of a
bi-directional relation, we also have to specify the ``inversed-by``
attribute. They have to point to the field names on the inverse
side of the relationship. We will see in the next example that the ``inversed-by``
attribute has a counterpart ``mapped-by`` which makes that
bi-directional relation, we also have to specify the ``inversedBy``
parameter. They have to point to the field names on the inverse
side of the relationship. We will see in the next example that the ``inversedBy``
parameter has a counterpart ``mappedBy`` which makes that
the inverse side.
The last definition is for the ``Bug#products`` collection. It
holds all products where the specific bug occurs. Again
you have to define the ``target-entity`` and ``field`` attributes
on the ``many-to-many`` tag.
you have to define the ``targetEntity`` and ``field`` parameters
on the ``ManyToMany`` attribute.
Finally, we'll add metadata mappings for the ``User`` entity.
@@ -1250,54 +1099,13 @@ Finally, we'll add metadata mappings for the ``User`` entity.
// .. (other code)
}
.. code-block:: annotation
<?php
// src/User.php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="users")
*/
class User
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @var int
*/
private int|null $id = null;
/**
* @ORM\Column(type="string")
* @var string
*/
private string $name;
/**
* @ORM\OneToMany(targetEntity="Bug", mappedBy="reporter")
* @var Collection<int, Bug> An ArrayCollection of Bug objects.
*/
private Collection $reportedBugs;
/**
* @ORM\OneToMany(targetEntity="Bug", mappedBy="engineer")
* @var Collection<int, Bug> An ArrayCollection of Bug objects.
*/
private Collection $assignedBugs;
// .. (other code)
}
.. code-block:: xml
<!-- config/xml/User.dcm.xml -->
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://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" table="users">
<id name="id" type="integer">
@@ -1311,32 +1119,6 @@ Finally, we'll add metadata mappings for the ``User`` entity.
</entity>
</doctrine-mapping>
.. note::
The YAML driver is deprecated and will be removed in version 3.0.
It is strongly recommended to switch to one of the other mappings.
.. code-block:: yaml
# config/yaml/User.dcm.yml
User:
type: entity
table: users
id:
id:
type: integer
generator:
strategy: AUTO
fields:
name:
type: string
oneToMany:
reportedBugs:
targetEntity: Bug
mappedBy: reporter
assignedBugs:
targetEntity: Bug
mappedBy: engineer
Here are some new things to mention about the ``one-to-many`` tags.
Remember that we discussed about the inverse and owning side. Now
both reportedBugs and assignedBugs are inverse relations, which
@@ -1344,8 +1126,7 @@ means the join details have already been defined on the owning
side. Therefore we only have to specify the property on the Bug
class that holds the owning sides.
Update your database schema by running:
::
Update your database schema by running::
$ php bin/doctrine orm:schema-tool:update --force
@@ -1802,26 +1583,11 @@ we have to adjust the metadata slightly.
// ...
}
.. code-block:: annotation
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="BugRepository")
* @ORM\Table(name="bugs")
*/
class Bug
{
// ...
}
.. code-block:: xml
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Bug" table="bugs" repository-class="BugRepository">
@@ -1829,16 +1595,6 @@ we have to adjust the metadata slightly.
</entity>
</doctrine-mapping>
.. note::
The YAML driver is deprecated and will be removed in version 3.0.
It is strongly recommended to switch to one of the other mappings.
.. code-block:: yaml
Bug:
type: entity
repositoryClass: BugRepository
Now we can remove our query logic in all the places and instead use them through the EntityRepository.
As an example here is the code of the first use case "List of Bugs":

View File

@@ -27,22 +27,6 @@ can specify the ``#[OrderBy]`` in the following way:
private Collection $groups;
}
.. code-block:: annotation
<?php
/** @Entity **/
class User
{
// ...
/**
* @ManyToMany(targetEntity="Group")
* @OrderBy({"name" = "ASC"})
* @var Collection<int, Group>
*/
private Collection $groups;
}
.. code-block:: xml
<doctrine-mapping>
@@ -55,23 +39,6 @@ can specify the ``#[OrderBy]`` in the following way:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
orderBy: { 'name': 'ASC' }
targetEntity: Group
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
The DQL Snippet in OrderBy is only allowed to consist of
unqualified, unquoted field names and of an optional ASC/DESC
positional statement. Multiple Fields are separated by a comma (,).

View File

@@ -66,7 +66,7 @@ which has mapping metadata that is overridden by the attribute above:
#[Column(name: 'trait_foo', type: 'integer', length: 100, nullable: true, unique: true)]
protected int $foo;
#[OneToOne(targetEntity: Bar::class, cascade: ['persist', 'merge'])]
#[OneToOne(targetEntity: Bar::class, cascade: ['persist'])]
#[JoinColumn(name: 'example_trait_bar_id', referencedColumnName: 'id')]
protected Bar|null $bar = null;
}
@@ -81,4 +81,4 @@ The case for just extending a class would be just the same but:
// ...
}
Overriding is also supported via XML and YAML (:ref:`examples <inheritence_mapping_overrides>`).
Overriding is also supported via XML (:ref:`examples <inheritence_mapping_overrides>`).

View File

@@ -15,7 +15,7 @@ has a very simple API and implements the SPL interfaces ``Countable`` and
->setFirstResult(0)
->setMaxResults(100);
$paginator = new Paginator($query, $fetchJoinCollection = true);
$paginator = new Paginator($query, fetchJoinCollection: true);
$c = count($paginator);
foreach ($paginator as $post) {
@@ -36,10 +36,25 @@ correct result:
This behavior is only necessary if you actually fetch join a to-many
collection. You can disable this behavior by setting the
``$fetchJoinCollection`` flag to ``false``; in that case only 2 instead of the 3 queries
``fetchJoinCollection`` argument to ``false``; in that case only 2 instead of the 3 queries
described are executed. We hope to automate the detection for this in
the future.
.. note::
``$fetchJoinCollection`` flag set to ``true`` might affect results if you use aggregations in your query.
``fetchJoinCollection`` argument set to ``true`` might affect results if you use aggregations in your query.
By using the ``Paginator::HINT_ENABLE_DISTINCT`` you can instruct doctrine that the query to be executed
will not produce "duplicate" rows (only to-one relations are joined), thus the SQL limit will work as expected.
In this way the `DISTINCT` keyword will be omitted and can bring important performance improvements.
.. code-block:: php
<?php
use Doctrine\ORM\Tools\Pagination\Paginator;
$dql = "SELECT u, p FROM User u JOIN u.mainPicture p";
$query = $entityManager->createQuery($dql)
->setHint(Paginator::HINT_ENABLE_DISTINCT, false)
->setFirstResult(0)
->setMaxResults(100);

View File

@@ -24,9 +24,7 @@ Mapping Indexed Associations
You can map indexed associations by adding:
* ``indexBy`` argument to any ``#[OneToMany]`` or ``#[ManyToMany]`` attribute.
* ``indexBy`` attribute to any ``@OneToMany`` or ``@ManyToMany`` annotation.
* ``index-by`` attribute to any ``<one-to-many />`` or ``<many-to-many />`` xml element.
* ``indexBy:`` key-value pair to any association defined in ``manyToMany:`` or ``oneToMany:`` YAML mapping files.
The code and mappings for the Market entity looks like this:
@@ -90,80 +88,12 @@ The code and mappings for the Market entity looks like this:
}
}
.. code-block:: annotation
<?php
namespace Doctrine\Tests\Models\StockExchange;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity
* @Table(name="exchange_markets")
*/
class Market
{
/**
* @Id @Column(type="integer") @GeneratedValue
* @var int
*/
private int|null $id = null;
/**
* @Column(type="string")
* @var string
*/
private string $name;
/**
* @OneToMany(targetEntity="Stock", mappedBy="market", indexBy="symbol")
* @var Collection<int, Stock>
*/
private Collection $stocks;
public function __construct($name)
{
$this->name = $name;
$this->stocks = new ArrayCollection();
}
public function getId(): int|null
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function addStock(Stock $stock): void
{
$this->stocks[$stock->getSymbol()] = $stock;
}
public function getStock($symbol): Stock
{
if (!isset($this->stocks[$symbol])) {
throw new \InvalidArgumentException("Symbol is not traded on this market.");
}
return $this->stocks[$symbol];
}
/** @return array<string, Stock> */
public function getStocks(): array
{
return $this->stocks->toArray();
}
}
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\StockExchange\Market">
@@ -177,24 +107,6 @@ The code and mappings for the Market entity looks like this:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Doctrine\Tests\Models\StockExchange\Market:
type: entity
id:
id:
type: integer
generator:
strategy: AUTO
fields:
name:
type:string
oneToMany:
stocks:
targetEntity: Stock
mappedBy: market
indexBy: symbol
Inside the ``addStock()`` method you can see how we directly set the key of the association to the symbol,
so that we can work with the indexed association directly after invoking ``addStock()``. Inside ``getStock($symbol)``
we pick a stock traded on the particular market by symbol. If this stock doesn't exist an exception is thrown.
@@ -234,53 +146,12 @@ here are the code and mappings for it:
}
}
.. code-block:: annotation
<?php
namespace Doctrine\Tests\Models\StockExchange;
/**
* @Entity
* @Table(name="exchange_stocks")
*/
class Stock
{
/**
* @Id @GeneratedValue @Column(type="integer")
* @var int
*/
private int|null $id = null;
/**
* @Column(type="string", unique=true)
*/
private string $symbol;
/**
* @ManyToOne(targetEntity="Market", inversedBy="stocks")
* @var Market
*/
private Market|null $market = null;
public function __construct($symbol, Market $market)
{
$this->symbol = $symbol;
$this->market = $market;
$market->addStock($this);
}
public function getSymbol(): string
{
return $this->symbol;
}
}
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="https://doctrine-project.org/schemas/orm/doctrine-mapping"
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\StockExchange\Stock">
@@ -293,23 +164,6 @@ here are the code and mappings for it:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Doctrine\Tests\Models\StockExchange\Stock:
type: entity
id:
id:
type: integer
generator:
strategy: AUTO
fields:
symbol:
type: string
manyToOne:
market:
targetEntity: Market
inversedBy: stocks
Querying indexed associations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -35,7 +35,6 @@
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="cascade-all" type="orm:emptyType" minOccurs="0"/>
<xs:element name="cascade-persist" type="orm:emptyType" minOccurs="0"/>
<xs:element name="cascade-merge" type="orm:emptyType" minOccurs="0"/>
<xs:element name="cascade-remove" type="orm:emptyType" minOccurs="0"/>
<xs:element name="cascade-refresh" type="orm:emptyType" minOccurs="0"/>
<xs:element name="cascade-detach" type="orm:emptyType" minOccurs="0"/>
@@ -82,36 +81,6 @@
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="named-query">
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="query" type="xs:string" use="required" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="named-queries">
<xs:sequence>
<xs:element name="named-query" type="orm:named-query" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="named-native-query">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="query" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="result-class" type="orm:fqcn" />
<xs:attribute name="result-set-mapping" type="xs:string" />
</xs:complexType>
<xs:complexType name="named-native-queries">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="named-native-query" type="orm:named-native-query" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="entity-listener">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="lifecycle-callback" type="orm:lifecycle-callback" minOccurs="0" maxOccurs="unbounded"/>
@@ -143,24 +112,6 @@
<xs:attribute name="discriminator-column" type="xs:string" use="optional" />
</xs:complexType>
<xs:complexType name="sql-result-set-mapping">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="entity-result" type="orm:entity-result"/>
<xs:element name="column-result" type="orm:column-result"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="sql-result-set-mappings">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="sql-result-set-mapping" type="orm:sql-result-set-mapping" minOccurs="1" maxOccurs="unbounded" />
</xs:choice>
</xs:complexType>
<xs:complexType name="cache">
<xs:attribute name="usage" type="orm:cache-usage-type" />
<xs:attribute name="region" type="xs:string" />
@@ -176,9 +127,6 @@
<xs:element name="discriminator-map" type="orm:discriminator-map" minOccurs="0"/>
<xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" />
<xs:element name="entity-listeners" type="orm:entity-listeners" minOccurs="0" maxOccurs="1" />
<xs:element name="named-queries" type="orm:named-queries" minOccurs="0" maxOccurs="1" />
<xs:element name="named-native-queries" type="orm:named-native-queries" minOccurs="0" maxOccurs="1" />
<xs:element name="sql-result-set-mappings" type="orm:sql-result-set-mappings" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="field" type="orm:field" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="embedded" type="orm:embedded" minOccurs="0" maxOccurs="unbounded"/>
@@ -226,22 +174,13 @@
<xs:complexType name="mapped-superclass" >
<xs:complexContent>
<xs:extension base="orm:entity">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:anyAttribute namespace="##other"/>
</xs:extension>
<xs:extension base="orm:entity"/>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="embeddable">
<xs:complexContent>
<xs:extension base="orm:entity">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
</xs:extension>
<xs:extension base="orm:entity"/>
</xs:complexContent>
</xs:complexType>
@@ -249,7 +188,6 @@
<xs:restriction base="xs:token">
<xs:enumeration value="DEFERRED_IMPLICIT"/>
<xs:enumeration value="DEFERRED_EXPLICIT"/>
<xs:enumeration value="NOTIFY"/>
</xs:restriction>
</xs:simpleType>
@@ -257,7 +195,6 @@
<xs:restriction base="xs:token">
<xs:enumeration value="SINGLE_TABLE"/>
<xs:enumeration value="JOINED"/>
<xs:enumeration value="TABLE_PER_CLASS"/>
</xs:restriction>
</xs:simpleType>
@@ -267,7 +204,6 @@
<xs:enumeration value="SEQUENCE"/>
<xs:enumeration value="IDENTITY"/>
<xs:enumeration value="AUTO"/>
<xs:enumeration value="UUID"/>
<xs:enumeration value="CUSTOM" />
</xs:restriction>
</xs:simpleType>
@@ -330,6 +266,7 @@
<xs:complexType name="discriminator-column">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="options" type="orm:options" minOccurs="0" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
@@ -564,7 +501,6 @@
<xs:choice minOccurs="0" maxOccurs="1">
<xs:element name="join-column" type="orm:join-column"/>
<xs:element name="join-columns" type="orm:join-columns"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
@@ -582,7 +518,6 @@
<xs:choice minOccurs="0" maxOccurs="1">
<xs:element name="join-column" type="orm:join-column"/>
<xs:element name="join-columns" type="orm:join-columns"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>

View File

@@ -1,164 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM;
use Doctrine\ORM\Cache\QueryCache;
use Doctrine\ORM\Cache\Region;
/**
* Provides an API for querying/managing the second level cache regions.
*/
interface Cache
{
public const DEFAULT_QUERY_REGION_NAME = 'query_cache_region';
public const DEFAULT_TIMESTAMP_REGION_NAME = 'timestamp_cache_region';
/**
* May read items from the cache, but will not add items.
*/
public const MODE_GET = 1;
/**
* Will never read items from the cache,
* but will add items to the cache as it reads them from the database.
*/
public const MODE_PUT = 2;
/**
* May read items from the cache, and add items to the cache.
*/
public const MODE_NORMAL = 3;
/**
* The query will never read items from the cache,
* but will refresh items to the cache as it reads them from the database.
*/
public const MODE_REFRESH = 4;
/**
* @param string $className The entity class.
*
* @return Region|null
*/
public function getEntityCacheRegion($className);
/**
* @param string $className The entity class.
* @param string $association The field name that represents the association.
*
* @return Region|null
*/
public function getCollectionCacheRegion($className, $association);
/**
* Determine whether the cache contains data for the given entity "instance".
*
* @param string $className The entity class.
* @param mixed $identifier The entity identifier
*
* @return bool true if the underlying cache contains corresponding data; false otherwise.
*/
public function containsEntity($className, $identifier);
/**
* Evicts the entity data for a particular entity "instance".
*
* @param string $className The entity class.
* @param mixed $identifier The entity identifier.
*
* @return void
*/
public function evictEntity($className, $identifier);
/**
* Evicts all entity data from the given region.
*
* @param string $className The entity metadata.
*
* @return void
*/
public function evictEntityRegion($className);
/**
* Evict data from all entity regions.
*
* @return void
*/
public function evictEntityRegions();
/**
* Determine whether the cache contains data for the given collection.
*
* @param string $className The entity class.
* @param string $association The field name that represents the association.
* @param mixed $ownerIdentifier The identifier of the owning entity.
*
* @return bool true if the underlying cache contains corresponding data; false otherwise.
*/
public function containsCollection($className, $association, $ownerIdentifier);
/**
* Evicts the cache data for the given identified collection instance.
*
* @param string $className The entity class.
* @param string $association The field name that represents the association.
* @param mixed $ownerIdentifier The identifier of the owning entity.
*
* @return void
*/
public function evictCollection($className, $association, $ownerIdentifier);
/**
* Evicts all entity data from the given region.
*
* @param string $className The entity class.
* @param string $association The field name that represents the association.
*
* @return void
*/
public function evictCollectionRegion($className, $association);
/**
* Evict data from all collection regions.
*
* @return void
*/
public function evictCollectionRegions();
/**
* Determine whether the cache contains data for the given query.
*
* @param string $regionName The cache name given to the query.
*
* @return bool true if the underlying cache contains corresponding data; false otherwise.
*/
public function containsQuery($regionName);
/**
* Evicts all cached query results under the given name, or default query cache if the region name is NULL.
*
* @param string|null $regionName The cache name associated to the queries being cached.
*
* @return void
*/
public function evictQueryRegion($regionName = null);
/**
* Evict data from all query regions.
*
* @return void
*/
public function evictQueryRegions();
/**
* Get query cache by region name or create a new one if none exist.
*
* @param string|null $regionName Query cache region name, or default query cache if the region name is NULL.
*
* @return QueryCache The Query Cache associated with the region name.
*/
public function getQueryCache($regionName = null);
}

View File

@@ -1,53 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache;
/**
* Association cache entry
*/
class AssociationCacheEntry implements CacheEntry
{
/**
* The entity identifier
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var array<string, mixed>
*/
public $identifier;
/**
* The entity class name
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var string
* @psalm-var class-string
*/
public $class;
/**
* @param string $class The entity class.
* @param array<string, mixed> $identifier The entity identifier.
* @psalm-param class-string $class
*/
public function __construct($class, array $identifier)
{
$this->class = $class;
$this->identifier = $identifier;
}
/**
* Creates a new AssociationCacheEntry
*
* This method allow Doctrine\Common\Cache\PhpFileCache compatibility
*
* @param array<string, mixed> $values array containing property values
*
* @return AssociationCacheEntry
*/
public static function __set_state(array $values)
{
return new self($values['class'], $values['identifier']);
}
}

View File

@@ -1,83 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache;
use Doctrine\ORM\Cache\Logging\CacheLogger;
/**
* Configuration container for second-level cache.
*/
class CacheConfiguration
{
/** @var CacheFactory|null */
private $cacheFactory;
/** @var RegionsConfiguration|null */
private $regionsConfig;
/** @var CacheLogger|null */
private $cacheLogger;
/** @var QueryCacheValidator|null */
private $queryValidator;
/** @return CacheFactory|null */
public function getCacheFactory()
{
return $this->cacheFactory;
}
/** @return void */
public function setCacheFactory(CacheFactory $factory)
{
$this->cacheFactory = $factory;
}
/** @return CacheLogger|null */
public function getCacheLogger()
{
return $this->cacheLogger;
}
/** @return void */
public function setCacheLogger(CacheLogger $logger)
{
$this->cacheLogger = $logger;
}
/** @return RegionsConfiguration */
public function getRegionsConfiguration()
{
if ($this->regionsConfig === null) {
$this->regionsConfig = new RegionsConfiguration();
}
return $this->regionsConfig;
}
/** @return void */
public function setRegionsConfiguration(RegionsConfiguration $regionsConfig)
{
$this->regionsConfig = $regionsConfig;
}
/** @return QueryCacheValidator */
public function getQueryValidator()
{
if ($this->queryValidator === null) {
$this->queryValidator = new TimestampQueryCacheValidator(
$this->cacheFactory->getTimestampRegion()
);
}
return $this->queryValidator;
}
/** @return void */
public function setQueryValidator(QueryCacheValidator $validator)
{
$this->queryValidator = $validator;
}
}

View File

@@ -1,61 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache;
use Doctrine\ORM\Exception\ORMException;
use function sprintf;
/**
* Exception for cache.
*/
class CacheException extends ORMException
{
/**
* @param string $sourceEntity
* @param string $fieldName
*
* @return CacheException
*/
public static function updateReadOnlyCollection($sourceEntity, $fieldName)
{
return new self(sprintf('Cannot update a readonly collection "%s#%s"', $sourceEntity, $fieldName));
}
/**
* @deprecated This method is not used anymore.
*
* @param string $entityName
*
* @return CacheException
*/
public static function updateReadOnlyEntity($entityName)
{
return new self(sprintf('Cannot update a readonly entity "%s"', $entityName));
}
/**
* @param string $entityName
*
* @return CacheException
*/
public static function nonCacheableEntity($entityName)
{
return new self(sprintf('Entity "%s" not configured as part of the second-level cache.', $entityName));
}
/**
* @deprecated This method is not used anymore.
*
* @param string $entityName
* @param string $field
*
* @return CacheException
*/
public static function nonCacheableEntityAssociation($entityName, $field)
{
return new self(sprintf('Entity association field "%s#%s" not configured as part of the second-level cache.', $entityName, $field));
}
}

View File

@@ -1,36 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache;
use Doctrine\Deprecations\Deprecation;
/**
* Defines entity / collection / query key to be stored in the cache region.
* Allows multiple roles to be stored in the same cache region.
*/
abstract class CacheKey
{
/**
* Unique identifier
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var string
*/
public $hash;
public function __construct(?string $hash = null)
{
if ($hash === null) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/pull/10212',
'Calling %s() without providing a value for the $hash parameter is deprecated.',
__METHOD__
);
} else {
$this->hash = $hash;
}
}
}

View File

@@ -1,58 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache;
use function implode;
use function ksort;
use function str_replace;
use function strtolower;
/**
* Defines entity collection roles to be stored in the cache region.
*/
class CollectionCacheKey extends CacheKey
{
/**
* The owner entity identifier
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var array<string, mixed>
*/
public $ownerIdentifier;
/**
* The owner entity class
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var string
* @psalm-var class-string
*/
public $entityClass;
/**
* The association name
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var string
*/
public $association;
/**
* @param string $entityClass The entity class.
* @param string $association The field name that represents the association.
* @param array<string, mixed> $ownerIdentifier The identifier of the owning entity.
* @psalm-param class-string $entityClass
*/
public function __construct($entityClass, $association, array $ownerIdentifier)
{
ksort($ownerIdentifier);
$this->ownerIdentifier = $ownerIdentifier;
$this->entityClass = (string) $entityClass;
$this->association = (string) $association;
parent::__construct(str_replace('\\', '.', strtolower($entityClass)) . '_' . implode(' ', $ownerIdentifier) . '__' . $association);
}
}

View File

@@ -1,73 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache;
use Doctrine\ORM\EntityManagerInterface;
use function array_map;
/**
* Entity cache entry
*/
class EntityCacheEntry implements CacheEntry
{
/**
* The entity map data
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var array<string,mixed>
*/
public $data;
/**
* The entity class name
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var string
* @psalm-var class-string
*/
public $class;
/**
* @param string $class The entity class.
* @param array<string,mixed> $data The entity data.
* @psalm-param class-string $class
*/
public function __construct($class, array $data)
{
$this->class = $class;
$this->data = $data;
}
/**
* Creates a new EntityCacheEntry
*
* This method allow Doctrine\Common\Cache\PhpFileCache compatibility
*
* @param array<string,mixed> $values array containing property values
*
* @return EntityCacheEntry
*/
public static function __set_state(array $values)
{
return new self($values['class'], $values['data']);
}
/**
* Retrieves the entity data resolving cache entries
*
* @return array<string, mixed>
*/
public function resolveAssociationEntries(EntityManagerInterface $em)
{
return array_map(static function ($value) use ($em) {
if (! ($value instanceof AssociationCacheEntry)) {
return $value;
}
return $em->getReference($value->class, $value->identifier);
}, $this->data);
}
}

View File

@@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache\Exception;
/** @deprecated */
final class InvalidResultCacheDriver extends CacheException
{
public static function create(): self
{
return new self(
'Invalid result cache driver; it must implement Doctrine\\Common\\Cache\\Cache.'
);
}
}

View File

@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache\Exception;
final class MetadataCacheNotConfigured extends CacheException
{
public static function create(): self
{
return new self('Class Metadata Cache is not configured.');
}
}

View File

@@ -1,19 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache\Exception;
use Doctrine\Common\Cache\Cache;
use function get_debug_type;
final class MetadataCacheUsesNonPersistentCache extends CacheException
{
public static function fromDriver(Cache $cache): self
{
return new self(
'Metadata Cache uses a non-persistent cache driver, ' . get_debug_type($cache) . '.'
);
}
}

View File

@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache\Exception;
final class QueryCacheNotConfigured extends CacheException
{
public static function create(): self
{
return new self('Query Cache is not configured.');
}
}

View File

@@ -1,19 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache\Exception;
use Doctrine\Common\Cache\Cache;
use function get_debug_type;
final class QueryCacheUsesNonPersistentCache extends CacheException
{
public static function fromDriver(Cache $cache): self
{
return new self(
'Query Cache uses a non-persistent cache driver, ' . get_debug_type($cache) . '.'
);
}
}

View File

@@ -1,29 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache;
use function time;
use function uniqid;
class Lock
{
/** @var string */
public $value;
/** @var int */
public $time;
public function __construct(string $value, ?int $time = null)
{
$this->value = $value;
$this->time = $time ?: time();
}
/** @return Lock */
public static function createLockRead()
{
return new self(uniqid((string) time(), true));
}
}

View File

@@ -1,105 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Cache\Logging;
use Doctrine\ORM\Cache\CollectionCacheKey;
use Doctrine\ORM\Cache\EntityCacheKey;
use Doctrine\ORM\Cache\QueryCacheKey;
/**
* Interface for logging.
*/
interface CacheLogger
{
/**
* Log an entity put into second level cache.
*
* @param string $regionName The name of the cache region.
* @param EntityCacheKey $key The cache key of the entity.
*
* @return void
*/
public function entityCachePut($regionName, EntityCacheKey $key);
/**
* Log an entity get from second level cache resulted in a hit.
*
* @param string $regionName The name of the cache region.
* @param EntityCacheKey $key The cache key of the entity.
*
* @return void
*/
public function entityCacheHit($regionName, EntityCacheKey $key);
/**
* Log an entity get from second level cache resulted in a miss.
*
* @param string $regionName The name of the cache region.
* @param EntityCacheKey $key The cache key of the entity.
*
* @return void
*/
public function entityCacheMiss($regionName, EntityCacheKey $key);
/**
* Log an entity put into second level cache.
*
* @param string $regionName The name of the cache region.
* @param CollectionCacheKey $key The cache key of the collection.
*
* @return void
*/
public function collectionCachePut($regionName, CollectionCacheKey $key);
/**
* Log an entity get from second level cache resulted in a hit.
*
* @param string $regionName The name of the cache region.
* @param CollectionCacheKey $key The cache key of the collection.
*
* @return void
*/
public function collectionCacheHit($regionName, CollectionCacheKey $key);
/**
* Log an entity get from second level cache resulted in a miss.
*
* @param string $regionName The name of the cache region.
* @param CollectionCacheKey $key The cache key of the collection.
*
* @return void
*/
public function collectionCacheMiss($regionName, CollectionCacheKey $key);
/**
* Log a query put into the query cache.
*
* @param string $regionName The name of the cache region.
* @param QueryCacheKey $key The cache key of the query.
*
* @return void
*/
public function queryCachePut($regionName, QueryCacheKey $key);
/**
* Log a query get from the query cache resulted in a hit.
*
* @param string $regionName The name of the cache region.
* @param QueryCacheKey $key The cache key of the query.
*
* @return void
*/
public function queryCacheHit($regionName, QueryCacheKey $key);
/**
* Log a query get from the query cache resulted in a miss.
*
* @param string $regionName The name of the cache region.
* @param QueryCacheKey $key The cache key of the query.
*
* @return void
*/
public function queryCacheMiss($regionName, QueryCacheKey $key);
}

Some files were not shown because too many files have changed in this diff Show More