Compare commits

...

463 Commits

Author SHA1 Message Date
Grégoire Paris
5bff0919a7 Merge pull request #12254 from elliotbruneel/fix/empty-array-query
fix: handling of empty array in SQL condition generation
2025-11-10 14:35:45 +01:00
Elliot Bruneel
9ef0f5301b fix: update SQL condition for empty array to 1=0 instead of IN (NULL) 2025-11-10 10:44:48 +01:00
Elliot Bruneel
4989ca6f15 test: add test for finding by nullable field with empty array 2025-11-05 10:03:09 +01:00
Elliot Bruneel
32d1e97ce7 chore: improve empty array check in SQL condition generation 2025-11-05 09:51:33 +01:00
Grégoire Paris
ca8147b148 Merge pull request #12257 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-12.2.0
Bump doctrine/.github from 12.1.0 to 12.2.0
2025-11-03 09:32:58 +01:00
dependabot[bot]
c8ebea77f0 Bump doctrine/.github from 12.1.0 to 12.2.0
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 12.1.0 to 12.2.0.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/12.1.0...v12.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 06:11:36 +00:00
Elliot Bruneel
23f22860f1 chore: update phpstan version and regenerate baseline 2025-10-31 09:04:03 +01:00
Elliot Bruneel
b24586b1b5 fix: handling of empty array in SQL condition generation 2025-10-30 17:31:04 +01:00
Grégoire Paris
fe5ee705db Merge pull request #12247 from greg0ire/composer-lint
Setup composer lint workflow
2025-10-29 07:28:39 +01:00
Grégoire Paris
0511a9f790 Merge pull request #12248 from greg0ire/remove-mailing-list
Drop link to mailing list
2025-10-28 22:06:18 +01:00
Grégoire Paris
0e3d5e8c82 Drop link to mailing list
Who still uses this? Not me, that's for sure!
2025-10-28 21:20:15 +01:00
Grégoire Paris
72ffb3bfbf Remove archive exclude list
It is not up-to-date, and we use .gitattributes for this purpose.
2025-10-28 21:04:43 +01:00
Grégoire Paris
2e9a1adc23 Setup composer lint workflow 2025-10-28 21:03:24 +01:00
Grégoire Paris
59938cae57 Merge pull request #12238 from mpdude/fix-collections-deprecation
Avoid triggering a deprecation notice in doctrine/collections
2025-10-27 22:19:59 +01:00
Grégoire Paris
298dc9bb6a Merge pull request #12183 from mpdude/paginator-confused-result-set-mapping-initialized
Paginator with output walker returns count 0 when the query has previously been executed
2025-10-27 21:54:38 +01:00
Matthias Pigulla
da67f323e0 Add PHPStan errors to persistence2 baseline file 2025-10-27 19:51:11 +01:00
Matthias Pigulla
63635cad0e Remove PHPStan error suppressions 2025-10-27 12:28:48 +01:00
Grégoire Paris
a0d401b688 Merge pull request #12239 from doctrine/dependabot/github_actions/2.20.x/actions/download-artifact-6
Bump actions/download-artifact from 5 to 6
2025-10-27 08:38:07 +01:00
Grégoire Paris
6acbadfbbe Merge pull request #12240 from doctrine/dependabot/github_actions/2.20.x/actions/upload-artifact-5
Bump actions/upload-artifact from 4 to 5
2025-10-27 08:37:52 +01:00
dependabot[bot]
c64dcb4d38 Bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 06:41:11 +00:00
dependabot[bot]
3304290b21 Bump actions/download-artifact from 5 to 6
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 06:22:30 +00:00
Matthias Pigulla
1865717721 Avoid triggering a deprecation notice in doctrine/collections
This updates the code to avoid triggering the deprecation introduced in https://github.com/doctrine/collections/pull/472.
2025-10-26 23:20:27 +01:00
Matthias Pigulla
828b06e20f Update the DQL walker cookbook example 2025-10-26 22:13:51 +01:00
Matthias Pigulla
c2b844d2e3 Update src/Tools/Pagination/Paginator.php
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2025-10-26 22:08:56 +01:00
dependabot[bot]
b45d5329f8 Bump doctrine/.github from 10.1.0 to 12.0.0 (#12227) 2025-10-23 08:10:27 +02:00
Grégoire Paris
c1047b30e3 Merge pull request #12216 from paulinevos/docs-builder
Use docs builder in ORM repo
2025-10-23 07:48:31 +02:00
Grégoire Paris
aa62efa30a Adapt to latest coding standard 2025-10-22 21:12:17 +02:00
Pauline Vos
f71956f001 Use docs-builder to generate ORM docs
Introduces the `composer docs` command to generate the docs locally, and
uses the same tool (`docs-builder`) in the documentation GH workflow.
2025-10-22 21:09:03 +02:00
Ali Sol
96f9b29573 Merge pull request #12233 from alisolphp/fix-docs-typos-2-20
Docs: fix typos and grammar across reference docs
2025-10-21 17:09:12 +02:00
Grégoire Paris
9a55cf4f30 Merge pull request #12190 from mpdude/criteria-matching-custom-type-retry
Fix collection filtering API for `IN`/`NOT IN` comparisons that require type conversions
2025-10-16 07:56:07 +02:00
Matthias Pigulla
9d680a6de4 Do not eagerly set metadata from ResolveTargetEntityListener (#12174)
* Do not eagerly set metadata from ResolveTargetEntityListener

When using the `ResolveTargetEntityListener` to substitute `targetEntities` in association mappings, do not eagerly put the resolved (target) entity into the class metadata cache under the class name of the original entity.

#### Motivation

I have a library that wants to distribute a MappedSuperclass as the base for some functionality. It will be necessary that clients using the library will extend the MappedSuperclass to fill in some blanks, creating the first real `#[Entity]` instance of it.

This client-provided entity will be the primary means of working with the class. Thus, I was following the [note in the documentation](https://www.doctrine-project.org/projects/doctrine-orm/en/3.5/reference/inheritance-mapping.html#mapped-superclasses:~:text=It%20is%2C%20however) and using the `ResolveTargetEntityListener` to declare that whenever an association refers to that mapped superclass, the particular entity class shall be used instead.

>  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 [ResolveTargetEntityListener](https://www.doctrine-project.org/projects/doctrine-orm/en/3.5/cookbook/resolve-target-entity-listener.html) 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.

#### Changes made

The `ResolveTargetEntityListener` primarily does what its name suggests: For newly loaded class metadata, it inspects all associations declared and replaces the `targetEntity` with new (resolved) values.

But additionally, when a loaded class is the target of such a resolution, it would also put the class metadata into the cache under the name of the original entity.

I think that extra step is wrong, and this PR removes it. It had the side effect that when other classes extending the MappedSuperclass were loaded _after_ the resolve target class has been seen for the first time, the metadata for those classes would not inherit from the mapped superclass anymore, but from the target entity class instead. In my real-life use case, this causes weird mapping errors down the road; as of ^3.0, it would throw a mapping exception asking to configure inheritance mapping. But note that there would be no inheritance between the two entity classes at all.

#### More background

The documentation [describes the use of `ResolveTargetEntityListener`](https://www.doctrine-project.org/projects/doctrine-orm/en/3.5/cookbook/resolve-target-entity-listener.html) with an interface that is resolved to an entity class. For an interface, adding the extra metadata does not make a difference, since it never interferes with actual entity or mapped superclasses.

The initial idea of adding a copy of the entity class metadata under the interface name came from commit
9c7f3f2747 in #385. The goal was to make it possible to also find entities by interface names, like so:

```
$em->find('Foo\BarBundle\Entity\PersonInterface', 1);
```

It then [turned out that this only worked when the resolution had already been applied](https://github.com/doctrine/orm/pull/385#issuecomment-6658893). So, the new `onClassMetadataNotFound` event was added and the resolution map would be checked in that case as well (#1181). The inital code stayed in place, possibly giving a small performance gain.

In my real-world use case and the test case I added in this PR, the associations are even self-referencing. That should not really be necessary for the problem to surface. I decided to keep it this way to show that the `targetEntity` need not be an interface after all, and that a MappedSuperclass can be used in the same way.
2025-10-15 16:10:51 +02:00
Matthias Pigulla
7a59281157 Fix collection filtering API for IN/NOT IN comparisons that require type conversions
This PR fixes the `Criteria` matching API for `IN` and `NIN` conditions with values that are arrays, by making sure that type information for the matched field is passed to the DBAL level correctly.

Passing the right parameter type to DBAL is important to make sure parameter conversions are applied before matching at the database level.

Memory-based collections (`ArrayCollection`s or initialized collection fields) would perform matching on the objects in memory where no type conversion to the database representation is required, giving correct results.

But uninitialized collections that have their conditions evaluated at the database level need to convert parameter values to the database representation before performing the comparison.

One extra challenge is that the DBAL type system does currently not support array-valued parameters for custom types. Only a [limited list of types](https://www.doctrine-project.org/projects/doctrine-dbal/en/4.2/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion) is supported.

I discussed this with @morozov at the Doctrine Hackathon and came to the conclusion that it would be best to work around this limitation at the ORM level. Thus, this fix recognizes array-valued parameters and creates multiple placeholders (like `?, ?, ?`) for them, flattening out the arrays in the parameter list and repeating the type information for each one of them.

Previous stalled attempt to fix this was in #11897.
2025-10-13 23:11:56 +02:00
Grégoire Paris
5def068fe9 Merge pull request #12223 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-10.1.0
Bump doctrine/.github from 8.0.0 to 10.1.0
2025-10-13 08:49:34 +02:00
dependabot[bot]
693acbf812 Bump doctrine/.github from 8.0.0 to 10.1.0
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 8.0.0 to 10.1.0.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/8.0.0...10.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 06:11:35 +00:00
Grégoire Paris
c1ce2bb687 Merge pull request #12220 from mbeccati/fix-mysql9-library
Escape library as a table name in tests (#12170)
2025-10-11 17:08:47 +02:00
Matteo Beccati
5f6896a2f9 Avoid using LIBRARY as table name (#12170)
It is a reserved word since MySQL 9.2:
https://dev.mysql.com/doc/refman/9.2/en/create-library.html
2025-10-11 11:56:29 +02:00
Grégoire Paris
930a790a5a Merge pull request #12212 from mpdude/revert-11769
Revert "Fix fields of transient classes being considered duplicate with `reportFieldsWhereDeclared` (#11769)"
2025-10-10 08:17:09 +02:00
Christian Flothmann
3b7de17f2e add jobs using PHP 8.5 in the CI (#12180) 2025-10-09 16:39:28 +02:00
Matthias Pigulla
8afaa63d73 Add a recommendation not to use multiple private fields of the same name in entity hierarchies 2025-10-09 11:11:51 +02:00
Matthias Pigulla
2ad720b304 Revert "Fix fields of transient classes being considered duplicate with reportFieldsWhereDeclared (#11769)"
This reverts commit 4feaa470af.
2025-10-09 10:23:55 +02:00
Benjamin Eberlei
a939dc2e0d [GH-9219] Add support for toIterable over mixed or scalar results. (#12187)
* [GH-9219] Add support for toIterable over mixed or scalar results.

* Housekeeping: phpcs

* Update test names
2025-10-08 15:07:52 +02:00
Christophe Coevoet
f8186b1203 Merge pull request #12200 from mpdude/fix-invalid-dql-test-case
Fix DQL JOIN syntax in two test cases
2025-10-08 11:08:24 +02:00
Matthias Pigulla
048e308241 Fix DQL JOIN syntax in two test cases 2025-10-07 17:54:33 +02:00
Alexander M. Turek
4274dac8a2 Remove calls to getMockForAbstractClass() (#12003) 2025-10-07 16:34:22 +02:00
Grégoire Paris
c1af765960 Merge pull request #12185 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-8.0.0
Bump doctrine/.github from 7.3.0 to 8.0.0
2025-10-07 15:40:44 +02:00
Christian Flothmann
5f3551852f use the empty string instead of null as an array offset (#12181) 2025-10-07 14:50:23 +02:00
Grégoire Paris
8144cad07c Upgrade to doctrine/coding-standard 14 2025-10-06 09:01:36 +02:00
dependabot[bot]
70fd68cf7f Bump doctrine/.github from 7.3.0 to 8.0.0
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 7.3.0 to 8.0.0.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/7.3.0...8.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 06:14:08 +00:00
Matthias Pigulla
437259556c Fix CS 2025-10-01 19:48:04 +02:00
Matthias Pigulla
e7e2fef56c Fix creation of the count query, to that a new RSM is being created 2025-10-01 19:46:58 +02:00
Matthias Pigulla
3e34b8e86a Add a test to reproduce the issue 2025-10-01 19:35:18 +02:00
Christian Flothmann
7d950aba62 do not call setAccessible() on PHP >= 8.1 (#12182) 2025-10-01 16:17:00 +02:00
Grégoire Paris
8fe1200edf Merge pull request #11895 from mpdude/fix-many-to-many-in-expression
Fix `IN`/`NOT IN` expression handling and support enums when matching on to-many-collections
2025-08-26 15:32:52 +02:00
Grégoire Paris
397358c308 Merge pull request #12133 from greg0ire/update-phpstan
PHPStan 2.1.22
2025-08-19 07:36:10 +02:00
Grégoire Paris
ac37a87a3d Merge pull request #12139 from doctrine/dependabot/github_actions/2.20.x/actions/checkout-5
Bump actions/checkout from 4 to 5
2025-08-18 17:31:47 +02:00
dependabot[bot]
613f52db5a Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-18 09:50:01 +00:00
Grégoire Paris
cf5503b0d8 PHPCS 3.13.2 (#12134) 2025-08-17 21:53:23 +02:00
Grégoire Paris
ae5e9c8c6c PHPStan 2.1.22 2025-08-17 19:24:33 +02:00
Grégoire Paris
1a2826d147 Merge pull request #12053 from alexislefebvre/chore-remove-run-all.sh
chore: remove run-all.sh
2025-08-11 14:14:20 +02:00
Grégoire Paris
05760f9454 Merge pull request #12127 from doctrine/dependabot/github_actions/2.20.x/actions/download-artifact-5
Bump actions/download-artifact from 4 to 5
2025-08-11 13:06:03 +02:00
dependabot[bot]
26af013842 Bump actions/download-artifact from 4 to 5
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-11 10:22:17 +00:00
Grégoire Paris
c322c71cd4 Merge pull request #12120 from greg0ire/fix-broken-comments
Fix broken comments
2025-08-08 08:55:44 +02:00
Grégoire Paris
3c733a2fee Add missing phpdoc 2025-08-08 08:34:07 +02:00
Grégoire Paris
5984ad586a Fix broken phpdoc comments 2025-08-08 08:33:39 +02:00
Grégoire Paris
ee2c3a506b Merge pull request #12097 from mvorisek/add_fixed_id_insert_count_query_test
Add 2nd level cache test for insert without post-inserted ID
2025-08-08 08:26:23 +02:00
Grégoire Paris
04694a9f7b Merge pull request #11835 from gseidel/fix-pre-persist-call-persist
fix: calling scheduleForInsert twice
2025-08-07 06:25:35 +02:00
Michael Voříšek
5b2060e25f Add 2nd level cache test for insert without post-inserted ID
Inserts without post-inserted ID can be sent to DB grouped together
hence the extra test.
2025-08-06 08:22:48 +02:00
Grégoire Paris
39e35fc06c Merge pull request #12099 from alexislefebvre/2.20.x-update-supported-branches-on-README
doc: update supported branches on README (2.20.x)
2025-08-04 16:59:49 +02:00
Alexis Lefebvre
7f061c3870 doc: update supported branches on README 2025-08-04 16:38:55 +02:00
Grégoire Paris
74495711fb Merge pull request #11934 from mvorisek/fix_joined_subclass_persister_insert_of_multiple_entities
Fix JoinedSubclassPersister when multiple entities are inserted
2025-08-02 08:34:29 +02:00
Michael Voříšek
97a7cb8d2f Unify JoinedSubclassPersister dequeue
Fix JoinedSubclassPersister as BasicEntityPersister was already fixed in GH-10735.

The fix can be verified by modifying UnitOfWork to execute `BasicEntityPersister::executeInserts()` for multiple entities at once for the same entity class/persister instance - https://github.com/doctrine/orm/blob/2.20.3/src/UnitOfWork.php#L1186 - then reproducible on `Doctrine\Tests\ORM\Functional\Ticket\GH10531Test::testInserts` test.

As extending/modifying UnitOfWork in tests in not easily possible, I submit this fix for v2.x without a test.
2025-08-01 15:31:18 +02:00
Grégoire Paris
e0052390e1 Merge pull request #12087 from mvorisek/improve_basic_entity_persister
Improve BasicEntityPersister to be more flexible and cleaner
2025-07-30 09:44:24 +02:00
Michael Voříšek
8c6419e0e0 Prefer strict empty-array comparison over empty() call 2025-07-29 15:15:31 +02:00
Michael Voříšek
6f5ce1aca2 BasicEntityPersister: refactor $values variable into $placeholders
The new variable name is much more clearer.
2025-07-29 15:15:31 +02:00
Michael Voříšek
98e7a53b42 Remove BasicEntityPersister::$insertSql cache property
When the persister is extended to do a multi update, the caching is not
wanted. The impact is minimal as the CPU/time overhead per query is
much bigger and the prepared statement is not cached anyway.
2025-07-29 15:15:31 +02:00
Gerhard Seidel
3aaaf37dfb fix: PrePersistEventTest typos and unnecessary comments 2025-07-29 14:40:20 +02:00
Grégoire Paris
154a4652ee Merge pull request #12086 from mvorisek/add_cache_rw_strict_locking_test
Add functional strict-locking 2nd level cache test
2025-07-29 11:48:25 +02:00
Michael Voříšek
ae7489ff19 Add functional strict-locking 2nd level cache test 2025-07-28 12:14:50 +02:00
Grégoire Paris
1ee01f4473 Merge pull request #12078 from stlgaits/2.20.x
Fix embedded classes display in orm:mapping:command output
2025-07-22 08:48:52 +02:00
stlgaits
8a9ed138a8 Fix embedded classes display in orm:mapping:command output 2025-07-21 15:44:46 +02:00
Alexis Lefebvre
41ea59ac66 chore: use a shorter name for CI on GitHub Actions (#12055) 2025-07-04 00:19:01 +02:00
Alexis Lefebvre
e605e6d569 doc: add links to GitHub Actions on README (#12054) 2025-07-04 00:13:51 +02:00
Alexis Lefebvre
d68c1dcd6d chore: remove run-all.sh 2025-07-02 00:14:28 +02:00
Grégoire Paris
6307b4fa7d Merge pull request #8012 from sgehrig/bug/#8011-ordering-with-arithmetic-expression
Bug/#8011 ordering with arithmetic expression
2025-06-24 19:50:46 +02:00
Alexander M. Turek
5d21bb158b Fix calls to Application::add() (#12006) 2025-06-18 08:58:26 +02:00
Grégoire Paris
71550106d4 Merge pull request #11975 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-7.3.0
Bump doctrine/.github from 7.2.2 to 7.3.0
2025-06-09 22:24:12 +02:00
dependabot[bot]
36011f0d0f Bump doctrine/.github from 7.2.2 to 7.3.0
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 7.2.2 to 7.3.0.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/7.2.2...7.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-09 07:13:58 +00:00
Grégoire Paris
c97d775370 Merge pull request #11963 from dbu/update-doc-building
cleanup doc building instructions
2025-06-09 07:45:09 +02:00
Grégoire Paris
e9f0345a97 Merge pull request #11966 from greg0ire/partial-revert-10162-2
Partially revert to stdout
2025-06-07 09:41:03 +02:00
Grégoire Paris
0feb09d0d6 Partially revert to stdout
This command's purpose is to provide structured data, except for a call
to caution() that warns the user in case they do not have any mapped
entities or they have errors.
2025-06-06 07:57:38 +02:00
Grégoire Paris
fe5f8bbaa1 Merge pull request #11965 from greg0ire/partial-revert-10162
Revert to stdout for MappingDescribeCommand
2025-06-06 00:04:07 +02:00
Grégoire Paris
ecf3cec376 chore: ignore deprecations from Symfony
Symfony 7.3 is not available to all of our users, so we cannot switch to
native lazy objects, which require a PHP version higher than the lowest
PHP version we support.
2025-06-05 23:19:32 +02:00
Grégoire Paris
0a714db4d9 Revert to stdout for MappingDescribeCommand
In f256d996cc, I did a global move to
stderr for notifications, and went a bit overboard for
MappingDescribeCommand, which purpose is to output a description.
2025-06-05 23:07:28 +02:00
David Buchmann
471fda8d0b cleanup doc building instructions 2025-06-05 07:44:37 +02:00
Grégoire Paris
dfe32c2f74 Unwrap literalinclude block (#11962)
For some reason, it does not appear to work when nested inside a
code-block directive. Anyway, if you specify the language attribute, you
get markup identical to what you obtain when using code-block and
literalinclude, so this wrapping seems unneeded.
2025-06-04 00:18:59 +02:00
Grégoire Paris
c51ba3ce6b Merge pull request #11951 from dbu/fix-doc-syntax
insert blank line before code in code-block
2025-05-27 14:08:44 +02:00
David Buchmann
fe025e8d23 insert blank line before code in code-block 2025-05-27 08:59:14 +02:00
Grégoire Paris
ae2957cf7e Merge pull request #11932 from dbannik/2.20.3-issue-11931
#11931 Bug when change sql filter [Related issue #11694]
2025-05-06 07:53:48 +02:00
Dmitry Bannik
e172b3bf9c #11931 Bug when change sql filter [Related issue #11694]
This fix takes into account the invalidation of the filter sql for SingleTablePersister and JoinedSubclassPersister
2025-05-05 23:43:27 +03:00
Grégoire Paris
c9c6e8da2e Merge pull request #11834 from dbu/document-generated-columns
document how to work with generated columns
2025-05-05 10:05:55 +02:00
Grégoire Paris
528b8837e1 Merge pull request #11929 from doctrine/2.20.x-merge-up-into-2.21.x_KkdqS0u7
Merge release 2.20.3 into 2.21.x
2025-05-02 21:57:23 +02:00
Grégoire Paris
17d28b5c4c Merge pull request #11917 from stof/lazy_ghost_postload
Fix the initialization of lazy-ghost proxies with postLoad listeners
2025-05-02 19:07:53 +02:00
Christophe Coevoet
a2d510c6f4 Fix the initialization of lazy-ghost proxies with postLoad listeners
PostLoad listeners might initialize values for transient properties, so
the proxy should not skip initialization when using transient
properties.

Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
2025-05-02 15:27:59 +02:00
Christophe Coevoet
2a4ebca90e Refactor tests to avoid using instance properties to track postLoad
The old proxy implementation of doctrine/common was triggered by public
methods rather than access to properties (making public properties
unsupported in entities), so tests could use public instance properties
to track the state of postLoad lifecycle callbacks without triggering
the proxy initialization when reading that state (which then changes the
state of triggering the postLoad callback).
As the new proxy implementation hooks into properties instead, the tests
now use a static method (ensuring it is reset properly before loading
the instance for which we care about the tracking) instead of an
instance property.
2025-04-22 17:39:29 +02:00
Matthias Pigulla
9bf407f336 Fix IN/NOT IN expression handling and support enums when matching on to-many-collections
This fixes that using a `Criteria` with an `IN` or `NIN` expression on a to-many collection currently leads to an SQL error (#6173). The `ManyToMany` persister needs to know about the slightly different SQL syntax for `[NOT] IN ()`.

In the case of `[NOT] IN` expressions, the value will be an array, which also required me to change (I guess "fix") the parameter type handling. I have pulled the necessary code from the `BasicEntityPersister` and placed it as static helper methods in `PersisterHelper`.

This is somewhat inspired by #11516, which aims at fixing #11481: By re-using the parameter type handling code, it also fixes using backed enums in `EQ`, `IN` and `NIN` expressions within `Criteria` when `matching()` on one-to-many and many-to-many collections.
2025-03-30 22:44:12 +02:00
Grégoire Paris
cc29ae0d36 Merge pull request #11891 from mpdude/expression-matching-caveats
Add more detailed caveats for using the Collection filtering API
2025-03-29 11:31:36 +01:00
Grégoire Paris
bd4a053d29 Merge pull request #11894 from DavidPetrasek/3.3.x
Fix URL's in xml-mapping.rst
2025-03-27 20:59:26 +01:00
David Petrásek
52fbfb3785 Revert to http for namespace name
These URLs are meant as identifiers rather than actual urls intended to
be used to perform an HTTP request.
2025-03-27 17:39:10 +01:00
Matthias Pigulla
c259371e5f Remove property hooks mention 2025-03-26 18:58:17 +01:00
Matthias Pigulla
dcdd58b642 working-with-associations.rst aktualisieren
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2025-03-26 18:14:01 +01:00
Matthias Pigulla
7b9c53854f Add more detailed caveats for using the Collection filtering API 2025-03-26 13:38:52 +01:00
Grégoire Paris
cdc5fe11dd Merge pull request #11889 from Rixafy/docs-typo-fix
Fix docs typo (nulable -> nullable)
2025-03-25 23:16:01 +01:00
Rixafy
69ece00564 Fix docs typo (nulable -> nullable) 2025-03-25 22:25:00 +01:00
Grégoire Paris
c679d1b007 Merge pull request #11885 from greg0ire/no-triple-stars
Avoid triple stars
2025-03-25 07:51:08 +01:00
Grégoire Paris
1e15b22dcb Avoid triple stars
They don't have a special meaning, and are rendered like this:
<strong>*REQUIRED</strong>*.
2025-03-25 07:49:53 +01:00
Grégoire Paris
44057b4683 Merge pull request #11845 from lacatoire/update-message-annotation-to-attribute
Update message of `ORMInvalidArgumentException`
2025-03-24 10:58:02 +01:00
Grégoire Paris
013df03795 Upgrade to doctrine/coding-standard 13 (#11881) 2025-03-24 07:18:07 +01:00
Louis-Arnaud
2d2a34407c Use attributes in exception message 2025-03-23 16:07:31 +01:00
Stefan Gehrig
067ad51b3f fixes sqlite sql inconsistency 2025-03-17 08:48:30 +01:00
Stefan Gehrig
00c77213fb fixes codesniffer violation 2025-03-15 09:42:21 +01:00
Matteo Beccati
3303cd3b5d Fix non-deterministic test (#11866) 2025-03-14 00:09:36 +01:00
Grégoire Paris
afcf91e839 Merge pull request #11863 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-7.2.2
Bump doctrine/.github from 7.2.1 to 7.2.2
2025-03-10 09:24:12 +01:00
dependabot[bot]
c61a9b3b6d Bump doctrine/.github from 7.2.1 to 7.2.2
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 7.2.1 to 7.2.2.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/7.2.1...7.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 06:43:02 +00:00
Stefan Gehrig
c68b8f90b3 adds a test for postgres that uses a HIDDEN result variable for ordering based on arithmetic expression 2025-03-05 09:28:52 +01:00
Stefan Gehrig
aa4f9ce9e9 CS fix based on PHP_CodeSniffer report 2025-03-05 09:22:57 +01:00
Stefan Gehrig
d96fc23327 skips tests when running on postgres 2025-02-27 10:30:21 +01:00
Louis-Arnaud
3aed6912a3 Update ORMInvalidArgumentException.php
update message to use attribute instead of annotation
2025-02-21 10:10:22 +01:00
Gerhard Seidel
4fb044d5f6 fix: cs 2025-02-20 10:01:35 +08:00
David Buchmann
8ce7b310c5 document how to work with generated columns 2025-02-17 15:06:18 +01:00
Gerhard Seidel
2a953c5e2b fix: PrePersistEventTest and cs 2025-02-17 14:01:08 +08:00
Gerhard Seidel
abc6a40ccb fix: calling scheduleForInsert twice
If scheduleForInsert was called in prePersist hook already, then persistNew need to check this case first, otherwise a ORMInvalidArgumentException will be thrown
2025-02-14 12:45:13 +08:00
Grégoire Paris
158605bf24 Merge pull request #11833 from HypeMC/fix-dql
Fix DQL example with composite key
2025-02-13 23:49:22 +01:00
Grégoire Paris
2c2ef65817 Merge pull request #11826 from aprat84/gh-11741
Clone query hints and parameters in `LimitSubqueryOutputWalker` constructor
2025-02-12 08:52:33 +01:00
HypeMC
1c33a86983 Fix DQL example with composite key 2025-02-11 16:10:59 +01:00
Albert Prat
310fe1cccb Clone query hints and parameters in LimitSubqueryOutputWalker constructor
This fixes a bug that arises when using Pagination and an entity relation is mapped with fetch-mode EAGER but setFetchMode LAZY (or anything that is not EAGER) has been used on the query. If the query use WITH condition, an exception is incorrectly raised (Associations with fetch-mode=EAGER may not be using WITH conditions).
The class LimitSubqueryOutputWalker clones the query, but not its parameters and hints, so the generated subquery does not know that fetch-mode has been overridden.

Fixes #11741
2025-02-11 10:48:14 +01:00
Grégoire Paris
a67f677747 Merge pull request #11707 from jorenMartens/2.20.x
[DDC-551] fix, add filter support in oneToOne relation 2.20.x
2025-02-07 08:23:53 +01:00
Grégoire Paris
73e68f3c7d Merge pull request #11821 from doctrine/2.20.x-merge-up-into-2.21.x_8O8nHxqC
Merge release 2.20.2 into 2.21.x
2025-02-04 20:24:01 +01:00
Grégoire Paris
19912de927 Merge pull request #11820 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-7.2.1
Bump doctrine/.github from 7.1.0 to 7.2.1
2025-02-04 20:17:01 +01:00
dependabot[bot]
737cca5b78 Bump doctrine/.github from 7.1.0 to 7.2.1
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 7.1.0 to 7.2.1.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/7.1.0...7.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-04 18:23:54 +00:00
Grégoire Paris
9e999ea1ff Merge pull request #11792 from dbannik/11783-failure-with-indexed-relation
11783 failure with indexed relation
2025-01-28 15:32:25 +01:00
Bob van de Vijver
6755bb0c7b Fix Hydration when use ManyToMany[indexBy]
The bug related (#11694) and fixed mapping of sql column alias to field in entity (#11783) and
invalidate cache [cache/persisted/entity|cache/persisted/collection] when sql filter changes
2025-01-27 15:35:59 +03:00
Alexander M. Turek
73777d0bd4 Merge branch '2.20.x' into 2.21.x
* 2.20.x:
  Introduce testNotListedValueInEnumArray
  Fix documentation for JoinColumn nullable (#11798)
  Ignore deprecations from doctrine/common
  Fix fields of transient classes being considered duplicate with `reportFieldsWhereDeclared`
2025-01-26 19:56:20 +01:00
Grégoire Paris
c2a49327a7 Merge pull request #11799 from HypeMC/enum-array-error
Fix invalid enum value in array of enums
2025-01-22 11:54:59 +01:00
Maxime COLIN
9bd7242376 Introduce testNotListedValueInEnumArray 2025-01-22 02:25:34 +01:00
pawel-slowik
fff085b63f Fix documentation for JoinColumn nullable (#11798)
Nullability is not inherited from the PHP type. The change that enabled
this feature was reversed in https://github.com/doctrine/orm/pull/8732.
2025-01-22 00:12:00 +01:00
Grégoire Paris
5ad5b11ae1 Merge pull request #11769 from HypeMC/fix-reportfieldswheredeclared
Fix fields of transient classes being considered duplicate with `reportFieldsWhereDeclared`
2025-01-20 23:48:32 +01:00
Grégoire Paris
c12fd2cb94 Merge pull request #11793 from greg0ire/doctrine-common-support
Ignore deprecations from doctrine/common
2025-01-18 22:29:13 +01:00
Grégoire Paris
44d5d4a779 Ignore deprecations from doctrine/common
These new issues are caused by doctrine/common 3.5.0, released 2 weeks
ago.
2025-01-17 08:33:24 +01:00
Stefan Gehrig
ec6d1b9f72 fixes whitespace
Signed-off-by: Stefan Gehrig <stefan.gehrig.hn@googlemail.com>
2025-01-07 08:51:19 +01:00
Stefan Gehrig
d809fed52a fixes code sniffer complaints
Signed-off-by: Stefan Gehrig <stefan.gehrig.hn@googlemail.com>
2025-01-07 08:48:42 +01:00
Stefan Gehrig
0e4786dfa8 adds testcases for order by items enclosed in ((...)) (double brackets - just one bracket does not work)
just one bracket (...) gives

Exception : [Doctrine\ORM\Query\QueryException] [Syntax Error] line 0, col xx: Error: Expected Doctrine\ORM\Query\Lexer::T_IDENTIFIER, got '('
2025-01-03 10:45:08 +01:00
Stefan Gehrig
c429262f02 adds detection of literals/result variables at the beginning of an order by item with arithmetic expression
Not sure whether this covers the whole problem regarding complex expressions in order by items but it fixes the provided test cases
2025-01-03 10:45:07 +01:00
Stefan Gehrig
f4fdcbcdcb adds more test cases 2025-01-03 10:44:17 +01:00
Stefan Gehrig
b0806469d5 adds test case for GH issue #8011 2025-01-03 10:44:17 +01:00
Grégoire Paris
e89b58a13f Merge pull request #11771 from doctrine/2.20.x-merge-up-into-2.21.x_3Yg2ZYgM
Merge release 2.20.1 into 2.21.x
2024-12-19 08:16:04 +01:00
Grégoire Paris
e3cabade99 Merge pull request #11768 from pbreteche/HINT_READ_ONLY-use-its-boolean-value
Check hint value before considering instance read-only
2024-12-19 07:48:36 +01:00
HypeMC
9402f9e0f7 Fix docs examples for mappings overrides (#11770) 2024-12-18 20:41:44 +01:00
HypeMC
4feaa470af Fix fields of transient classes being considered duplicate with reportFieldsWhereDeclared 2024-12-18 15:42:12 +01:00
Pierre Bretéché
4a9101f383 Check hint value before considering instance read-only
This fixes a bug that occurs when calling setHint(Query::HINT_READ_ONLY, false) from a query object.
UnitOfWork checks if this hint exists without considering the value passed as second argument.
Handling the second parameter improves consistency with documentation.
https://www.doctrine-project.org/projects/doctrine-orm/en/2.20/reference/improving-performance.html#read-only-entities
2024-12-18 14:55:22 +01:00
Grégoire Paris
f91da5b950 Merge pull request #11767 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-7.1.0
Bump doctrine/.github from 6.0.0 to 7.1.0
2024-12-16 08:30:26 +01:00
dependabot[bot]
66f654d4e2 Bump doctrine/.github from 6.0.0 to 7.1.0
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 6.0.0 to 7.1.0.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/6.0.0...7.1.0)

---
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-12-16 06:51:45 +00:00
Grégoire Paris
53b51ae40e Merge pull request #11613 from alexander-schranz/patch-2
Add missing generated option to documentation
2024-12-11 19:51:14 +01:00
Alexander Schranz
95b0f5c328 Add missing generated option 2024-12-11 11:55:34 +01:00
Grégoire Paris
2b94ec18b9 Merge pull request #11759 from doctrine/2.20.x
Merge 2.20.x up into 2.21.x
2024-12-08 14:33:31 +01:00
Grégoire Paris
a5c80a4c75 Provide XSD for phpcs file (#11752)
It unlocks autocompletion and validation in some IDEs.
2024-12-07 23:21:04 +01:00
Grégoire Paris
6fd26a3933 Order result (#11757)
This avoids a test flakyness observed when using PostgreSQL in the CI.
2024-12-07 22:07:23 +01:00
Grégoire Paris
8ef9253999 Upgrade to PHPStan 2 (#11756)
Some calls to assert() are no longer necessary.
2024-12-07 20:42:54 +01:00
Grégoire Paris
2a662149f4 Merge pull request #11754 from doctrine/2.20.x
Merge 2.20.x up into 2.21.x
2024-12-07 15:39:29 +01:00
Grégoire Paris
0ed0be089c Run static analysis checks on PHP 8.4 (#11753)
* Run static analysis checks on PHP 8.4

* Remove forgotten references to Psalm

* Remove invalid annotation

I do not think it achieves anything.
2024-12-07 13:36:37 +01:00
Grégoire Paris
8fb1043e96 Merge pull request #11704 from beberlei/DropPsalm-2.20
Drop Psalm
2024-12-07 12:43:18 +01:00
Benjamin Eberlei
fd041fbe80 Drop Psalm 2024-12-07 12:29:58 +01:00
Grégoire Paris
eadf96c879 Merge pull request #11743 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-6.0.0
Bump doctrine/.github from 5.3.0 to 6.0.0
2024-12-02 08:07:33 +01:00
dependabot[bot]
0d770c89d6 Bump doctrine/.github from 5.3.0 to 6.0.0
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 5.3.0 to 6.0.0.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/5.3.0...6.0.0)

---
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-12-02 06:07:53 +00:00
Grégoire Paris
37051d57ce Merge pull request #11739 from doctrine/2.20.x
Merge 2.20.x up into 2.21.x
2024-11-28 08:23:12 +01:00
Grégoire Paris
4bda5147f3 Merge pull request #11736 from greg0ire/avoid-coverage-upload
Avoid coverage upload for merge up pull requests
2024-11-28 07:54:05 +01:00
Grégoire Paris
4563f2f9a7 Merge pull request #11737 from doctrine/2.20.x
Merge 2.20.x up into 2.21.x
2024-11-27 22:10:21 +01:00
Grégoire Paris
38c6569645 Avoid coverage upload for merge up pull requests
When there are no conflicts between branches, we create pull requests
where the head branch is a branch on the origin repository. That branch
points to a commit that should already have coverage information
provided by the build that happens after merging a regular pull request.

The thing is, coverage information provided by builds that happen before
merging a pull request are associated with the commit of the head
repository. This means that when merging up 1.2 into 1.3, the build
produces coverage information that is the result of a merge between 1.2
and 1.3, and associates it with 1.2, although it is run on with a
codebase that is much closer to 1.3 (and is in fact supposed to become
1.3 after the merge).

This means that when we create a merge up PR from 1.2 to anything else,
the coverage information is going to be wrong until a PR targeting 1.2
gets merged.

I do not think we need coverage about conflictless merge up PRs more
than we need accurate numbers, so I propose we disable the upload for
those instead of, say, trying to associate them with the temporary merge
commit.
2024-11-27 21:39:44 +01:00
Grégoire Paris
7c0eebe90a Merge pull request #11733 from doctrine/dependabot/github_actions/2.20.x/doctrine/dot-github-5.3.0
Bump doctrine/.github from 5.2.0 to 5.3.0
2024-11-25 09:11:24 +01:00
dependabot[bot]
8784f2bce9 Bump doctrine/.github from 5.2.0 to 5.3.0
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/5.2.0...5.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 06:38:50 +00:00
Grégoire Paris
fbcac42ebd Merge pull request #11732 from greg0ire/phpstan-lvl-7
Raise PHPStan level to 7
2024-11-24 23:44:33 +01:00
Grégoire Paris
619302dc9a Raise PHPStan level to 7
We have a plan to drop Psalm. Before we do that, let us ensure we run
PHPStan at the level we agreed upon during the Hackathon.
2024-11-24 21:50:03 +01:00
Grégoire Paris
91201c094a Merge pull request #11722 from doctrine/2.20.x
Merge 2.20.x up into 2.21.x
2024-11-23 19:35:45 +01:00
Grégoire Paris
82e2c981da Merge pull request #11556 from k00ni/patch-1
[Docs] unitofwork.rst: php => PHP
2024-11-19 13:07:44 +01:00
Konrad Abicht
8422a41423 unitofwork.rst: php => PHP 2024-11-19 13:06:17 +01:00
Grégoire Paris
58ad1d9678 Merge pull request #11709 from lyrixx/fix-event-doc
Fix `Events::onFlush` and `PostFlush()` documentation: events are always raised
2024-11-18 22:06:18 +01:00
Grégoire Pineau
346c49832c Fix Events::onFlush and PostFlush() documentation: events are always raised
see 9e2bfa8169/src/UnitOfWork.php (L399-L413)
2024-11-18 21:51:27 +01:00
Grégoire Paris
f140651ff0 Merge pull request #11719 from greg0ire/ignore-deprecation
Ignore deprecation about StaticReflectionService
2024-11-18 21:50:12 +01:00
Grégoire Paris
bb5b2a3300 Ignore deprecation about StaticReflectionService
It is from a class that is deprecated and removed in later branches.
2024-11-18 21:46:52 +01:00
Grégoire Paris
ba11851ac4 Merge pull request #11718 from doctrine/dependabot/github_actions/2.20.x/codecov/codecov-action-5
Bump codecov/codecov-action from 4 to 5
2024-11-18 08:42:38 +01:00
dependabot[bot]
4fbce94999 Bump codecov/codecov-action from 4 to 5
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-18 06:30:54 +00:00
Grégoire Paris
486e406236 Merge pull request #10065 from goetas/lazy-eager-collection-refresh
Lazy and eager collection refresh inconsistency
2024-11-14 23:43:20 +01:00
Asmir Mustafic
7d1b24f3b1 attempt a fix 2024-11-14 20:15:56 +01:00
Asmir Mustafic
43ce0bef78 lazy and eager collection refresh 2024-11-14 20:06:32 +01:00
Grégoire Paris
d9aa6ef6dc Merge pull request #11716 from acasademont/patch-1
Add `isEmpty()` method to the Extra Lazy Associations tutorial
2024-11-14 08:03:31 +01:00
Albert Casademont
ff3ccff36a Add isEmpty() method to the Extra Lazy Associations tutorial
Extra lazy support for it was added a long time ago
(see https://github.com/doctrine/orm/pull/912) but was never properly
documented.
2024-11-13 23:59:12 +01:00
Joren Martens
14866461c5 [DDC-551] fix, add filter support in oneToOne relation 2024-11-07 10:48:16 +01:00
Indra Gunawan
9e2bfa8169 Run tests against PostgreSQL 17 (#11697)
* Run tests against PostgreSQL 17

* remove pgsql 15
2024-10-25 14:57:39 +02:00
Grégoire Paris
3ca9529c32 Merge pull request #11694 from dbannik/Bug-join-sql-when-change-sqlFilter-parameters
BUG: When changing SQLFilter parameter, resulting SQL query is not generated correctly
2024-10-23 21:23:17 +02:00
Dzmitry Bannik
439b4dacf4 Is not correctly generated sql when changed/switched sqlFilter parameters
CachedPersisterContext::$selectJoinSql should be clear or regenerated when sqlFilter changed
The problem reproduce when in use fetch=EAGER and use additional sql filter on this property
2024-10-23 12:02:03 +03:00
Grégoire Paris
a4a15ad243 Merge pull request #11687 from doctrine/2.20.x
Merge 2.20.x up into 2.21.x
2024-10-16 23:37:08 +02:00
Grégoire Paris
182469b346 Fix copy/paste/adapt mistake (#11684)
The last step was missing.
2024-10-16 22:59:19 +02:00
Grégoire Paris
e47398ecc5 Remove leftovers from Sphinx (#11683)
We use phpDocumentor/guides now, no need for this.
2024-10-16 22:08:16 +02:00
Grégoire Paris
9e884ccf1f Merge pull request #11453 from MatteoFeltrin/allow-fqcn-in-value-attribute-of-discriminator-mapping
Allow classname in 'value' attribute of xml discriminator-mapping field
2024-10-16 08:06:49 +02:00
dependabot[bot]
982d6060a3 Bump doctrine/.github from 5.1.0 to 5.2.0 (#11680) 2024-10-14 08:56:04 +02:00
Grégoire Paris
013f850c76 Merge pull request #11676 from derrabus/chore/phpunit-deprecations
Fix PHPUnit deprecations
2024-10-14 08:17:49 +02:00
Grégoire Paris
ef4508e52f Merge pull request #11667 from greg0ire/literalinclude
Experiment with literalinclude
2024-10-14 08:15:17 +02:00
Alexander M. Turek
f53350934f Psalm 5.26.1 (#11677) 2024-10-13 22:04:07 +02:00
Grégoire Paris
4ff909044e Update README (#11673) 2024-10-13 21:45:35 +02:00
Alexander M. Turek
32682aa14d Fix PHPUnit deprecations 2024-10-13 21:17:33 +02:00
dependabot[bot]
bd20df1043 Bump doctrine/.github from 5.1.0 to 5.2.0 (#11671) 2024-10-13 12:47:29 +02:00
Grégoire Paris
2ec2030ab2 Experiment with literalinclude
I think it would be great to use literalinclude for big code snippets,
because our IDEs could warn us about issues, and it would be easily to
showcase our coding standard. Before we do that though, let us validate
that it renders as expected. I have picked a complex example where we
have a configuration block.
2024-10-12 15:46:50 +02:00
Grégoire Paris
8ed6c2234a Merge pull request #11661 from doctrine/2.19.x
Merge 2.19.x up into 2.20.x
2024-10-11 13:47:24 +02:00
Grégoire Paris
ff612b9678 Merge pull request #11660 from simPod/test-method
test: cover all transactional methods in `EntityManagerTest::testItPreservesTheOriginalExceptionOnRollbackFailure()`
2024-10-11 13:11:31 +02:00
Simon Podlipsky
ee0d7197dd test: cover all transactional methods in EntityManagerTest::testItPreservesTheOriginalExceptionOnRollbackFailure() 2024-10-11 13:00:52 +02:00
Matthias Pigulla
39d2136f46 Fix different first/max result values taking up query cache space (#11188)
* Add a test covering the #11112 issue

* Add new OutputWalker and SqlFinalizer interfaces

* Add a SingleSelectSqlFinalizer that can take care of adding offset/limit as well as locking mode statements to a given SQL query.

Add a FinalizedSelectExecutor that executes given, finalized SQL statements.

* In SqlWalker, split SQL query generation into the two parts that shall happen before and after the finalization phase.

Move the part that generates "pre-finalization" SQL into a dedicated method. Use a side channel in SingleSelectSqlFinalizer to access the "finalization" logic and avoid duplication.

* Fix CS violations

* Skip the GH11112 test while applying refactorings

* Avoid a Psalm complaint due to invalid (?) docblock syntax

* Establish alternate code path - queries can obtain the sql executor through the finalizer, parser knows about output walkers yielding finalizers

* Remove a possibly premature comment

* Re-enable the #11112 test

* Fix CS

* Make RootTypeWalker inherit from SqlOutputWalker so it becomes finalizer-aware

* Update QueryCacheTest, since first/max results no longer need extra cache entries

* Fix ParserResultSerializationTest by forcing the parser to produce a ParserResult of the old kind (with the executor already constructed)

* Fix WhereInWalkerTest

* Update lib/Doctrine/ORM/Query/Exec/PreparedExecutorFinalizer.php

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

* Fix tests

* Fix a Psalm complaint

* Fix a test

* Fix CS

* Make the NullSqlWalker an instance of SqlOutputWalker

* Avoid multiple cache entries caused by LimitSubqueryOutputWalker

* Fix Psalm complaints

* Fix static analysis complaints

* Remove experimental code that I committed accidentally

* Remove unnecessary baseline entry

* Make AddUnknownQueryComponentWalker subclass SqlOutputWalker

That way, we have no remaining classes in the codebase subclassing SqlWalker but not SqlOutputWalker

* Use more expressive exception classes

* Add a deprecation message

* Move SqlExecutor creation to ParserResult, to minimize public methods available on it

* Avoid keeping the SqlExecutor in the Query, since it must be generated just in time (e. g. in case Query parameters change)

* Address PHPStan complaints

* Fix tests

* Small refactorings

* Add an upgrade notice

* Small refactorings

* Update the Psalm baseline

* Add a missing namespace import

* Update Psalm baseline

* Fix CS

* Fix Psalm baseline

---------

Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2024-10-10 15:15:08 +02:00
Benjamin Eberlei
bea454eefc [GH-8471] undeprecate partials completly (#11647)
* [GH-8471] Undeprecate all PARTIAL object usage.
2024-10-10 13:54:34 +02:00
Grégoire Paris
14f2572e4e Merge pull request #11656 from doctrine/2.19.x
Merge 2.19.x up into 2.20.x
2024-10-10 13:53:05 +02:00
Grégoire Paris
c2c500077b Merge pull request #11646 from greg0ire/finally-fix-bug
Run risky code in finally block
2024-10-10 11:46:49 +02:00
Grégoire Paris
6281c2b79f Merge pull request #11655 from greg0ire/submodule-cleanup
Submodule cleanup
2024-10-10 11:12:12 +02:00
Grégoire Paris
bac1c17eab Remove submodule remnant
This should make a warning we have in the CI go away.

>  fatal: No url found for submodule path 'docs/en/_theme' in .gitmodules
2024-10-10 11:07:38 +02:00
Grégoire Paris
b6137c8911 Add guard clause
It maybe happen that the SQL COMMIT statement is successful, but then
something goes wrong. In that kind of case, you do not want to attempt a
rollback.

This was implemented in UnitOfWork::commit(), but for some reason not in
the similar EntityManager methods.
2024-10-10 10:58:24 +02:00
Grégoire Paris
51be1b1d52 Run risky code in finally block
catch blocks are not supposed to fail. If you want to do something
despite an exception happening, you should do it in a finally block.

Closes #7545
2024-10-10 10:06:12 +02:00
Alexander M. Turek
488a5dd3bf Remove vendor prefix of PHPDoc referencing class-string (#11643) 2024-10-09 21:58:37 +02:00
Matthias Pigulla
896c65504d Deprecate the \Doctrine\ORM\Query\Parser::setCustomOutputTreeWalker() method (#11641)
We use this method only from within one of our own test cases, and I don't see how it would be useful to anybody else outside – it has to be called on the `Parser` instance which exists internally in the `Query` only.

Deprecating and removing it in 3.x allows for a slight simplification in the `Parser` there, since we do no longer need the field (it can be a local variable).
2024-10-09 16:12:41 +02:00
Matthias Pigulla
16a8f10fd2 Remove a misleading comment (#11644) 2024-10-09 15:37:04 +02:00
Alexander M. Turek
d80a831157 Stop recommending vendor-prefixed PHPDoc (#11640) 2024-10-09 14:48:42 +02:00
Alexander M. Turek
52660297ab Let PHPStan detect deprecated usages (#11639) 2024-10-09 14:47:57 +02:00
Alexander M. Turek
58287bb731 Merge branch '2.19.x' into 2.20.x
* 2.19.x:
  PHPStan 1.12.6 (#11635)
2024-10-09 11:08:42 +02:00
Alexander M. Turek
bc37f75b41 PHPStan 1.12.6 (#11635) 2024-10-09 11:08:02 +02:00
Grégoire Paris
8a25b264f7 Add upgrade note about property hooks (#11636)
People that might have experimented with property hooks while still
using ORM < 2.20.0 need to know that they need to remove their
experiment or upgrade to a version that explicitly supports them.
2024-10-09 11:05:58 +02:00
Benjamin Eberlei
0e48b19cd3 Prepare PHP 8.4 support: Prevent property hooks from being used (#11628)
Prevent property hooks from being used as they currently would work on external non-raw values without explicit code.
2024-10-09 10:36:21 +02:00
Grégoire Paris
109042e5af Merge pull request #11631 from greg0ire/php84-ci
Add CI job for PHP 8.4
2024-10-09 09:42:08 +02:00
Grégoire Paris
08328adc6c Use E_ALL instead of E_ALL | E_STRICT
E_STRICT is deprecated as of PHP 8.4
2024-10-09 09:19:32 +02:00
Grégoire Paris
65806884b0 Add CI job for PHP 8.4
For now doctrine/common generates proxies that trigger deprecation, so
let us only test with lazy ghosts only.
2024-10-08 17:56:38 +02:00
Alexander M. Turek
ad80e8281a Merge branch '2.19.x' into 2.20.x
* 2.19.x:
  Replace custom directives with native option
2024-10-08 15:54:57 +02:00
Grégoire Paris
0c0c61c51b Merge pull request #11627 from greg0ire/no-custom-directives
Replace custom directives with native option
2024-10-08 15:26:44 +02:00
Grégoire Paris
cc28fed9f5 Replace custom directives with native option 2024-10-08 14:43:18 +02:00
Alexander M. Turek
2245149588 Merge branch '2.19.x' into 2.20.x
* 2.19.x:
  Make nullable parameters explicit in generated entities (#11625)
  Update attributes-reference.rst
  Bump doctrine/.github from 5.0.1 to 5.1.0 (#11616)
  Move orphan metadata to where it belongs
  PHPStan 1.12 (#11585)
2024-10-08 12:26:50 +02:00
Alexander M. Turek
b13564c6c0 Make nullable parameters explicit in generated entities (#11625) 2024-10-08 12:25:31 +02:00
Max Mustermann
91709c1275 fix generating duplicate method stubs
When adding the same lifecycle event callback to two or more lifecycle events, the generator will create a stub for each event resulting in fatal 'Cannot redeclare' errors. That is, only if the callback name contains uppercase letters.
2024-10-05 13:40:04 +02:00
Grégoire Paris
d18126aac5 Merge pull request #11618 from n0099/patch-1
unclosed `]` in attributes-reference.rst
2024-10-01 17:27:04 +02:00
n0099
b7fd8241cf Update attributes-reference.rst 2024-10-01 21:19:44 +08:00
dependabot[bot]
2432939e4f Bump doctrine/.github from 5.0.1 to 5.1.0 (#11616)
Bumps [doctrine/.github](https://github.com/doctrine/.github) from 5.0.1 to 5.1.0.
- [Release notes](https://github.com/doctrine/.github/releases)
- [Commits](https://github.com/doctrine/.github/compare/5.0.1...5.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 09:04:06 +02:00
Grégoire Paris
1bf4603422 Merge pull request #11615 from greg0ire/move-orphan
Move orphan metadata to where it belongs
2024-09-29 09:22:54 +02:00
Grégoire Paris
25d5bc5b46 Move orphan metadata to where it belongs
The goal here was to retain compatibility with doctrine/rst-parser,
which is no longer in use in the website.
2024-09-27 19:42:13 +02:00
Alexander M. Turek
6cde337777 PHPStan 1.12 (#11585) 2024-08-27 12:10:07 +02:00
Grégoire Paris
74ef28295a Merge pull request #11582 from doctrine/2.19.x-merge-up-into-2.20.x_0oKsBvVN
Merge release 2.19.7 into 2.20.x
2024-08-23 12:29:43 +02:00
Grégoire Paris
168ac31084 Merge pull request #11109 from mcurland/Fix11108
Original entity data resolves inverse 1-1 joins
2024-08-23 08:54:57 +02:00
Matthew Curland
fe4a2e83cf Original entity data resolves inverse 1-1 joins
If the source entity for an inverse (non-owning) 1-1 relationship is
identified by an association then the identifying association may not
be set when an inverse one-to-one association is resolved. This means
that no data is available in the entity to resolve the needed column
value for the join query.

The original entity data can be retrieved from the unit of work and
is used as a fallback to populate the query condition.

Fixes #11108
2024-08-17 11:50:56 +02:00
Grégoire Paris
8ac6a13ca0 Merge pull request #11564 from gitbugr/GH11501_fix_o2m_persister_single_inheritence_parent_relation_bugfix
GH11551 - fix OneToManyPersister::deleteEntityCollection case where single-inheritence table parent entity is targetEntity.
2024-08-05 07:47:46 +02:00
gitbugr
2707b09a07 fix spacing
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2024-08-03 21:38:49 +01:00
Kyron Taylor
121158f92c GH11551 - fix OneToManyPersister::deleteEntityCollection when using
single-inheritence entity parent as targetEntity.

When using the parent entity for a single-inheritence table as the
targetEntity for a property, the discriminator value should be all
of the values in the discriminator map.
OneToManyPersister::deleteEntityCollection has been amended to
reflect this.
2024-08-03 16:55:14 +01:00
Grégoire Paris
51ad860a25 Merge pull request #11543 from stof/fix_native_query_parameter_type
Fix the support for custom parameter types in native queries
2024-07-04 20:12:59 +02:00
Christophe Coevoet
9bd51aaeb6 Fix the support for custom parameter types in native queries
The Query class (used for DQL queries) takes care of using the value and
type as is when a type was specified for a parameter instead of going
through the default processing of values.
The NativeQuery class was missing the equivalent check, making the
custom type work only if the default processing of values does not
convert the value to a different one.
2024-07-04 16:25:34 +02:00
Grégoire Paris
c37b115450 Merge pull request #11534 from k00ni/patch-1
working-with-objects.rst: added missing white space
2024-06-28 09:03:54 +02:00
Konrad Abicht
19129e9f8a working-with-objects.rst: added missing white space 2024-06-28 09:00:12 +02:00
Grégoire Paris
7d01f19667 Merge pull request #11531 from doctrine/2.19.x-merge-up-into-2.20.x_QMtlHSin
Merge release 2.19.6 into 2.20.x
2024-06-27 17:50:50 +02:00
Grégoire Paris
c1bb2ccf4b Merge pull request #11526 from GromNaN/patch-1
doc: Use modern array syntax in getting started
2024-06-26 19:24:40 +02:00
Jérôme Tamarelle
e3d7c6076c Use modern array syntax in the doc 2024-06-26 19:18:32 +02:00
Grégoire Paris
40f299f1eb Merge pull request #11506 from michalbundyra/composite-key-relations-3
[2.19.x] Fetching entities with Composite Key Relations and null values
2024-06-21 08:12:27 +02:00
Grégoire Paris
d0e9177121 Merge pull request #11514 from doctrine/2.19.x
Merge 2.19.x up into 2.20.x
2024-06-20 22:51:33 +02:00
Grégoire Paris
68af854f46 Merge pull request #11513 from greg0ire/address-persistence-3.3.3-release
Address doctrine/persistence 3.3.3 release
2024-06-20 22:14:52 +02:00
Grégoire Paris
77467cd824 Address doctrine/persistence 3.3.3 release
FileDriver became templatable, and some very wrong phpdoc has been
fixed, causing Psalm to better understand the 2 FileDriver classes in
this project.
2024-06-20 22:00:33 +02:00
Grégoire Paris
802f20b8e7 Merge pull request #11509 from greg0ire/remove-unneeded-rule
Remove unneeded CS rule
2024-06-19 23:49:15 +02:00
Michał Bundyra
96d13ac62a Fetching entities with Composite Key Relations and null values
Remove redundant condition to check if target class contains foreign
identifier in order to allow fetching a null for relations with
composite keys, when part of the key value is null.
2024-06-19 21:54:02 +01:00
Grégoire Paris
2ea6a1a5fb Remove unneeded CS rule 2024-06-19 21:47:55 +02:00
Alexander M. Turek
83851a9716 Merge branch '2.19.x' into 2.20.x
* 2.19.x:
  Fix OneToManyPersister::deleteEntityCollection missing discriminator column/value. (GH-11500)
  Skip joined entity creation for empty relation (#10889)
  ci: maintained and stable mariadb version (11.4 current lts) (#11490)
  fix(docs): use string value in `addAttribute`
  Replace assertion with exception (#11489)
  Use ramsey/composer-install in PHPBench workflow
  update EntityManager#transactional to EntityManager#wrapInTransaction
  Fix cloning entities
  Consider usage of setFetchMode when checking for simultaneous usage of fetch-mode EAGER and WITH condition.
2024-06-18 14:19:19 +02:00
Alexander M. Turek
066ec1ac81 Fix upgrade guide for 2.20 (#11504) 2024-06-18 14:18:37 +02:00
Benjamin Eberlei
68744489f0 Undeprecate PARTIAL for array hydration. (#11366)
* Undeprecate PARTIAL for array hydration.

* note about undeprecate partial in UPGRADE.md
2024-06-18 14:15:31 +02:00
Grégoire Paris
cc2ad1993c Merge pull request #11501 from gitbugr/2.19.x
Fix OneToManyPersister::deleteEntityCollection missing discriminator column/value. (GH-11500)
2024-06-17 21:40:07 +02:00
Kyron Taylor
e4d46c4276 Fix OneToManyPersister::deleteEntityCollection missing discriminator column/value. (GH-11500) 2024-06-15 21:58:08 +01:00
Grégoire Paris
858a1adc3b Merge pull request #11194 from noemi-salaun/fix/gh10889
Skip joined entity creation for empty relation (#10889)
2024-06-14 20:06:59 +02:00
Noemi Salaun
3b499132d9 Skip joined entity creation for empty relation (#10889) 2024-06-14 14:34:04 +02:00
Daniel Black
39153fd88a ci: maintained and stable mariadb version (11.4 current lts) (#11490)
Also use MARIADB env names and the healthcheck.sh included in the container.
2024-06-13 19:34:46 +02:00
Grégoire Paris
bdc9679e37 Merge pull request #11493 from SamMousa/fix-docs-11492
fix(docs): use string value in `addAttribute`
2024-06-11 15:26:45 +01:00
Sam Mousa
87a8ee21c9 fix(docs): use string value in addAttribute 2024-06-11 16:21:28 +02:00
Grégoire Paris
59c8bc09ab Replace assertion with exception (#11489) 2024-06-03 23:08:27 +02:00
Grégoire Paris
3a7d7c9f57 Merge pull request #11484 from greg0ire/backport-ramsey
Use ramsey/composer-install in PHPBench workflow
2024-06-02 15:26:00 +02:00
Grégoire Paris
06eca40134 Use ramsey/composer-install in PHPBench workflow
It will handle caching for us.
2024-06-02 15:22:59 +02:00
Grégoire Paris
23b35e9554 Merge pull request #11475 from nicolas-grekas/fix-clone
Fix cloning entities
2024-06-01 22:47:57 +02:00
Grégoire Paris
e063926cbd Merge pull request #11445 from aprat84/gh-11128
Consider usage of setFetchMode when checking for simultaneous usage of fetch-mode EAGER and WITH condition
2024-05-30 17:24:11 +02:00
Grégoire Paris
4a01a76a17 Merge pull request #11460 from IndraGunawan/update-transactional-doc
docs: update EntityManager#transactional to EntityManager#wrapInTransaction
2024-05-28 14:07:06 +02:00
Indra Gunawan
93c2dd9d4b update EntityManager#transactional to EntityManager#wrapInTransaction
One has been deprecated in favor of the other.
2024-05-28 13:59:17 +02:00
Nicolas Grekas
75bc22980e Fix cloning entities 2024-05-27 14:53:58 +02:00
Alix Mauro
9696c3434d Consider usage of setFetchMode when checking for simultaneous usage of fetch-mode EAGER and WITH condition.
This fixes a bug that arises when an entity relation is mapped with
fetch-mode EAGER but setFetchMode LAZY (or anything that is not EAGER)
has been used on the query. If the query use WITH condition, an
exception is incorrectly raised (Associations with fetch-mode=EAGER may
not be using WITH conditions).

Fixes #11128

Co-Authored-By: Albert Prat <albert.prat@interactiu.cat>
2024-05-25 14:22:20 +02:00
Alexander M. Turek
bf3e082c00 Merge branch '2.19.x' into 2.20.x
* 2.19.x:
  Psalm 5.24.0 (#11467)
  PHPStan 1.11.1 (#11466)
  Test with actual lock modes (#11465)
  Backport test for Query::setLockMode() (#11463)
2024-05-21 14:22:18 +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
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
eb49f66926 Merge branch '2.19.x' into 2.20.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:40:37 +02:00
MatteoFeltrin
73e30df52b allow classname in 'value' attribute of xml discriminator-mapping field 2024-05-20 11:00:23 +02: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
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
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
8b6a58fa0e Merge pull request #11432 from doctrine/2.19.x-merge-up-into-2.20.x_IfraK93L
Merge release 2.19.5 into 2.20.x
2024-04-30 09:04:52 +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
b725908c83 Merge branch '2.19.x' into 2.20.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:26:53 +02:00
Alexander M. Turek
b274893486 Fix BIGINT validation (#11414) 2024-04-15 15:11:10 +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
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
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
Alexander M. Turek
be307edba8 Merge release 2.19.3 into 2.20.x (#11398) 2024-03-22 12:11:39 +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
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
083f642cfa Merge branch '2.19.x' into 2.20.x
* 2.19.x:
  Remove unused variable (#11391)
2024-03-21 10:33:34 +01:00
Alexander M. Turek
db6e702088 Remove unused variable (#11391) 2024-03-21 10:32:55 +01:00
Alexander M. Turek
716da7e538 Merge branch '2.19.x' into 2.20.x
* 2.19.x:
  [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 10:12:37 +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
bcdc5bdaf4 Merge pull request #11378 from doctrine/2.19.x-merge-up-into-2.20.x_eyF2lMAL
Merge release 2.19.2 into 2.20.x
2024-03-18 20:22:04 +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
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
a3e3a3bbf3 Merge pull request #11360 from doctrine/2.19.x-merge-up-into-2.20.x_aXnS7Xw9
Merge release 2.19.1 into 2.20.x
2024-03-16 21:32:18 +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
a809a71aa6 Prepare releases 2.19 and 3.1 (#11335) 2024-03-03 18:43:41 +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
Benjamin Eberlei
e62571c8f4 Refator array_map into simple loop for performance. (#11332) 2024-03-02 23:11:11 +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
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
Alexander M. Turek
feb27f00c1 Address deprecations from Collection 2.2 (#11315) 2024-02-27 17:37:52 +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
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
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
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
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
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
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
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
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
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
1d218bae30 Make docs valid according to guides 0.3.3 (#11252) 2024-02-12 23:46:09 +01:00
Alexander M. Turek
7baef1e120 Remove references to deprecated constants from Lexer (#11234) 2024-02-07 15:39:20 +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
Grégoire Paris
40fbbf4429 Point link to correct upgrade guide (#11220) 2024-02-04 17:41:45 +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
cfadb5499d Merge pull request #11207 from derrabus/chore/readme
Update branches in README
2024-02-03 20:06:12 +01:00
Alexander M. Turek
9ce9ae2818 Update branches in README 2024-02-03 19:43:49 +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
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
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
Jonathan H. Wage
d386b43be3 Remove XML validation disabling deprecation. 2024-01-26 09:59:03 -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
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
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
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
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
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
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
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
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
Yonel Ceruto
7613f25d57 Adds metadata field type and enumType validation against Entity property type 2023-11-06 08:23:58 -05:00
1730 changed files with 17790 additions and 8672 deletions

View File

@@ -6,22 +6,52 @@
"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",
"upcoming": true
"maintained": false
},
{
"name": "2.17",
"branchName": "2.17.x",
"slug": "2.17",
"current": true
"maintained": false
},
{
"name": "2.16",

3
.gitattributes vendored
View File

@@ -11,7 +11,6 @@ build.properties.dev export-ignore
build.xml export-ignore
CONTRIBUTING.md export-ignore
phpunit.xml.dist export-ignore
run-all.sh export-ignore
phpcs.xml.dist export-ignore
phpbench.json export-ignore
phpstan.neon export-ignore
@@ -19,5 +18,3 @@ phpstan-baseline.neon export-ignore
phpstan-dbal2.neon export-ignore
phpstan-params.neon export-ignore
phpstan-persistence2.neon export-ignore
psalm.xml export-ignore
psalm-baseline.xml export-ignore

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@v12.2.0"

20
.github/workflows/composer-lint.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: "Composer Lint"
on:
pull_request:
branches:
- "*.x"
paths:
- ".github/workflows/composer-lint.yml"
- "composer.json"
push:
branches:
- "*.x"
paths:
- ".github/workflows/composer-lint.yml"
- "composer.json"
jobs:
composer-lint:
name: "Composer Lint"
uses: "doctrine/.github/.github/workflows/composer-lint.yml@v12.2.0"

View File

@@ -1,4 +1,4 @@
name: "Continuous Integration"
name: "CI"
on:
pull_request:
@@ -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/**
@@ -40,6 +40,8 @@ jobs:
- "8.1"
- "8.2"
- "8.3"
- "8.4"
- "8.5"
dbal-version:
- "default"
extension:
@@ -63,7 +65,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v5"
with:
fetch-depth: 2
@@ -80,7 +82,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+"
@@ -97,9 +99,9 @@ jobs:
ORM_PROXY_IMPLEMENTATION: "${{ matrix.proxy }}"
- name: "Upload coverage file"
uses: "actions/upload-artifact@v3"
uses: "actions/upload-artifact@v5"
with:
name: "phpunit-${{ matrix.extension }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-coverage"
name: "phpunit-${{ matrix.extension }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-${{ matrix.proxy }}-coverage"
path: "coverage*.xml"
@@ -113,11 +115,13 @@ jobs:
php-version:
- "8.2"
- "8.3"
- "8.4"
- "8.5"
dbal-version:
- "default"
- "3@dev"
postgres-version:
- "15"
- "17"
extension:
- pdo_pgsql
- pgsql
@@ -145,7 +149,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v5"
with:
fetch-depth: 2
@@ -162,7 +166,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+"
@@ -170,9 +174,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@v5"
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"
@@ -186,11 +190,13 @@ jobs:
php-version:
- "8.2"
- "8.3"
- "8.4"
- "8.5"
dbal-version:
- "default"
- "3@dev"
mariadb-version:
- "10.9"
- "11.4"
extension:
- "mysqli"
- "pdo_mysql"
@@ -204,18 +210,18 @@ jobs:
mariadb:
image: "mariadb:${{ matrix.mariadb-version }}"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: "doctrine_tests"
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: yes
MARIADB_DATABASE: "doctrine_tests"
options: >-
--health-cmd "mysqladmin ping --silent"
--health-cmd "healthcheck.sh --connect --innodb_initialized"
ports:
- "3306:3306"
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v5"
with:
fetch-depth: 2
@@ -232,7 +238,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+"
@@ -240,7 +246,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@v5"
with:
name: "${{ github.job }}-${{ matrix.mariadb-version }}-${{ matrix.extension }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-coverage"
path: "coverage.xml"
@@ -256,6 +262,8 @@ jobs:
php-version:
- "8.2"
- "8.3"
- "8.4"
- "8.5"
dbal-version:
- "default"
- "3@dev"
@@ -285,7 +293,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v5"
with:
fetch-depth: 2
@@ -302,7 +310,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+"
@@ -317,7 +325,7 @@ jobs:
ENABLE_SECOND_LEVEL_CACHE: 1
- name: "Upload coverage files"
uses: "actions/upload-artifact@v3"
uses: "actions/upload-artifact@v5"
with:
name: "${{ github.job }}-${{ matrix.mysql-version }}-${{ matrix.extension }}-${{ matrix.php-version }}-${{ matrix.dbal-version }}-coverage"
path: "coverage*.xml"
@@ -337,7 +345,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v5"
with:
fetch-depth: 2
@@ -348,7 +356,7 @@ jobs:
ini-values: "zend.assertions=1, apc.enable_cli=1"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
uses: "ramsey/composer-install@v3"
with:
dependency-versions: "${{ matrix.deps }}"
@@ -359,6 +367,8 @@ jobs:
upload_coverage:
name: "Upload coverage to Codecov"
runs-on: "ubuntu-22.04"
# Only run on PRs from forks
if: "github.event.pull_request.head.repo.full_name != github.repository"
needs:
- "phpunit-smoke-check"
- "phpunit-postgres"
@@ -367,16 +377,18 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v5"
with:
fetch-depth: 2
- name: "Download coverage files"
uses: "actions/download-artifact@v3"
uses: "actions/download-artifact@v6"
with:
path: "reports"
- name: "Upload to Codecov"
uses: "codecov/codecov-action@v3"
uses: "codecov/codecov-action@v5"
with:
directory: reports
env:
CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}"

View File

@@ -5,44 +5,16 @@ on:
branches:
- "*.x"
paths:
- .github/workflows/documentation.yml
- docs/**
- ".github/workflows/documentation.yml"
- "docs/**"
push:
branches:
- "*.x"
paths:
- .github/workflows/documentation.yml
- docs/**
- ".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.2"
- 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@v2"
with:
dependency-versions: "highest"
- name: "Add dummy title to the sidebar"
run: |
printf '%s\n%s\n\n%s\n' "Dummy title" "===========" "$(cat docs/en/sidebar.rst)" > docs/en/sidebar.rst
- name: "Run guides-cli"
run: "vendor/bin/guides -vvv --no-progress docs/en 2>&1 | grep -v 'Unknown directive' | ( ! grep WARNING )"
documentation:
name: "Documentation"
uses: "doctrine/.github/.github/workflows/documentation.yml@v12.2.0"

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/**
@@ -36,7 +36,7 @@ jobs:
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: "actions/checkout@v5"
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@v12.2.0"
secrets:
GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}

View File

@@ -7,20 +7,18 @@ 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:
@@ -42,13 +40,13 @@ jobs:
steps:
- name: "Checkout code"
uses: "actions/checkout@v4"
uses: "actions/checkout@v5"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "8.2"
php-version: "8.4"
- name: "Require specific DBAL version"
run: "composer require doctrine/dbal ^${{ matrix.dbal-version }} --no-update"
@@ -58,7 +56,7 @@ jobs:
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"
uses: "ramsey/composer-install@v3"
with:
dependency-versions: "highest"
@@ -73,31 +71,3 @@ jobs:
- 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'}}"
static-analysis-psalm:
name: "Static Analysis with Psalm"
runs-on: "ubuntu-22.04"
strategy:
fail-fast: false
steps:
- name: "Checkout code"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "8.2"
- name: "Require specific persistence version"
run: "composer require doctrine/persistence ^3.1 --no-update"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
with:
dependency-versions: "highest"
- name: "Run a static analysis with vimeo/psalm"
run: "vendor/bin/psalm --show-info=false --stats --output-format=github --threads=$(nproc)"

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.
@@ -57,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/2.8.x/tests/Tests/ORM/Functional/Ticket/DDC2306Test.php` for an
example.
## Getting merged

View File

@@ -1,7 +1,7 @@
| [3.0.x][3.0] | [2.16.x][2.16] | [2.15.x][2.15] |
|:----------------:|:----------------:|:----------:|
| [![Build status][3.0 image]][3.0] | [![Build status][2.16 image]][2.16] | [![Build status][2.15 image]][2.15] |
| [![Coverage Status][3.0 coverage image]][3.0 coverage]| [![Coverage Status][2.16 coverage image]][2.16 coverage] | [![Coverage Status][2.15 coverage image]][2.15 coverage] |
| [4.0.x][4.0] | [3.6.x][3.6] | [3.5.x][3.5] | [2.21.x][2.21] | [2.20.x][2.20] |
|:------------------------------------------------------:|:------------------------------------------------------:|:------------------------------------------------------:|:--------------------------------------------------------:|:--------------------------------------------------------:|
| [![Build status][4.0 image]][4.0 workflow] | [![Build status][3.6 image]][3.6 workflow] | [![Build status][3.5 image]][3.5 workflow] | [![Build status][2.21 image]][2.21 workflow] | [![Build status][2.20 image]][2.20 workflow] |
| [![Coverage Status][4.0 coverage image]][4.0 coverage] | [![Coverage Status][3.6 coverage image]][3.6 coverage] | [![Coverage Status][3.5 coverage image]][3.5 coverage] | [![Coverage Status][2.21 coverage image]][2.21 coverage] | [![Coverage Status][2.20 coverage image]][2.20 coverage] |
[<h1 align="center">🇺🇦 UKRAINE NEEDS YOUR HELP NOW!</h1>](https://www.doctrine-project.org/stop-war.html)
@@ -18,15 +18,28 @@ 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.16 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.16.x
[2.16]: https://github.com/doctrine/orm/tree/2.16.x
[2.16 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.16.x/graph/badge.svg
[2.16 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.16.x
[2.15 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.15.x
[2.15]: https://github.com/doctrine/orm/tree/2.15.x
[2.15 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.15.x/graph/badge.svg
[2.15 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.15.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 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A4.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.6 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.6.x
[3.6]: https://github.com/doctrine/orm/tree/3.6.x
[3.6 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A3.6.x
[3.6 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.6.x/graph/badge.svg
[3.6 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.6.x
[3.5 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.5.x
[3.5]: https://github.com/doctrine/orm/tree/3.5.x
[3.5 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A3.5.x
[3.5 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.5.x/graph/badge.svg
[3.5 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.5.x
[2.21 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=2.21.x
[2.21]: https://github.com/doctrine/orm/tree/2.21.x
[2.21 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A2.21.x
[2.21 coverage image]: https://codecov.io/gh/doctrine/orm/branch/2.21.x/graph/badge.svg
[2.21 coverage]: https://codecov.io/gh/doctrine/orm/branch/2.21.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 workflow]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml?query=branch%3A2.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

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,56 @@
# Upgrade to 2.20
## Add `Doctrine\ORM\Query\OutputWalker` interface, deprecate `Doctrine\ORM\Query\SqlWalker::getExecutor()`
Output walkers should implement the new `\Doctrine\ORM\Query\OutputWalker` interface and create
`Doctrine\ORM\Query\Exec\SqlFinalizer` instances instead of `Doctrine\ORM\Query\Exec\AbstractSqlExecutor`s.
The output walker must not base its workings on the query `firstResult`/`maxResult` values, so that the
`SqlFinalizer` can be kept in the query cache and used regardless of the actual `firstResult`/`maxResult` values.
Any operation dependent on `firstResult`/`maxResult` should take place within the `SqlFinalizer::createExecutor()`
method. Details can be found at https://github.com/doctrine/orm/pull/11188.
## Explictly forbid property hooks
Property hooks are not supported yet by Doctrine ORM. Until support is added,
they are explicitly forbidden because the support would result in a breaking
change in behavior.
Progress on this is tracked at https://github.com/doctrine/orm/issues/11624 .
## PARTIAL DQL syntax is undeprecated
Use of the PARTIAL keyword is not deprecated anymore in DQL, because we will be
able to support PARTIAL objects with PHP 8.4 Lazy Objects and
Symfony/VarExporter in a better way. When we decided to remove this feature
these two abstractions did not exist yet.
WARNING: If you want to upgrade to 3.x and still use PARTIAL keyword in DQL
with array or object hydrators, then you have to directly migrate to ORM 3.3.x or higher.
PARTIAL keyword in DQL is not available in 3.0, 3.1 and 3.2 of ORM.
## Deprecate `\Doctrine\ORM\Query\Parser::setCustomOutputTreeWalker()`
Use the `\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER` query hint to set the output walker
class instead of setting it through the `\Doctrine\ORM\Query\Parser::setCustomOutputTreeWalker()` method
on the parser instance.
# 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
@@ -1235,7 +1288,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

@@ -27,7 +27,7 @@
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
<directory suffix=".php">../../../src</directory>
</whitelist>
</filter>

View File

@@ -27,7 +27,7 @@
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
<directory suffix=".php">../../../src</directory>
</whitelist>
</filter>

View File

@@ -27,7 +27,7 @@
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
<directory suffix=".php">../../../src</directory>
</whitelist>
</filter>

View File

@@ -25,7 +25,7 @@
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
<directory suffix=".php">../../../src</directory>
</whitelist>
</filter>

View File

@@ -27,7 +27,7 @@
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
<directory suffix=".php">../../../src</directory>
</whitelist>
</filter>

View File

@@ -25,7 +25,7 @@
<filter>
<whitelist>
<directory suffix=".php">../../../lib/Doctrine</directory>
<directory suffix=".php">../../../src</directory>
</whitelist>
</filter>

View File

@@ -1,28 +1,39 @@
{
"name": "doctrine/orm",
"type": "library",
"description": "Object-Relational-Mapper for PHP",
"keywords": ["orm", "database"],
"homepage": "https://www.doctrine-project.org/projects/orm.html",
"license": "MIT",
"authors": [
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
{"name": "Marco Pivetta", "email": "ocramius@gmail.com"}
"type": "library",
"keywords": [
"orm",
"database"
],
"config": {
"allow-plugins": {
"composer/package-versions-deprecated": true,
"dealerdirect/phpcodesniffer-composer-installer": true
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
"sort-packages": true
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
}
],
"homepage": "https://www.doctrine-project.org/projects/orm.html",
"require": {
"php": "^7.1 || ^8.0",
"composer-runtime-api": "^2",
"ext-ctype": "*",
"composer-runtime-api": "^2",
"doctrine/cache": "^1.12.1 || ^2.1.1",
"doctrine/collections": "^1.5 || ^2.1",
"doctrine/common": "^3.0.3",
@@ -31,7 +42,7 @@
"doctrine/event-manager": "^1.2 || ^2",
"doctrine/inflector": "^1.4 || ^2.0",
"doctrine/instantiator": "^1.3 || ^2",
"doctrine/lexer": "^2",
"doctrine/lexer": "^2 || ^3",
"doctrine/persistence": "^2.4 || ^3",
"psr/cache": "^1 || ^2 || ^3",
"symfony/console": "^4.2 || ^5.0 || ^6.0 || ^7.0",
@@ -40,16 +51,16 @@
},
"require-dev": {
"doctrine/annotations": "^1.13 || ^2",
"doctrine/coding-standard": "^9.0.2 || ^12.0",
"doctrine/coding-standard": "^9.0.2 || ^14.0",
"phpbench/phpbench": "^0.16.10 || ^1.0",
"phpstan/phpstan": "~1.4.10 || 1.10.35",
"phpstan/extension-installer": "~1.1.0 || ^1.4",
"phpstan/phpstan": "~1.4.10 || 2.1.23",
"phpstan/phpstan-deprecation-rules": "^1 || ^2",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6",
"psr/log": "^1 || ^2 || ^3",
"squizlabs/php_codesniffer": "3.7.2",
"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.15.0"
"symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0",
"symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0",
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"conflict": {
"doctrine/annotations": "<1.13 || >= 3.0"
@@ -60,17 +71,29 @@
"symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
},
"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\\Performance\\": "tests/Performance",
"Doctrine\\StaticAnalysis\\": "tests/StaticAnalysis",
"Doctrine\\Tests\\": "tests/Tests"
}
},
"bin": ["bin/doctrine"],
"archive": {
"exclude": ["!vendor", "tests", "*phpunit.xml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor", "*.swp"]
"bin": [
"bin/doctrine"
],
"config": {
"allow-plugins": {
"composer/package-versions-deprecated": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true
},
"sort-packages": true
},
"scripts": {
"docs": "composer --working-dir docs update && ./docs/vendor/bin/build-docs.sh @additional_args"
}
}

7
docs/.gitignore vendored
View File

@@ -1,4 +1,3 @@
en/_exts/configurationblock.pyc
build
en/_build
.idea
composer.lock
vendor/
output/

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

@@ -1,18 +1,18 @@
# Doctrine ORM Documentation
The documentation is written in [ReStructured Text](https://docutils.sourceforge.io/rst.html).
## How to Generate:
Using Ubuntu 14.04 LTS:
1. Run ./bin/install-dependencies.sh
2. Run ./bin/generate-docs.sh
In the project root, run
It will generate the documentation into the build directory of the checkout.
composer docs
This will generate the documentation into the `docs/output` subdirectory.
## Theme issues
To browse the documentation, you need to run a webserver:
If you get a "Theme error", check if the `en/_theme` subdirectory is empty,
in which case you will need to run:
cd docs/output
php -S localhost:8000
1. git submodule init
2. git submodule update
Now the documentation is available at [http://localhost:8000](http://localhost:8000).

View File

@@ -1,10 +0,0 @@
#!/bin/bash
EXECPATH=`dirname $0`
cd $EXECPATH
cd ..
rm build -Rf
sphinx-build en build
sphinx-build -b latex en build/pdf
rubber --into build/pdf --pdf build/pdf/Doctrine2ORM.tex

View File

@@ -1,2 +0,0 @@
#!/bin/bash
sudo apt-get update && sudo apt-get install -y python2.7 python-sphinx python-pygments

9
docs/composer.json Normal file
View File

@@ -0,0 +1,9 @@
{
"name": "doctrine/orm-docs",
"description": "Documentation for the Object-Relational Mapper\"",
"type": "library",
"license": "MIT",
"require-dev": {
"doctrine/docs-builder": "^1.0"
}
}

View File

@@ -1,89 +0,0 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Doctrine2ORM.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Doctrine2ORM.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

View File

@@ -1,93 +0,0 @@
#Copyright (c) 2010 Fabien Potencier
#
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is furnished
#to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in all
#copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
from docutils.parsers.rst import Directive, directives
from docutils import nodes
from string import upper
class configurationblock(nodes.General, nodes.Element):
pass
class ConfigurationBlock(Directive):
has_content = True
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = True
option_spec = {}
formats = {
'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):
env = self.state.document.settings.env
node = nodes.Element()
node.document = self.state.document
self.state.nested_parse(self.content, self.content_offset, node)
entries = []
for i, child in enumerate(node):
if isinstance(child, nodes.literal_block):
# add a title (the language name) before each block
#targetid = "configuration-block-%d" % env.new_serialno('configuration-block')
#targetnode = nodes.target('', '', ids=[targetid])
#targetnode.append(child)
innernode = nodes.emphasis(self.formats[child['language']], self.formats[child['language']])
para = nodes.paragraph()
para += [innernode, child]
entry = nodes.list_item('')
entry.append(para)
entries.append(entry)
resultnode = configurationblock()
resultnode.append(nodes.bullet_list('', *entries))
return [resultnode]
def visit_configurationblock_html(self, node):
self.body.append(self.starttag(node, 'div', CLASS='configuration-block'))
def depart_configurationblock_html(self, node):
self.body.append('</div>\n')
def visit_configurationblock_latex(self, node):
pass
def depart_configurationblock_latex(self, node):
pass
def setup(app):
app.add_node(configurationblock,
html=(visit_configurationblock_html, depart_configurationblock_html),
latex=(visit_configurationblock_latex, depart_configurationblock_latex))
app.add_directive('configuration-block', ConfigurationBlock)

Submodule docs/en/_theme deleted from 6f1bc8bead

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);
}
}
@@ -213,18 +191,18 @@ Now look at the following test-code for our entities:
{
$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);
$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

@@ -101,8 +101,16 @@ The ``Paginate::count(Query $query)`` looks like:
{
static public function count(Query $query)
{
/** @var Query $countQuery */
$countQuery = clone $query;
/*
To avoid changing the $query passed into the method and to make sure a possibly existing
ResultSetMapping is discarded, we create a new query object any copy relevant data over.
*/
$countQuery = new Query($query->getEntityManager());
$countQuery->setDQL($query->getDQL());
$countQuery->setParameters(clone $query->getParameters());
foreach ($query->getHints() as $name => $value) {
$countQuery->setHint($name, $value);
}
$countQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('DoctrineExtensions\Paginate\CountSqlWalker'));
$countQuery->setFirstResult(null)->setMaxResults(null);
@@ -111,7 +119,7 @@ The ``Paginate::count(Query $query)`` looks like:
}
}
It clones the query, resets the limit clause first and max results
This resets the limit clause first and max results
and registers the ``CountSqlWalker`` custom tree walker which
will modify the AST to execute a count query. The walkers
implementation is:

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

@@ -0,0 +1,44 @@
Generated Columns
=================
Generated columns, sometimes also called virtual columns, are populated by
the database engine itself. They are a tool for performance optimization, to
avoid calculating a value on each query.
You can define generated columns on entities and have Doctrine map the values
to your entity.
Declaring a generated column
----------------------------
There is no explicit mapping instruction for generated columns. Instead, you
specify that the column should not be written to, and define a custom column
definition.
.. literalinclude:: generated-columns/Person.php
:language: php
* ``insertable``, ``updatable``: Setting these to false tells Doctrine to never
write this column - writing to a generated column would result in an error
from the database.
* ``columnDefinition``: We specify the full DDL to create the column. To allow
to use database specific features, this attribute does not use Doctrine Query
Language but native SQL. Note that you need to reference columns by their
database name (either explicitly set in the mapping or per the current
:doc:`naming strategy <../reference/namingstrategy>`).
Be aware that specifying a column definition makes the ``SchemaTool``
completely ignore all other configuration for this column. See also
:ref:`#[Column] <attrref_column>`
* ``generated``: Specifying that this column is always generated tells Doctrine
to update the field on the entity with the value from the database after
every write operation.
Advanced example: Extracting a value from a JSON structure
----------------------------------------------------------
Lets assume we have an entity that stores a blogpost as structured JSON.
To avoid extracting all titles on the fly when listing the posts, we create a
generated column with the field.
.. literalinclude:: generated-columns/Article.php
:language: php

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Article
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private int $id;
/**
* When working with Postgres, it is recommended to use the jsonb
* format for better performance.
*/
#[ORM\Column(options: ['jsonb' => true])]
private array $content;
/**
* Because we specify NOT NULL, inserting will fail if the content does
* not have a string in the title field.
*/
#[ORM\Column(
insertable: false,
updatable: false,
columnDefinition: "VARCHAR(255) generated always as (content->>'title') stored NOT NULL",
generated: 'ALWAYS',
)]
private string $title;
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Person
{
#[ORM\Column(type: 'string')]
private string $firstName;
#[ORM\Column(type: 'string', name: 'name')]
private string $lastName;
#[ORM\Column(
type: 'string',
insertable: false,
updatable: false,
columnDefinition: "VARCHAR(255) GENERATED ALWAYS AS (concat(firstName, ' ', name) stored NOT NULL",
generated: 'ALWAYS',
)]
private string $fullName;
}

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,7 +1,7 @@
Implementing the Notify ChangeTracking Policy
=============================================
.. sectionauthor:: Roman Borschel (roman@code-factory.org)
.. 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

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

@@ -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.

View File

@@ -13,7 +13,6 @@ If this documentation is not helping to answer questions you have about
Doctrine ORM don't panic. You can get help from different sources:
- There is a :doc:`FAQ <reference/faq>` with answers to frequent questions.
- The `Doctrine Mailing List <https://groups.google.com/group/doctrine-user>`_
- Slack chat room `#orm <https://www.doctrine-project.org/slack>`_
- Report a bug on `GitHub <https://github.com/doctrine/orm/issues>`_.
- On `StackOverflow <https://stackoverflow.com/questions/tagged/doctrine-orm>`_
@@ -96,13 +95,14 @@ 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:`Generated/Virtual Columns <cookbook/generated-columns>` \|
:doc:`Decorator Pattern <cookbook/decorator-pattern>` \|
:doc:`Strategy Pattern <cookbook/strategy-cookbook-introduction>`
@@ -123,4 +123,5 @@ Cookbook
* **Custom Datatypes**
:doc:`MySQL Enums <cookbook/mysql-enums>`
:doc:`Custom Mapping Types <cookbook/custom-mapping-types>`
:doc:`Advanced Field Value Conversion <cookbook/advanced-field-value-conversion-using-custom-mapping-types>`

View File

@@ -1,113 +0,0 @@
@ECHO OFF
REM Command file for Sphinx documentation
set SPHINXBUILD=sphinx-build
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Doctrine2ORM.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Doctrine2ORM.ghc
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

View File

@@ -71,8 +71,8 @@ Configuration Options
The following sections describe all the configuration options
available on a ``Doctrine\ORM\Configuration`` instance.
Proxy Directory (***REQUIRED***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proxy Directory (**REQUIRED**)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: php
@@ -85,8 +85,8 @@ classes. For a detailed explanation on proxy classes and how they
are used in Doctrine, refer to the "Proxy Objects" section further
down.
Proxy Namespace (***REQUIRED***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proxy Namespace (**REQUIRED**)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: php
@@ -98,8 +98,8 @@ Gets or sets the namespace to use for generated proxy classes. For
a detailed explanation on proxy classes and how they are used in
Doctrine, refer to the "Proxy Objects" section further down.
Metadata Driver (***REQUIRED***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Metadata Driver (**REQUIRED**)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: php
@@ -144,8 +144,8 @@ accept either a single directory as a string or an array of
directories. With this feature a single driver can support multiple
directories of Entities.
Metadata Cache (***RECOMMENDED***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Metadata Cache (**RECOMMENDED**)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: php
@@ -166,8 +166,8 @@ For development you should use an array cache like
``Symfony\Component\Cache\Adapter\ArrayAdapter``
which only caches data on a per-request basis.
Query Cache (***RECOMMENDED***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Query Cache (**RECOMMENDED**)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: php
@@ -189,8 +189,8 @@ For development you should use an array cache like
``Symfony\Component\Cache\Adapter\ArrayAdapter``
which only caches data on a per-request basis.
SQL Logger (***Optional***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQL Logger (**Optional**)
~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: php
@@ -202,8 +202,8 @@ Gets or sets the logger to use for logging all SQL statements
executed by Doctrine. The logger class must implement the
deprecated ``Doctrine\DBAL\Logging\SQLLogger`` interface.
Auto-generating Proxy Classes (***OPTIONAL***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Auto-generating Proxy Classes (**OPTIONAL**)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proxy classes can either be generated manually through the Doctrine
Console or automatically at runtime by Doctrine. The configuration
@@ -279,7 +279,7 @@ requests.
Connection
----------
The ``$connection`` passed as the first argument to he constructor of
The ``$connection`` passed as the first argument to the constructor of
``EntityManager`` has to be an instance of ``Doctrine\DBAL\Connection``.
You can use the factory ``Doctrine\DBAL\DriverManager::getConnection()``
to create such a connection. The DBAL configuration is explained in the
@@ -446,7 +446,7 @@ correctly if sub-namespaces use different metadata driver
implementations.
Default Repository (***OPTIONAL***)
Default Repository (**OPTIONAL**)
-----------------------------------
Specifies the FQCN of a subclass of the EntityRepository.
@@ -461,7 +461,7 @@ That will be available for all entities without a custom repository class.
The default value is ``Doctrine\ORM\EntityRepository``.
Any repository class must be a subclass of EntityRepository otherwise you got an ORMException
Ignoring entities (***OPTIONAL***)
Ignoring entities (**OPTIONAL**)
-----------------------------------
Specifies the Entity FQCNs to ignore.

View File

@@ -168,7 +168,7 @@ recommended, at least not as long as an entity instance still holds
references to proxy objects or is still managed by an EntityManager.
By default, serializing proxy objects does not initialize them. On
unserialization, resulting objects are detached from the entity
manager and cannot be initialiazed anymore. You can implement the
manager and cannot be initialized anymore. You can implement the
``__serialize()`` method if you want to change that behavior, but
then you need to ensure that you won't generate large serialized
object graphs and take care of circular associations.

View File

@@ -1300,8 +1300,8 @@ 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;
// ...
@@ -1333,10 +1333,10 @@ 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>
@@ -1368,8 +1368,7 @@ defaults to "id", just as in one-to-one or many-to-one mappings.
Additionally, when using typed properties with Doctrine 2.9 or newer
you can skip ``targetEntity`` in ``ManyToOne`` and ``OneToOne``
associations as they will be set based on type. Also ``nullable``
attribute on ``JoinColumn`` will be inherited from PHP type. So that:
associations as they will be set based on type. So that:
.. configuration-block::
@@ -1409,7 +1408,7 @@ Is essentially the same as following:
<?php
/** One Product has One Shipment. */
#[OneToOne(targetEntity: Shipment::class)]
#[JoinColumn(name: 'shipment_id', referencedColumnName: 'id', nullable: false)]
#[JoinColumn(name: 'shipment_id', referencedColumnName: 'id')]
private Shipment $shipment;
.. code-block:: annotation
@@ -1418,7 +1417,7 @@ Is essentially the same as following:
/**
* One Product has One Shipment.
* @OneToOne(targetEntity="Shipment")
* @JoinColumn(name="shipment_id", referencedColumnName="id", nullable=false)
* @JoinColumn(name="shipment_id", referencedColumnName="id")
*/
private Shipment $shipment;
@@ -1427,7 +1426,7 @@ Is essentially the same as following:
<doctrine-mapping>
<entity class="Product">
<one-to-one field="shipment" target-entity="Shipment">
<join-column name="shipment_id" referenced-column-name="id" nulable=false />
<join-column name="shipment_id" referenced-column-name="id" nullable=false />
</one-to-one>
</entity>
</doctrine-mapping>
@@ -1442,7 +1441,6 @@ Is essentially the same as following:
joinColumn:
name: shipment_id
referencedColumnName: id
nullable: false
If you accept these defaults, you can reduce the mapping code to a
minimum.

View File

@@ -14,7 +14,7 @@ Index
- :ref:`#[AttributeOverride] <attrref_attributeoverride>`
- :ref:`#[Column] <attrref_column>`
- :ref:`#[Cache] <attrref_cache>`
- :ref:`#[ChangeTrackingPolicy <attrref_changetrackingpolicy>`
- :ref:`#[ChangeTrackingPolicy] <attrref_changetrackingpolicy>`
- :ref:`#[CustomIdGenerator] <attrref_customidgenerator>`
- :ref:`#[DiscriminatorColumn] <attrref_discriminatorcolumn>`
- :ref:`#[DiscriminatorMap] <attrref_discriminatormap>`
@@ -213,12 +213,15 @@ Optional parameters:
- ``check``: Adds a check constraint type to the column (might not
be supported by all vendors).
- **columnDefinition**: DDL SQL snippet that starts after the column
- **columnDefinition**: Specify the DDL SQL snippet that starts after the column
name and specifies the complete (non-portable!) column definition.
This attribute allows to make use of advanced RMDBS features.
However you should make careful use of this feature and the
consequences. ``SchemaTool`` will not detect changes on the column correctly
anymore if you use ``columnDefinition``.
However, as this needs to be specified in the DDL native to the database,
the resulting schema changes are no longer portable. If you specify a
``columnDefinition``, the ``SchemaTool`` ignores all other attributes
that are normally used to build the definition DDL. Changes to the
``columnDefinition`` are not detected, you will need to manually create a
migration to apply changes.
Additionally you should remember that the ``type``
attribute still handles the conversion between PHP and Database
@@ -261,10 +264,11 @@ Examples:
)]
protected $loginCount;
// MySQL example: full_name char(41) GENERATED ALWAYS AS (concat(firstname,' ',lastname)),
// columnDefinition is raw SQL, not DQL. This example works for MySQL:
#[Column(
type: "string",
name: "user_fullname",
columnDefinition: "VARCHAR(255) GENERATED ALWAYS AS (concat(firstname,' ',lastname))",
insertable: false,
updatable: false
)]
@@ -366,7 +370,7 @@ Optional parameters:
- **type**: By default this is string.
- **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.
- **columnDefinition**: Allows to override how the column is generated. See the "columnDefinition" attribute on :ref:`#[Column] <attrref_column>`
- **enumType**: By default this is `null`. Allows to map discriminatorColumn value to PHP enum
- **options**: See "options" attribute on :ref:`#[Column] <attrref_column>`.
@@ -678,8 +682,10 @@ Optional parameters:
- **onDelete**: Cascade Action (Database-level)
- **columnDefinition**: DDL SQL snippet that starts after the column
name and specifies the complete (non-portable!) column definition.
This attribute enables the use of advanced RMDBS features. Using
this attribute on ``#[JoinColumn]`` is necessary if you need slightly
This attribute enables the use of advanced RMDBS features. Note that you
need to reference columns by their database name (either explicitly set in
the mapping or per the current :doc:`naming strategy <namingstrategy>`).
Using this attribute on ``#[JoinColumn]`` is necessary if you need
different column definitions for joining columns, for example
regarding NULL/NOT NULL defaults. However by default a
"columnDefinition" attribute on :ref:`#[Column] <attrref_column>` also sets

View File

@@ -239,6 +239,7 @@ Here is a complete list of ``Column``s attributes (all optional):
- ``nullable`` (default: ``false``): Whether the column is nullable.
- ``insertable`` (default: ``true``): Whether the column should be inserted.
- ``updatable`` (default: ``true``): Whether the column should be updated.
- ``generated`` (default: ``null``): Whether the generated strategy should be ``'NEVER'``, ``'INSERT'`` and ``ALWAYS``.
- ``enumType`` (requires PHP 8.1 and ``doctrine/orm`` 2.11): The PHP enum class name to convert the database value into.
- ``precision`` (default: 0): The precision for a decimal (exact numeric) column
(applies only for decimal column),
@@ -300,50 +301,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::
@@ -462,7 +425,7 @@ Here is the list of possible generation strategies:
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 :ref:`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. <annref_customidgenerator>`
Sequence Generator
^^^^^^^^^^^^^^^^^^

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
------------
@@ -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

@@ -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:
@@ -807,7 +812,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 +827,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 +1003,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 +1020,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,165 +1263,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\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');
Iterating Large Result Sets
~~~~~~~~~~~~~~~~~~~~~~~~~~~

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
~~~~~~~~~~~~~~~~~
@@ -286,7 +299,7 @@ specific to a particular entity class's lifecycle.
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="User">
@@ -345,7 +358,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
@@ -458,11 +471,11 @@ prePersist
There are two ways for the ``prePersist`` event to be triggered:
- One is when you call ``EntityManager::persist()``. The
event is also called for all :ref:`cascaded associations<transitive-persistence>`.
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
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>`.
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.
@@ -486,7 +499,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.
@@ -534,7 +547,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
@@ -699,30 +712,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.
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. Generated primary
key values will be available for all entities at the time this
event is triggered.
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 all database
delete operations for entity rows have been executed. This event is
not called for a DQL ``DELETE`` statement.
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.
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::
@@ -731,19 +747,6 @@ not directly mapped by Doctrine.
cascade remove relations. In this case, you should load yourself the proxy in
the associated ``pre*`` event.
.. warning::
Making changes to entities and calling ``EntityManager::flush()`` from within
``post*`` event handlers 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.
.. _reference-events-post-load:
postLoad
@@ -1140,16 +1143,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

@@ -101,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

@@ -30,7 +30,7 @@ table alias of the SQL table of the entity.
For the filter to correctly function, the following rules must be followed. Failure to do so will lead to unexpected results from the query cache.
1. Parameters for the query should be set on the filter object by ``SQLFilter#setParameter()`` before the filter is used by the ORM ( i.e. do not set parameters inside ``SQLFilter#addFilterConstraint()`` function ).
2. The filter must be deterministic. Don't change the values base on external inputs.
2. The filter must be deterministic. Don't change the values based on external inputs.
The ``SQLFilter#getParameter()`` function takes care of the proper quoting of parameters.

View File

@@ -380,7 +380,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

View File

@@ -1,3 +1,5 @@
:orphan:
Installation
============

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.
@@ -175,6 +175,26 @@ 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.
Apart from that, in the case of having multiple ``private`` fields of the same name within
the class hierarchy an entity or mapped superclass, the Collection filtering API cannot determine
the right field to look at. Even if only one of these fields is actually mapped, the ``ArrayCollection``
will not be able to tell, since it does not have access to any metadata.
Thus, to avoid problems in this regard, it is best to avoid having multiple ``private`` fields of the
same name in class hierarchies containing entity and mapped superclasses.
Known Issues
------------

View File

@@ -81,8 +81,8 @@ implements the ``MappingDriver`` interface:
/**
* Loads the metadata for the specified class into the provided container.
*
* @psalm-param class-string<T> $className
* @psalm-param ClassMetadata<T> $metadata
* @param class-string<T> $className
* @param ClassMetadata<T> $metadata
*
* @return void
*
@@ -93,8 +93,7 @@ implements the ``MappingDriver`` interface:
/**
* Gets the names of all mapped classes known to this driver.
*
* @return array<int, string> The names of all mapped classes known to this driver.
* @psalm-return list<class-string>
* @return list<class-string> The names of all mapped classes known to this driver.
*/
public function getAllClassNames();
@@ -102,7 +101,7 @@ implements the ``MappingDriver`` interface:
* Returns whether the class with the specified name should have its metadata loaded.
* This is only the case if it is either mapped as an Entity or a MappedSuperclass.
*
* @psalm-param class-string $className
* @param class-string $className
*
* @return bool
*/

View File

@@ -44,7 +44,7 @@ Something like below for an entity region:
If the entity holds a collection that also needs to be cached.
An collection region could look something like:
A collection region could look something like:
.. code-block:: php
@@ -323,7 +323,7 @@ level cache region.
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Country">
@@ -431,7 +431,7 @@ It caches the primary keys of association and cache each element will be cached
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="State">
@@ -630,7 +630,7 @@ DELETE / UPDATE queries
DQL UPDATE / DELETE statements are ported directly into a database and bypass
the second-level cache.
Entities that are already cached will NOT be invalidated.
However the cached data could be evicted using the cache API or an special query hint.
However the cached data could be evicted using the cache API or a special query hint.
Execute the ``UPDATE`` and invalidate ``all cache entries`` using ``Query::HINT_CACHE_EVICT``

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
---------------------------
@@ -119,7 +118,7 @@ entity might look like this:
}
}
Now the possiblity of mass-assignment exists on this entity and can
Now the possibility of mass-assignment exists on this entity and can
be exploited by attackers to set the "isAdmin" flag to true on any
object when you pass the whole request data to this method like:

View File

@@ -88,7 +88,7 @@ requirement.
A more convenient alternative for explicit transaction demarcation is the use
of provided control abstractions in the form of
``Connection#transactional($func)`` and ``EntityManager#transactional($func)``.
``Connection#transactional($func)`` and ``EntityManager#wrapInTransaction($func)``.
When used, these control abstractions ensure that you never forget to rollback
the transaction, in addition to the obvious code reduction. An example that is
functionally equivalent to the previously shown code looks as follows:
@@ -96,21 +96,23 @@ functionally equivalent to the previously shown code looks as follows:
.. code-block:: php
<?php
// transactional with Connection instance
// $conn instanceof Connection
$conn->transactional(function($conn) {
// ... do some work
$user = new User;
$user->setName('George');
});
// transactional with EntityManager instance
// $em instanceof EntityManager
$em->transactional(function($em) {
$em->wrapInTransaction(function($em) {
// ... do some work
$user = new User;
$user->setName('George');
$em->persist($user);
});
.. warning::
For historical reasons, ``EntityManager#transactional($func)`` will return
``true`` whenever the return value of ``$func`` is loosely false.
Some examples of this include ``array()``, ``"0"``, ``""``, ``0``, and
``null``.
The difference between ``Connection#transactional($func)`` and
``EntityManager#transactional($func)`` is that the latter
abstraction flushes the ``EntityManager`` prior to transaction

View File

@@ -102,7 +102,7 @@ How Doctrine Detects Changes
----------------------------
Doctrine is a data-mapper that tries to achieve persistence-ignorance (PI).
This means you map php objects into a relational database that don't
This means you map PHP objects into a relational database that don't
necessarily know about the database at all. A natural question would now be,
"how does Doctrine even detect objects have changed?".

View File

@@ -736,6 +736,35 @@ methods:
.. note::
There is a limitation on the compatibility of Criteria comparisons.
You have to use scalar values only as the value in a comparison or
the behaviour between different backends is not the same.
Depending on whether the collection has already been loaded from the
database or not, criteria matching may happen at the database/SQL level
or on objects in memory. This may lead to different results and come
surprising, for example when a code change in one place leads to a collection
becoming initialized and, as a side effect, returning a different result
or even breaking a ``matching()`` call somewhere else. Also, collection
initialization state in practical use cases may differ from the one covered
in unit tests.
Database level comparisons are based on scalar representations of the values
stored in entity properties. The field names passed to expressions correspond
to property names. Comparison and sorting may be affected by
database-specific behavior. For example, MySQL enum types sort by index position,
not lexicographically by value.
In-memory handling is based on the ``Selectable`` API of `Doctrine Collections <https://www.doctrine-project.org/projects/doctrine-collections/en/stable/index.html#matching>`.
In this case, field names passed to expressions are being used to derive accessor
method names. Strict type comparisons are used for equal and not-equal checks,
and generally PHP language rules are being used for other comparison operators
or sorting.
As a general guidance, for consistent results use the Criteria API with scalar
values only. Note that ``DateTime`` and ``DateTimeImmutable`` are two predominant
examples of value objects that are *not* scalars.
Refrain from using special database-level column types or custom Doctrine Types
that may lead to database-specific comparison or sorting rules being applied, or
to database-level values being different from object field values.
Provide accessor methods for all entity fields used in criteria expressions,
and implement those methods in a way that their return value is the
same as the database-level value.

View File

@@ -338,10 +338,11 @@ 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
``EntityManager#remove()``. If the association is a collection, Doctrine will loop over all its elements and pass them to``EntityManager#remove()``.
1. If an association is marked as ``CASCADE=REMOVE`` Doctrine ORM will
fetch this association. If it's a Single association it will pass
this entity to ``EntityManager#remove()``. If the association is a
collection, Doctrine will loop over all its elements and pass them to
``EntityManager#remove()``.
In both cases the cascade remove semantics are applied recursively.
For large object graphs this removal strategy can be very costly.
2. Using a DQL ``DELETE`` statement allows you to delete multiple

View File

@@ -17,7 +17,7 @@ setup for the latest code in trunk.
.. code-block:: xml
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
@@ -103,7 +103,7 @@ of several common elements:
// Doctrine.Tests.ORM.Mapping.User.dcm.xml
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
@@ -770,7 +770,7 @@ entity relationship. You can define this in XML with the "association-key" attri
.. code-block:: xml
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

View File

@@ -1,83 +1,78 @@
.. toc::
:orphan:
.. tocheader:: Tutorials
.. toctree::
:caption: Tutorials
:depth: 3
.. toctree::
:depth: 3
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
tutorials/embeddables
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
tutorials/embeddables
.. toctree::
:caption: Reference
:depth: 3
.. toc::
reference/architecture
reference/configuration
reference/faq
reference/basic-mapping
reference/association-mapping
reference/inheritance-mapping
reference/working-with-objects
reference/working-with-associations
reference/typedfieldmapper
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
.. tocheader:: Reference
.. toctree::
:caption: Cookbook
:depth: 3
.. toctree::
:depth: 3
reference/architecture
reference/configuration
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
.. toc::
.. tocheader:: Cookbook
.. toctree::
:depth: 3
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
cookbook/aggregate-fields
cookbook/custom-mapping-types
cookbook/decorator-pattern
cookbook/dql-custom-walkers
cookbook/dql-user-defined-functions
cookbook/generated-columns
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

@@ -86,7 +86,7 @@ and year of production as primary keys:
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
@@ -127,11 +127,12 @@ And for querying you can use arrays to both DQL and EntityRepositories:
namespace VehicleCatalogue\Model;
// $em is the EntityManager
$audi = $em->find("VehicleCatalogue\Model\Car", array("name" => "Audi A8", "year" => 2010));
$audi = $em->find("VehicleCatalogue\Model\Car", ["name" => "Audi A8", "year" => 2010]);
$dql = "SELECT c FROM VehicleCatalogue\Model\Car c WHERE c.id = ?1";
$dql = "SELECT c FROM VehicleCatalogue\Model\Car c WHERE c.name = ?1 AND c.year = ?2";
$audi = $em->createQuery($dql)
->setParameter(1, ["name" => "Audi A8", "year" => 2010])
->setParameter(1, "Audi A8")
->setParameter(2, 2010)
->getSingleResult();
You can also use this entity in associations. Doctrine will then generate two foreign keys one for ``name``
@@ -188,7 +189,7 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
#[OneToMany(targetEntity: ArticleAttribute::class, mappedBy: 'article', cascade: ['ALL'], indexBy: 'attribute')]
private Collection $attributes;
public function addAttribute(string $name, ArticleAttribute $value): void
public function addAttribute(string $name, string $value): void
{
$this->attributes[$name] = new ArticleAttribute($name, $value, $this);
}
@@ -268,7 +269,7 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
.. code-block:: xml
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

View File

@@ -18,6 +18,7 @@ can be called without triggering a full load of the collection:
- ``Collection#containsKey($key)``
- ``Collection#count()``
- ``Collection#get($key)``
- ``Collection#isEmpty()``
- ``Collection#slice($offset, $length = null)``
For each of the above methods the following semantics apply:
@@ -86,7 +87,7 @@ switch to extra lazy as shown in these examples:
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

View File

@@ -144,7 +144,7 @@ step:
// Create a simple "default" Doctrine ORM configuration for Attributes
$config = ORMSetup::createAttributeMetadataConfiguration(
paths: array(__DIR__."/src"),
paths: [__DIR__ . '/src'],
isDevMode: true,
);
// or if you prefer annotation, YAML or XML
@@ -153,7 +153,7 @@ step:
// isDevMode: true,
// );
// $config = ORMSetup::createXMLMetadataConfiguration(
// paths: array(__DIR__."/config/xml"),
// paths: [__DIR__ . '/config/xml'],
// isDevMode: true,
//);
// $config = ORMSetup::createYAMLMetadataConfiguration(
@@ -558,7 +558,7 @@ methods, but you only need to choose one.
<!-- config/xml/Product.dcm.xml -->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
@@ -1139,7 +1139,7 @@ the ``Product`` before:
<!-- config/xml/Bug.dcm.xml -->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
@@ -1294,7 +1294,7 @@ Finally, we'll add metadata mappings for the ``User`` entity.
<!-- config/xml/User.dcm.xml -->
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
@@ -1818,7 +1818,7 @@ we have to adjust the metadata slightly.
.. code-block:: xml
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

View File

@@ -9,7 +9,7 @@ i.e. attributes and associations metadata in particular. The example here shows
the overriding of a class that uses a trait but is similar when extending a base
class as shown at the end of this tutorial.
Suppose we have a class ExampleEntityWithOverride. This class uses trait ExampleTrait:
Suppose we have a class ``ExampleEntityWithOverride``. This class uses trait ``ExampleTrait``:
.. code-block:: php
@@ -17,22 +17,20 @@ Suppose we have a class ExampleEntityWithOverride. This class uses trait Example
#[Entity]
#[AttributeOverrides([
new AttributeOverride('foo', [
'column' => new Column([
'name' => 'foo_overridden',
'type' => 'integer',
'length' => 140,
'nullable' => false,
'unique' => false,
]),
]),
new AttributeOverride('foo', new Column(
name: 'foo_overridden',
type: 'integer',
length: 140,
nullable: false,
unique: false,
)),
])]
#[AssociationOverrides([
new AssociationOverride('bar', [
'joinColumns' => new JoinColumn([
'name' => 'example_entity_overridden_bar_id',
'referencedColumnName' => 'id',
]),
new JoinColumn(
name: 'example_entity_overridden_bar_id',
referencedColumnName: 'id',
),
]),
])]
class ExampleEntityWithOverride
@@ -47,7 +45,7 @@ Suppose we have a class ExampleEntityWithOverride. This class uses trait Example
private $id;
}
The docblock is showing metadata override of the attribute and association type. It
``#[AttributeOverrides]`` contains metadata override of the attribute and association type. It
basically changes the names of the columns mapped for a property ``foo`` and for
the association ``bar`` which relates to Bar class shown above. Here is the trait
which has mapping metadata that is overridden by the attribute above:

View File

@@ -31,169 +31,18 @@ You can map indexed associations by adding:
The code and mappings for the Market entity looks like this:
.. configuration-block::
.. code-block:: attribute
.. literalinclude:: working-with-indexed-associations/Market.php
:language: attribute
<?php
namespace Doctrine\Tests\Models\StockExchange;
.. literalinclude:: working-with-indexed-associations/Market-annotations.php
:language: annotation
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
.. literalinclude:: working-with-indexed-associations/market.xml
:language: xml
#[Entity]
#[Table(name: 'exchange_markets')]
class Market
{
#[Id, Column(type: 'integer'), GeneratedValue]
private int|null $id = null;
.. literalinclude:: working-with-indexed-associations/market.yaml
:language: yaml
#[Column(type: 'string')]
private string $name;
/** @var Collection<string, Stock> */
#[OneToMany(targetEntity: Stock::class, mappedBy: 'market', indexBy: 'symbol')]
private Collection $stocks;
public function __construct(string $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(string $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:: 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="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="Doctrine\Tests\Models\StockExchange\Market">
<id name="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="name" type="string"/>
<one-to-many target-entity="Stock" mapped-by="market" field="stocks" index-by="symbol" />
</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)``
@@ -279,7 +128,7 @@ here are the code and mappings for it:
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

View File

@@ -0,0 +1,74 @@
<?php
namespace Doctrine\Tests\Models\StockExchange;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\Table;
use InvalidArgumentException;
/**
* @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();
}
}

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace Doctrine\Tests\Models\StockExchange;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\Table;
use InvalidArgumentException;
#[Entity]
#[Table(name: 'exchange_markets')]
class Market
{
#[Id]
#[Column(type: 'integer')]
#[GeneratedValue]
private int|null $id = null;
#[Column(type: 'string')]
private string $name;
/** @var Collection<string, Stock> */
#[OneToMany(targetEntity: Stock::class, mappedBy: 'market', indexBy: 'symbol')]
private Collection $stocks;
public function __construct(string $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(string $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();
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\StockExchange\Market">
<id name="id" type="integer">
<generator strategy="AUTO" />
</id>
<field name="name" type="string"/>
<one-to-many target-entity="Stock" mapped-by="market" field="stocks" index-by="symbol" />
</entity>
</doctrine-mapping>

View File

@@ -0,0 +1,15 @@
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

View File

@@ -148,7 +148,6 @@
<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>
@@ -226,22 +225,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>
@@ -385,7 +375,7 @@
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="value" type="xs:NMTOKEN" use="required"/>
<xs:attribute name="value" type="orm:type" use="required"/>
<xs:attribute name="class" type="orm:fqcn" use="required"/>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
@@ -565,7 +555,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>
@@ -583,7 +572,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,251 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\ORM\Query;
use Doctrine\Common\Lexer\AbstractLexer;
use Doctrine\Deprecations\Deprecation;
use function constant;
use function ctype_alpha;
use function defined;
use function is_numeric;
use function str_contains;
use function str_replace;
use function stripos;
use function strlen;
use function strtoupper;
use function substr;
/**
* Scans a DQL query for tokens.
*
* @extends AbstractLexer<Lexer::T_*, string>
*/
class Lexer extends AbstractLexer
{
// All tokens that are not valid identifiers must be < 100
public const T_NONE = 1;
public const T_INTEGER = 2;
public const T_STRING = 3;
public const T_INPUT_PARAMETER = 4;
public const T_FLOAT = 5;
public const T_CLOSE_PARENTHESIS = 6;
public const T_OPEN_PARENTHESIS = 7;
public const T_COMMA = 8;
public const T_DIVIDE = 9;
public const T_DOT = 10;
public const T_EQUALS = 11;
public const T_GREATER_THAN = 12;
public const T_LOWER_THAN = 13;
public const T_MINUS = 14;
public const T_MULTIPLY = 15;
public const T_NEGATE = 16;
public const T_PLUS = 17;
public const T_OPEN_CURLY_BRACE = 18;
public const T_CLOSE_CURLY_BRACE = 19;
// All tokens that are identifiers or keywords that could be considered as identifiers should be >= 100
/** @deprecated No Replacement planned. */
public const T_ALIASED_NAME = 100;
public const T_FULLY_QUALIFIED_NAME = 101;
public const T_IDENTIFIER = 102;
// All keyword tokens should be >= 200
public const T_ALL = 200;
public const T_AND = 201;
public const T_ANY = 202;
public const T_AS = 203;
public const T_ASC = 204;
public const T_AVG = 205;
public const T_BETWEEN = 206;
public const T_BOTH = 207;
public const T_BY = 208;
public const T_CASE = 209;
public const T_COALESCE = 210;
public const T_COUNT = 211;
public const T_DELETE = 212;
public const T_DESC = 213;
public const T_DISTINCT = 214;
public const T_ELSE = 215;
public const T_EMPTY = 216;
public const T_END = 217;
public const T_ESCAPE = 218;
public const T_EXISTS = 219;
public const T_FALSE = 220;
public const T_FROM = 221;
public const T_GROUP = 222;
public const T_HAVING = 223;
public const T_HIDDEN = 224;
public const T_IN = 225;
public const T_INDEX = 226;
public const T_INNER = 227;
public const T_INSTANCE = 228;
public const T_IS = 229;
public const T_JOIN = 230;
public const T_LEADING = 231;
public const T_LEFT = 232;
public const T_LIKE = 233;
public const T_MAX = 234;
public const T_MEMBER = 235;
public const T_MIN = 236;
public const T_NEW = 237;
public const T_NOT = 238;
public const T_NULL = 239;
public const T_NULLIF = 240;
public const T_OF = 241;
public const T_OR = 242;
public const T_ORDER = 243;
public const T_OUTER = 244;
public const T_PARTIAL = 245;
public const T_SELECT = 246;
public const T_SET = 247;
public const T_SOME = 248;
public const T_SUM = 249;
public const T_THEN = 250;
public const T_TRAILING = 251;
public const T_TRUE = 252;
public const T_UPDATE = 253;
public const T_WHEN = 254;
public const T_WHERE = 255;
public const T_WITH = 256;
/**
* Creates a new query scanner object.
*
* @param string $input A query string.
*/
public function __construct($input)
{
$this->setInput($input);
}
/**
* {@inheritDoc}
*/
protected function getCatchablePatterns()
{
return [
'[a-z_][a-z0-9_]*\:[a-z_][a-z0-9_]*(?:\\\[a-z_][a-z0-9_]*)*', // aliased name
'[a-z_\\\][a-z0-9_]*(?:\\\[a-z_][a-z0-9_]*)*', // identifier or qualified name
'(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?', // numbers
"'(?:[^']|'')*'", // quoted strings
'\?[0-9]*|:[a-z_][a-z0-9_]*', // parameters
];
}
/**
* {@inheritDoc}
*/
protected function getNonCatchablePatterns()
{
return ['\s+', '--.*', '(.)'];
}
/**
* {@inheritDoc}
*/
protected function getType(&$value)
{
$type = self::T_NONE;
switch (true) {
// Recognize numeric values
case is_numeric($value):
if (str_contains($value, '.') || stripos($value, 'e') !== false) {
return self::T_FLOAT;
}
return self::T_INTEGER;
// Recognize quoted strings
case $value[0] === "'":
$value = str_replace("''", "'", substr($value, 1, strlen($value) - 2));
return self::T_STRING;
// Recognize identifiers, aliased or qualified names
case ctype_alpha($value[0]) || $value[0] === '_' || $value[0] === '\\':
$name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($value);
if (defined($name)) {
$type = constant($name);
if ($type > 100) {
return $type;
}
}
if (str_contains($value, ':')) {
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/issues/8818',
'Short namespace aliases such as "%s" are deprecated and will be removed in Doctrine ORM 3.0.',
$value
);
return self::T_ALIASED_NAME;
}
if (str_contains($value, '\\')) {
return self::T_FULLY_QUALIFIED_NAME;
}
return self::T_IDENTIFIER;
// Recognize input parameters
case $value[0] === '?' || $value[0] === ':':
return self::T_INPUT_PARAMETER;
// Recognize symbols
case $value === '.':
return self::T_DOT;
case $value === ',':
return self::T_COMMA;
case $value === '(':
return self::T_OPEN_PARENTHESIS;
case $value === ')':
return self::T_CLOSE_PARENTHESIS;
case $value === '=':
return self::T_EQUALS;
case $value === '>':
return self::T_GREATER_THAN;
case $value === '<':
return self::T_LOWER_THAN;
case $value === '+':
return self::T_PLUS;
case $value === '-':
return self::T_MINUS;
case $value === '*':
return self::T_MULTIPLY;
case $value === '/':
return self::T_DIVIDE;
case $value === '!':
return self::T_NEGATE;
case $value === '{':
return self::T_OPEN_CURLY_BRACE;
case $value === '}':
return self::T_CLOSE_CURLY_BRACE;
// Default
default:
// Do nothing
}
return $type;
}
}

View File

@@ -1,6 +1,6 @@
{
"runner.bootstrap": "tests/Doctrine/Tests/TestInit.php",
"runner.path": "tests/Doctrine/Performance",
"runner.bootstrap": "tests/Tests/TestInit.php",
"runner.path": "tests/Performance",
"runner.file_pattern": "*Bench.php",
"core.extensions": [

View File

@@ -1,5 +1,7 @@
<?xml version="1.0"?>
<ruleset>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="PHP_CodeSniffer"
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
<arg name="basepath" value="."/>
<arg name="extensions" value="php"/>
<arg name="parallel" value="80"/>
@@ -11,12 +13,11 @@
<config name="php_version" value="70100"/>
<file>lib</file>
<file>src</file>
<file>tests</file>
<exclude-pattern>*/lib/Doctrine/ORM/Mapping/InverseJoinColumn.php</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/Proxies/__CG__*</exclude-pattern>
<exclude-pattern>*/tests/Doctrine/Tests/ORM/Tools/Export/export/*</exclude-pattern>
<exclude-pattern>*/tests/Tests/Proxies/__CG__*</exclude-pattern>
<exclude-pattern>*/tests/Tests/ORM/Tools/Export/export/*</exclude-pattern>
<rule ref="Doctrine">
<exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint" />
@@ -34,119 +35,119 @@
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint">
<exclude-pattern>*/lib/*</exclude-pattern>
<exclude-pattern>*/src/*</exclude-pattern>
<!--
that class extends another one inside lib/ and can therefore not
that class extends another one inside src/ and can therefore not
have more native typehints since its parent cannot have them: that
would break signature compatibility.
-->
<exclude-pattern>tests/Doctrine/Tests/Mocks/HydratorMockStatement.php</exclude-pattern>
<exclude-pattern>tests/Tests/Mocks/HydratorMockStatement.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint">
<exclude-pattern>*/lib/*</exclude-pattern>
<exclude-pattern>*/src/*</exclude-pattern>
</rule>
<rule ref="PSR1.Classes.ClassDeclaration.MultipleClasses">
<exclude-pattern>lib/Doctrine/ORM/Mapping/Driver/CompatibilityAnnotationDriver.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Console/CommandCompatibility.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php</exclude-pattern>
<exclude-pattern>src/Mapping/Driver/CompatibilityAnnotationDriver.php</exclude-pattern>
<exclude-pattern>src/Tools/Console/CommandCompatibility.php</exclude-pattern>
<exclude-pattern>src/Tools/Console/Helper/EntityManagerHelper.php</exclude-pattern>
<exclude-pattern>tests/*</exclude-pattern>
</rule>
<rule ref="Squiz.Classes.ClassFileName.NoMatch">
<exclude-pattern>lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php</exclude-pattern>
<exclude-pattern>src/Tools/Console/Helper/EntityManagerHelper.php</exclude-pattern>
<exclude-pattern>tests/*</exclude-pattern>
</rule>
<rule ref="Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps">
<exclude-pattern>lib/Doctrine/ORM/Tools/Debug.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/ORM/Tools/DebugTest.php</exclude-pattern>
<exclude-pattern>src/Tools/Debug.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Tools/DebugTest.php</exclude-pattern>
</rule>
<rule ref="Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase">
<exclude-pattern>lib/Doctrine/ORM/Events.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/ToolEvents.php</exclude-pattern>
<exclude-pattern>src/Events.php</exclude-pattern>
<exclude-pattern>src/Tools/ToolEvents.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingTraversableTypeHintSpecification">
<!-- https://github.com/doctrine/annotations/issues/129 -->
<exclude-pattern>lib/Doctrine/ORM/Mapping/Column.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Index.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Table.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/UniqueConstraint.php</exclude-pattern>
<exclude-pattern>src/Mapping/Column.php</exclude-pattern>
<exclude-pattern>src/Mapping/Index.php</exclude-pattern>
<exclude-pattern>src/Mapping/Table.php</exclude-pattern>
<exclude-pattern>src/Mapping/UniqueConstraint.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator">
<exclude-pattern>lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php</exclude-pattern>
<exclude-pattern>src/Internal/Hydration/AbstractHydrator.php</exclude-pattern>
</rule>
<rule ref="PSR1.Methods.CamelCapsMethodName.NotCamelCaps">
<exclude-pattern>lib/Doctrine/ORM/Query/Parser.php</exclude-pattern>
<exclude-pattern>src/Query/Parser.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName">
<exclude-pattern>lib/Doctrine/ORM/Mapping/AssociationOverride.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/AssociationOverrides.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/AttributeOverride.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/AttributeOverrides.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Cache.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Column.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/ColumnResult.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/CustomIdGenerator.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/DiscriminatorMap.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Embeddable.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Embedded.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Entity.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/EntityListeners.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/EntityResult.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/FieldResult.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/GeneratedValue.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Id.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Index.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/InheritanceType.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/JoinColumn.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/JoinColumns.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/JoinTable.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/ManyToMany.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/ManyToOne.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/MappedSuperclass.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/NamedNativeQueries.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/NamedNativeQuery.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/NamedQueries.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/NamedQuery.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/OneToMany.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/OneToOne.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/OrderBy.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/PostLoad.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/PostPersist.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/PostRemove.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/PostUpdate.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/PreFlush.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/PrePersist.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/PreRemove.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/PreUpdate.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/SequenceGenerator.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Table.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/UniqueConstraint.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/Version.php</exclude-pattern>
<exclude-pattern>src/Mapping/AssociationOverride.php</exclude-pattern>
<exclude-pattern>src/Mapping/AssociationOverrides.php</exclude-pattern>
<exclude-pattern>src/Mapping/AttributeOverride.php</exclude-pattern>
<exclude-pattern>src/Mapping/AttributeOverrides.php</exclude-pattern>
<exclude-pattern>src/Mapping/Cache.php</exclude-pattern>
<exclude-pattern>src/Mapping/ChangeTrackingPolicy.php</exclude-pattern>
<exclude-pattern>src/Mapping/Column.php</exclude-pattern>
<exclude-pattern>src/Mapping/ColumnResult.php</exclude-pattern>
<exclude-pattern>src/Mapping/CustomIdGenerator.php</exclude-pattern>
<exclude-pattern>src/Mapping/DiscriminatorColumn.php</exclude-pattern>
<exclude-pattern>src/Mapping/DiscriminatorMap.php</exclude-pattern>
<exclude-pattern>src/Mapping/Embeddable.php</exclude-pattern>
<exclude-pattern>src/Mapping/Embedded.php</exclude-pattern>
<exclude-pattern>src/Mapping/Entity.php</exclude-pattern>
<exclude-pattern>src/Mapping/EntityListeners.php</exclude-pattern>
<exclude-pattern>src/Mapping/EntityResult.php</exclude-pattern>
<exclude-pattern>src/Mapping/FieldResult.php</exclude-pattern>
<exclude-pattern>src/Mapping/GeneratedValue.php</exclude-pattern>
<exclude-pattern>src/Mapping/HasLifecycleCallbacks.php</exclude-pattern>
<exclude-pattern>src/Mapping/Id.php</exclude-pattern>
<exclude-pattern>src/Mapping/Index.php</exclude-pattern>
<exclude-pattern>src/Mapping/InheritanceType.php</exclude-pattern>
<exclude-pattern>src/Mapping/JoinColumn.php</exclude-pattern>
<exclude-pattern>src/Mapping/JoinColumns.php</exclude-pattern>
<exclude-pattern>src/Mapping/JoinTable.php</exclude-pattern>
<exclude-pattern>src/Mapping/ManyToMany.php</exclude-pattern>
<exclude-pattern>src/Mapping/ManyToOne.php</exclude-pattern>
<exclude-pattern>src/Mapping/MappedSuperclass.php</exclude-pattern>
<exclude-pattern>src/Mapping/NamedNativeQueries.php</exclude-pattern>
<exclude-pattern>src/Mapping/NamedNativeQuery.php</exclude-pattern>
<exclude-pattern>src/Mapping/NamedQueries.php</exclude-pattern>
<exclude-pattern>src/Mapping/NamedQuery.php</exclude-pattern>
<exclude-pattern>src/Mapping/OneToMany.php</exclude-pattern>
<exclude-pattern>src/Mapping/OneToOne.php</exclude-pattern>
<exclude-pattern>src/Mapping/OrderBy.php</exclude-pattern>
<exclude-pattern>src/Mapping/PostLoad.php</exclude-pattern>
<exclude-pattern>src/Mapping/PostPersist.php</exclude-pattern>
<exclude-pattern>src/Mapping/PostRemove.php</exclude-pattern>
<exclude-pattern>src/Mapping/PostUpdate.php</exclude-pattern>
<exclude-pattern>src/Mapping/PreFlush.php</exclude-pattern>
<exclude-pattern>src/Mapping/PrePersist.php</exclude-pattern>
<exclude-pattern>src/Mapping/PreRemove.php</exclude-pattern>
<exclude-pattern>src/Mapping/PreUpdate.php</exclude-pattern>
<exclude-pattern>src/Mapping/SequenceGenerator.php</exclude-pattern>
<exclude-pattern>src/Mapping/SqlResultSetMapping.php</exclude-pattern>
<exclude-pattern>src/Mapping/SqlResultSetMappings.php</exclude-pattern>
<exclude-pattern>src/Mapping/Table.php</exclude-pattern>
<exclude-pattern>src/Mapping/UniqueConstraint.php</exclude-pattern>
<exclude-pattern>src/Mapping/Version.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Commenting.EmptyComment">
<exclude-pattern>lib/Doctrine/ORM/Cache/DefaultQueryCache.php</exclude-pattern>
<exclude-pattern>src/Cache/DefaultQueryCache.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming">
<exclude-pattern>lib/Doctrine/ORM/EntityManagerInterface.php</exclude-pattern>
<exclude-pattern>src/EntityManagerInterface.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousTraitNaming.SuperfluousSuffix">
<exclude-pattern>tests/Doctrine/Tests/Models/DDC1872/DDC1872ExampleTrait.php</exclude-pattern>
<exclude-pattern>tests/Tests/Models/DDC1872/DDC1872ExampleTrait.php</exclude-pattern>
</rule>
<rule name="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingAnyTypeHint">
@@ -167,25 +168,25 @@
<!-- intentionally without namespace -->
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
<exclude-pattern>tests/Doctrine/Tests/Models/Global/GlobalNamespaceModel.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/Models/DDC3231/DDC3231User1NoNamespace.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/Models/DDC3231/DDC3231User2NoNamespace.php</exclude-pattern>
<exclude-pattern>tests/Tests/Models/Global/GlobalNamespaceModel.php</exclude-pattern>
<exclude-pattern>tests/Tests/Models/DDC3231/DDC3231User1NoNamespace.php</exclude-pattern>
<exclude-pattern>tests/Tests/Models/DDC3231/DDC3231User2NoNamespace.php</exclude-pattern>
</rule>
<!-- file with multiple namespaces confuses the sniff -->
<rule ref="PSR2.Namespaces.UseDeclaration.UseAfterNamespace">
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2084Test.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/Ticket/DDC2084Test.php</exclude-pattern>
</rule>
<!-- file with multiple namespaces confuses the sniff -->
<rule ref="SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses.IncorrectlyOrderedUses">
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2084Test.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/Ticket/DDC2084Test.php</exclude-pattern>
</rule>
<!-- intentionally empty blocks -->
<rule ref="Generic.CodeAnalysis.EmptyStatement.DetectedForeach">
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1301Test.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/ExtraLazyCollectionTest.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/Ticket/DDC1301Test.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/ExtraLazyCollectionTest.php</exclude-pattern>
</rule>
<!--
@@ -193,90 +194,96 @@
different namespace. The use statement has to stay.
-->
<rule ref="SlevomatCodingStandard.Namespaces.UseFromSameNamespace.UseFromSameNamespace">
<exclude-pattern>tests/Doctrine/Tests/Models/DDC1590/DDC1590User.php</exclude-pattern>
<exclude-pattern>tests/Tests/Models/DDC1590/DDC1590User.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations.AnnotationForbidden">
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/Ticket/DDC832Test.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/Ticket/DDC832Test.php</exclude-pattern>
</rule>
<rule ref="Squiz.Classes.ValidClassName.NotCamelCaps">
<!-- we need to test what happens with an stdClass proxy -->
<exclude-pattern>tests/Doctrine/Tests/Proxy/DefaultProxyClassNameResolverTest.php</exclude-pattern>
<exclude-pattern>tests/Tests/Proxy/DefaultProxyClassNameResolverTest.php</exclude-pattern>
</rule>
<rule ref="Squiz.Commenting.FunctionComment.WrongStyle">
<!-- https://github.com/squizlabs/PHP_CodeSniffer/issues/1961 -->
<exclude-pattern>tests/Doctrine/Tests/Mocks/DatabasePlatformMock.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/Mocks/DriverMock.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/ORM/UnitOfWorkTest.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/ORM/Query/DeleteSqlGenerationTest.php</exclude-pattern>
<exclude-pattern>tests/Tests/Mocks/DatabasePlatformMock.php</exclude-pattern>
<exclude-pattern>tests/Tests/Mocks/DriverMock.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/UnitOfWorkTest.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Query/DeleteSqlGenerationTest.php</exclude-pattern>
</rule>
<rule ref="Squiz.Commenting.FunctionComment.InvalidNoReturn">
<!-- https://github.com/squizlabs/PHP_CodeSniffer/issues/2099 -->
<exclude-pattern>lib/Doctrine/ORM/Query/AST/Node.php</exclude-pattern>
<exclude-pattern>src/Query/AST/Node.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.NoAssignment">
<exclude-pattern>tests/Doctrine/Tests/ORM/Mapping/php/Doctrine.Tests*</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Mapping/php/Doctrine.Tests*</exclude-pattern>
</rule>
<rule ref="PSR2.Methods.MethodDeclaration.Underscore">
<exclude-pattern>lib/Doctrine/ORM/AbstractQuery.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/NativeQuery.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Query.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Query/TreeWalkerAdapter.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php</exclude-pattern>
<exclude-pattern>src/AbstractQuery.php</exclude-pattern>
<exclude-pattern>src/Mapping/ClassMetadataInfo.php</exclude-pattern>
<exclude-pattern>src/NativeQuery.php</exclude-pattern>
<exclude-pattern>src/Query.php</exclude-pattern>
<exclude-pattern>src/Query/TreeWalkerAdapter.php</exclude-pattern>
<exclude-pattern>src/Tools/Export/Driver/AbstractExporter.php</exclude-pattern>
<exclude-pattern>src/Tools/Export/Driver/AnnotationExporter.php</exclude-pattern>
<exclude-pattern>src/Tools/Export/Driver/PhpExporter.php</exclude-pattern>
<!-- extending a class from another package -->
<exclude-pattern>tests/Doctrine/Tests/Mocks/DatabasePlatformMock.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/Mocks/SchemaManagerMock.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/Ticket/DDC3634Test.php</exclude-pattern>
<exclude-pattern>tests/Tests/Mocks/DatabasePlatformMock.php</exclude-pattern>
<exclude-pattern>tests/Tests/Mocks/SchemaManagerMock.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/AbstractQueryTest.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/Ticket/DDC3634Test.php</exclude-pattern>
</rule>
<rule ref="Squiz.NamingConventions.ValidVariableName.PublicHasUnderscore">
<exclude-pattern>lib/Doctrine/ORM/AbstractQuery.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Configuration.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/EntityRepository.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Query/Printer.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php</exclude-pattern>
<exclude-pattern>src/AbstractQuery.php</exclude-pattern>
<exclude-pattern>src/Configuration.php</exclude-pattern>
<exclude-pattern>src/EntityRepository.php</exclude-pattern>
<exclude-pattern>src/Internal/Hydration/AbstractHydrator.php</exclude-pattern>
<exclude-pattern>src/Query/Exec/AbstractSqlExecutor.php</exclude-pattern>
<exclude-pattern>src/Query/Exec/AbstractSqlExecutor.php</exclude-pattern>
<exclude-pattern>src/Query/Printer.php</exclude-pattern>
<exclude-pattern>src/Tools/EntityRepositoryGenerator.php</exclude-pattern>
<exclude-pattern>src/Tools/Console/Helper/EntityManagerHelper.php</exclude-pattern>
<exclude-pattern>src/Tools/Export/Driver/AbstractExporter.php</exclude-pattern>
<exclude-pattern>src/Tools/Export/Driver/AnnotationExporter.php</exclude-pattern>
<exclude-pattern>src/Tools/Export/Driver/PhpExporter.php</exclude-pattern>
<exclude-pattern>src/Tools/Export/Driver/XmlExporter.php</exclude-pattern>
<exclude-pattern>src/Tools/Export/Driver/YamlExporter.php</exclude-pattern>
<!-- the impact of changing this would be too big -->
<exclude-pattern>tests/Doctrine/Tests/OrmFunctionalTestCase.php</exclude-pattern>
<exclude-pattern>tests/Tests/OrmFunctionalTestCase.php</exclude-pattern>
</rule>
<rule ref="Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps">
<!-- Member variable "__isCloning" is not in valid camel caps format -->
<exclude-pattern>lib/Doctrine/ORM/Proxy/ProxyFactory.php</exclude-pattern>
<exclude-pattern>src/Proxy/ProxyFactory.php</exclude-pattern>
<!-- accessing public property __isInitialized__ of a proxy -->
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/ProxiesLikeEntitiesTest.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses.MismatchingCaseSensitivity">
<!-- Using @group and Group entity in the same file -->
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1885Test.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1843Test.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/Ticket/DDC1885Test.php</exclude-pattern>
<exclude-pattern>tests/Tests/ORM/Functional/Ticket/DDC1843Test.php</exclude-pattern>
</rule>
<rule ref="Generic.CodeAnalysis.EmptyStatement.DetectedElse">
<!-- The missing code needs to be implemented someday -->
<exclude-pattern>lib/Doctrine/ORM/Id/TableGenerator.php</exclude-pattern>
<exclude-pattern>src/Id/TableGenerator.php</exclude-pattern>
</rule>
<rule ref="Generic.CodeAnalysis.EmptyStatement.DetectedIf">
<!-- The missing code needs to be implemented someday -->
<exclude-pattern>lib/Doctrine/ORM/Id/TableGenerator.php</exclude-pattern>
<exclude-pattern>src/Id/TableGenerator.php</exclude-pattern>
</rule>
<rule ref="Squiz.Commenting.FunctionComment.ExtraParamComment">
<!-- https://github.com/doctrine/orm/issues/8537 -->
<exclude-pattern>lib/Doctrine/ORM/QueryBuilder.php</exclude-pattern>
<exclude-pattern>src/QueryBuilder.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.PHP.UselessParentheses">
<!-- We need those parentheses to make enum access seem like valid syntax on PHP 7 -->
<exclude-pattern>src/Mapping/Driver/XmlDriver.php</exclude-pattern>
</rule>
</ruleset>

File diff suppressed because it is too large Load Diff

View File

@@ -7,12 +7,15 @@ parameters:
ignoreErrors:
# PHPStan doesn't understand our method_exists() safeguards.
- '/Call to function method_exists.*/'
- '/Call to an undefined method Doctrine\\DBAL\\Connection::createSchemaManager\(\)\./'
# Class name will change in DBAL 3.
- '/^Class Doctrine\\DBAL\\Platforms\\PostgreSQLPlatform not found\.$/'
- '/^Class Doctrine\\DBAL\\Platforms\\AbstractMySQLPlatform not found\.$/'
- '/^Class Doctrine\\DBAL\\Platforms\\MySQLPlatform not found\.$/'
-
message: '/Doctrine\\DBAL\\Platforms\\MyS(ql|QL)Platform/'
path: lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
path: src/Mapping/ClassMetadataFactory.php
# Forward compatibility for DBAL 3.5
- '/^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getAlterSchemaSQL\(\).$/'
@@ -20,44 +23,83 @@ parameters:
# Forward compatibility for DBAL 3.4
- '/^Call to an undefined method Doctrine\\DBAL\\Cache\\QueryCacheProfile::[gs]etResultCache\(\)\.$/'
-
message: '/^Call to an undefined static method Doctrine\\DBAL\\Configuration::[gs]etResultCache\(\)\.$/'
path: lib/Doctrine/ORM/Configuration.php
message: '/^Call to an undefined static method Doctrine\\DBAL\\Configuration::[gs]etResultCache\(\)\.$/'
path: src/Configuration.php
-
message: '/^Parameter #3 \$resultCache of class Doctrine\\DBAL\\Cache\\QueryCacheProfile constructor/'
path: lib/Doctrine/ORM/AbstractQuery.php
message: '/^Parameter #3 \$resultCache of class Doctrine\\DBAL\\Cache\\QueryCacheProfile constructor/'
path: src/AbstractQuery.php
-
message: '/^Parameter #2 \$\w+ of method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getDateAdd\w+Expression\(\) expects int, string given\.$/'
path: lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php
path: src/Query/AST/Functions/DateAddFunction.php
-
message: '/^Parameter #2 \$\w+ of method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getDateSub\w+Expression\(\) expects int, string given\.$/'
path: lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php
path: src/Query/AST/Functions/DateSubFunction.php
# False positive
-
message: '/^Call to an undefined method Doctrine\\Common\\Cache\\Cache::deleteAll\(\)\.$/'
count: 1
path: lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php
path: src/Tools/Console/Command/ClearCache/ResultCommand.php
# See https://github.com/doctrine/dbal/pull/5129
-
message: '/^Parameter #3 \$startPos of method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getLocateExpression\(\) expects int\|false, string given\.$/'
count: 1
path: lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php
path: src/Query/AST/Functions/LocateFunction.php
# Won't get fixed in DBAL 2
-
message: '#.*deleteItem.*expects string.*#'
count: 1
path: src/Query.php
-
message: '#.*get(Drop|Create)SchemaS(ql|QL).*should return list.*but returns array.*#'
count: 2
path: src/Tools/SchemaTool.php
-
message: '#introspectSchema#'
count: 2
identifier: 'method.notFound'
path: src/Tools/SchemaTool.php
-
message: '#getMaxIdentifierLength#'
identifier: 'method.deprecatedClass'
path: src/Mapping/ClassMetadataFactory.php
-
message: "#^Parameter \\#2 \\$start of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getSubstringExpression\\(\\) expects int, string given\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php
path: src/Query/AST/Functions/SubstringFunction.php
-
message: "#^Parameter \\#3 \\$length of method Doctrine\\\\DBAL\\\\Platforms\\\\AbstractPlatform\\:\\:getSubstringExpression\\(\\) expects int\\|null, string\\|null given\\.$#"
count: 1
path: lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php
path: src/Query/AST/Functions/SubstringFunction.php
-
message: '#^Class Doctrine\\DBAL\\Platforms\\MySQLPlatform not found\.$#'
count: 2
path: lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
path: src/Mapping/ClassMetadataFactory.php
- '~^Call to deprecated method getSQLResultCasing\(\) of class Doctrine\\DBAL\\Platforms\\AbstractPlatform\.$~'
-
message: '~deprecated class Doctrine\\DBAL\\Tools\\Console\\Command\\ImportCommand\:~'
path: src/Tools/Console/ConsoleRunner.php
-
message: '#^Method Doctrine\\ORM\\AbstractQuery\:\:getHydrationCacheId\(\) should return array\{string, string\} but returns array\<string\>\.$#'
path: src/AbstractQuery.php
-
message: '#^Method Doctrine\\ORM\\Internal\\Hydration\\AbstractHydrator\:\:\w+\(\) has parameter \$stmt with no value type specified in iterable type Doctrine\\DBAL\\Driver\\ResultStatement\.$#'
path: src/Internal/Hydration/AbstractHydrator.php
-
message: '#^Parameter \#1 \$key of method Psr\\Cache\\CacheItemPoolInterface\:\:deleteItem\(\) expects string, string\|false given\.$#'
path: src/Query
# Symfony cache supports passing a key prefix to the clear method.
- '/^Method Psr\\Cache\\CacheItemPoolInterface\:\:clear\(\) invoked with 1 parameter, 0 required\.$/'
@@ -65,10 +107,16 @@ parameters:
# Persistence 2 support
-
message: '/clear.*invoked with 1 parameter/'
path: lib/Doctrine/ORM/EntityRepository.php
path: src/EntityRepository.php
-
message: '#^Class Doctrine\\Persistence\\ObjectManagerAware not found\.$#'
path: lib/Doctrine/ORM/UnitOfWork.php
path: src/UnitOfWork.php
-
message: '#^Call to method injectObjectManager\(\) on an unknown class Doctrine\\Persistence\\ObjectManagerAware\.$#'
path: lib/Doctrine/ORM/UnitOfWork.php
path: src/UnitOfWork.php
-
message: '#contains generic type.*but class.*is not generic#'
paths:
- src/Mapping/Driver/XmlDriver.php
- src/Mapping/Driver/YamlDriver.php

View File

@@ -1,15 +1,11 @@
parameters:
level: 5
level: 7
paths:
- lib
- tests/Doctrine/StaticAnalysis
- src
- tests/StaticAnalysis
excludePaths:
- lib/Doctrine/ORM/Mapping/Driver/AttributeReader.php
- src/Mapping/Driver/AttributeReader.php
earlyTerminatingMethodCalls:
Doctrine\ORM\Query\Parser:
- syntaxError
phpVersion: 80200
ignoreErrors:
# Remove on 3.0.x
- '~^Default value of the parameter #2 \$value \(array\{\}\) of method Doctrine\\ORM\\Query\\AST\\InstanceOfExpression\:\:__construct\(\) is incompatible with type non\-empty\-array<int, Doctrine\\ORM\\Query\\AST\\InputParameter\|string>\.$~'
phpVersion: 80400

View File

@@ -3,36 +3,116 @@ includes:
- phpstan-params.neon
parameters:
reportUnmatchedIgnoredErrors: false
ignoreErrors:
# deprecations from doctrine/dbal:3.x
- '/^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getGuidExpression\(\).$/'
# Fallback logic for DBAL 2
-
message: '/Application::add\(\) expects Symfony\\Component\\Console\\Command\\Command/'
path: lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php
message: '/Parameter #2 \$command of static method Doctrine\\ORM\\Tools\\Console\\ConsoleRunner\:\:addCommandToApplication\(\) expects Symfony\\Component\\Console\\Command\\Command/'
path: src/Tools/Console/ConsoleRunner.php
- '/^Class Doctrine\\DBAL\\Platforms\\SQLAnywherePlatform not found\.$/'
- '/^Call to method \w+\(\) on an unknown class Doctrine\\DBAL\\Platforms\\SQLAnywherePlatform\.$/'
-
message: '/^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getSQLResultCasing\(\)\.$/'
path: lib/Doctrine/ORM/Internal/SQLResultCasing.php
message: '/^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getSQLResultCasing\(\)\.$/'
path: src/Internal/SQLResultCasing.php
-
message: '/^Parameter \$stmt of method .* has invalid type Doctrine\\DBAL\\Driver\\ResultStatement\.$/'
path: lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
message: '/^Parameter \$stmt of method .* has invalid type Doctrine\\DBAL\\Driver\\ResultStatement\.$/'
path: src/Internal/Hydration/AbstractHydrator.php
-
message: '/^Class Doctrine\\DBAL\\Driver\\ResultStatement not found\.$/'
path: lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
message: '/^Class Doctrine\\DBAL\\Driver\\ResultStatement not found\.$/'
path: src/Internal/Hydration/AbstractHydrator.php
-
message: '/^Call to static method ensure\(\) on an unknown class Doctrine\\DBAL\\ForwardCompatibility\\Result\.$/'
path: lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
message: '/^Call to static method ensure\(\) on an unknown class Doctrine\\DBAL\\ForwardCompatibility\\Result\.$/'
path: src/Internal/Hydration/AbstractHydrator.php
-
message: '/^Instanceof between Doctrine\\DBAL\\Platforms\\AbstractPlatform and Doctrine\\DBAL\\Platforms\\MySQLPlatform will always evaluate to false\.$/'
path: src/Utility/LockSqlHelper.php
# Forward compatibility with Collections 3
-
message: '#^Parameter \$order of anonymous function has invalid type Doctrine\\Common\\Collections\\Order\.$#'
path: src/Internal/CriteriaOrderings.php
-
message: '#^Anonymous function has invalid return type Doctrine\\Common\\Collections\\Order\.$#'
path: src/Internal/CriteriaOrderings.php
-
message: '#^Access to property \$value on an unknown class Doctrine\\Common\\Collections\\Order\.$#'
path: src/Internal/CriteriaOrderings.php
-
message: '#^Call to static method from\(\) on an unknown class Doctrine\\Common\\Collections\\Order\.$#'
path: src/Internal/CriteriaOrderings.php
-
message: '#^Call to an undefined method Doctrine\\Common\\Collections\\Criteria\:\:orderings\(\)\.$#'
path: src/Internal/CriteriaOrderings.php
-
message: '#^Method .+\:\:mapToOrderEnumIfAvailable\(\) has invalid return type Doctrine\\Common\\Collections\\Order\.$#'
path: src/Internal/CriteriaOrderings.php
# False positive
-
message: '/^Call to an undefined method Doctrine\\Common\\Cache\\Cache::deleteAll\(\)\.$/'
count: 1
path: lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php
path: src/Tools/Console/Command/ClearCache/ResultCommand.php
# Symfony cache supports passing a key prefix to the clear method.
- '/^Method Psr\\Cache\\CacheItemPoolInterface\:\:clear\(\) invoked with 1 parameter, 0 required\.$/'
-
message: '#contains generic type.*but class.*is not generic#'
paths:
- src/Mapping/Driver/XmlDriver.php
- src/Mapping/Driver/YamlDriver.php
# Extending a deprecated class conditionally to maintain BC
-
message: '~deprecated class Doctrine\\Persistence\\Mapping\\Driver\\AnnotationDriver\:~'
path: src/Mapping/Driver/CompatibilityAnnotationDriver.php
# We're sniffing for this deprecated class in order to detect Persistence 2
-
message: '~deprecated class Doctrine\\Common\\Persistence\\PersistentObject\:~'
path: src/EntityManager.php
-
message: '#Cannot access offset \S+ on .*ClassMetadata.*#'
paths:
- src/Mapping/Driver/XmlDriver.php
- src/Mapping/Driver/YamlDriver.php
-
message: '#^Parameter \#1 \$orderings of method Doctrine\\Common\\Collections\\Criteria\:\:orderBy\(\) expects array\<string\>, array\<string, Doctrine\\Common\\Collections\\Order\|string\> given\.$#'
path: src/PersistentCollection.php
-
message: '#^Parameter \#5 \.\.\.\$args of static method Doctrine\\Deprecations\\Deprecation\:\:trigger\(\) expects float\|int\|string, string\|false given\.$#'
path: src/Mapping/ClassMetadataFactory.php
-
message: '#^Parameter \#1 \$classNames of method Doctrine\\ORM\\Mapping\\ClassMetadataInfo\<object\>\:\:setParentClasses\(\) expects list\<class\-string\>, array\<string\> given\.$#'
path: src/Mapping/ClassMetadataFactory.php
-
message: '#loadMappingFile#'
identifier: 'return.type'
path: src/Mapping/Driver/XmlDriver.php
-
message: '#injectObjectManager#'
identifier: 'method.deprecatedInterface'
path: src/UnitOfWork.php
-
message: '#^Static method Doctrine\\Common\\Collections\\Criteria\:\:create\(\) invoked with 1 parameter, 0 required\.$#'
identifier: arguments.count
count: 3
path: src/Persisters/Collection/OneToManyPersister.php

View File

@@ -9,30 +9,33 @@ parameters:
# Fallback logic for DBAL 2
-
message: '/Application::add\(\) expects Symfony\\Component\\Console\\Command\\Command/'
path: lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php
message: '/Parameter #2 \$command of static method Doctrine\\ORM\\Tools\\Console\\ConsoleRunner\:\:addCommandToApplication\(\) expects Symfony\\Component\\Console\\Command\\Command/'
path: src/Tools/Console/ConsoleRunner.php
- '/^Class Doctrine\\DBAL\\Platforms\\SQLAnywherePlatform not found\.$/'
- '/^Call to method \w+\(\) on an unknown class Doctrine\\DBAL\\Platforms\\SQLAnywherePlatform\.$/'
-
message: '/^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getSQLResultCasing\(\)\.$/'
path: lib/Doctrine/ORM/Internal/SQLResultCasing.php
message: '/^Call to an undefined method Doctrine\\DBAL\\Platforms\\AbstractPlatform::getSQLResultCasing\(\)\.$/'
path: src/Internal/SQLResultCasing.php
-
message: '/^Parameter \$stmt of method .* has invalid type Doctrine\\DBAL\\Driver\\ResultStatement\.$/'
path: lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
message: '/^Parameter \$stmt of method .* has invalid type Doctrine\\DBAL\\Driver\\ResultStatement\.$/'
path: src/Internal/Hydration/AbstractHydrator.php
-
message: '/^Class Doctrine\\DBAL\\Driver\\ResultStatement not found\.$/'
path: lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
message: '/^Class Doctrine\\DBAL\\Driver\\ResultStatement not found\.$/'
path: src/Internal/Hydration/AbstractHydrator.php
-
message: '/^Call to static method ensure\(\) on an unknown class Doctrine\\DBAL\\ForwardCompatibility\\Result\.$/'
path: lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
message: '/^Call to static method ensure\(\) on an unknown class Doctrine\\DBAL\\ForwardCompatibility\\Result\.$/'
path: src/Internal/Hydration/AbstractHydrator.php
-
message: '/^Instanceof between Doctrine\\DBAL\\Platforms\\AbstractPlatform and Doctrine\\DBAL\\Platforms\\MySQLPlatform will always evaluate to false\.$/'
path: src/Utility/LockSqlHelper.php
# False positive
-
message: '/^Call to an undefined method Doctrine\\Common\\Cache\\Cache::deleteAll\(\)\.$/'
count: 1
path: lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php
path: src/Tools/Console/Command/ClearCache/ResultCommand.php
# Symfony cache supports passing a key prefix to the clear method.
- '/^Method Psr\\Cache\\CacheItemPoolInterface\:\:clear\(\) invoked with 1 parameter, 0 required\.$/'
@@ -40,10 +43,10 @@ parameters:
# Persistence 2 support
-
message: '/clear.*invoked with 1 parameter/'
path: lib/Doctrine/ORM/EntityRepository.php
path: src/EntityRepository.php
-
message: '#^Class Doctrine\\Persistence\\ObjectManagerAware not found\.$#'
path: lib/Doctrine/ORM/UnitOfWork.php
path: src/UnitOfWork.php
-
message: '#^Call to method injectObjectManager\(\) on an unknown class Doctrine\\Persistence\\ObjectManagerAware\.$#'
path: lib/Doctrine/ORM/UnitOfWork.php
path: src/UnitOfWork.php

View File

@@ -17,11 +17,11 @@
verbose="false"
failOnRisky="true"
convertDeprecationsToExceptions="true"
bootstrap="./tests/Doctrine/Tests/TestInit.php"
bootstrap="./tests/Tests/TestInit.php"
>
<testsuites>
<testsuite name="Doctrine ORM Test Suite">
<directory>./tests/Doctrine/Tests/ORM</directory>
<directory>./tests/Tests/ORM</directory>
</testsuite>
</testsuites>

File diff suppressed because it is too large Load Diff

301
psalm.xml
View File

@@ -1,301 +0,0 @@
<?xml version="1.0"?>
<psalm
errorLevel="2"
phpVersion="8.2"
resolveFromConfigFile="true"
findUnusedBaselineEntry="true"
findUnusedCode="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
>
<projectFiles>
<directory name="lib/Doctrine/ORM" />
<directory name="tests/Doctrine/StaticAnalysis" />
<ignoreFiles>
<directory name="vendor" />
<file name="lib/Doctrine/ORM/Mapping/Driver/AttributeReader.php" />
</ignoreFiles>
</projectFiles>
<enableExtensions>
<extension name="simplexml" />
</enableExtensions>
<issueHandlers>
<DeprecatedClass>
<errorLevel type="suppress">
<!-- DBAL 2 compatibility -->
<referencedClass name="Doctrine\DBAL\Tools\Console\Command\ImportCommand"/>
<referencedClass name="Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper"/>
<!-- The exception is thrown by a deprecated method. -->
<referencedClass name="Doctrine\ORM\Cache\Exception\InvalidResultCacheDriver"/>
<!-- We wire the command as long as DBAL ships it -->
<referencedClass name="Doctrine\DBAL\Tools\Console\Command\ReservedWordsCommand" />
<!-- Remove on 3.0.x -->
<referencedClass name="Doctrine\Common\Persistence\PersistentObject"/>
<referencedClass name="Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets"/>
<referencedClass name="Doctrine\ORM\Event\LifecycleEventArgs"/>
<referencedClass name="Doctrine\ORM\Exception\UnknownEntityNamespace"/>
<referencedClass name="Doctrine\ORM\Mapping\Driver\AnnotationDriver"/>
<referencedClass name="Doctrine\ORM\Mapping\Driver\YamlDriver"/>
<referencedClass name="Doctrine\ORM\Mapping\NamedNativeQueries"/>
<referencedClass name="Doctrine\ORM\Mapping\NamedNativeQuery"/>
<referencedClass name="Doctrine\ORM\Mapping\NamedQueries"/>
<referencedClass name="Doctrine\ORM\Mapping\NamedQuery"/>
<referencedClass name="Doctrine\ORM\Query\AST\InExpression"/>
<referencedClass name="Doctrine\ORM\Tools\Console\Command\ConvertDoctrine1SchemaCommand"/>
<referencedClass name="Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand"/>
<referencedClass name="Doctrine\ORM\Tools\Console\Command\EnsureProductionSettingsCommand"/>
<referencedClass name="Doctrine\ORM\Tools\Console\Command\GenerateEntitiesCommand"/>
<referencedClass name="Doctrine\ORM\Tools\Console\Command\GenerateRepositoriesCommand"/>
<referencedClass name="Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper"/>
<referencedClass name="Doctrine\ORM\Tools\Console\EntityManagerProvider\HelperSetManagerProvider"/>
</errorLevel>
</DeprecatedClass>
<DeprecatedConstant>
<errorLevel type="suppress">
<file name="lib/Doctrine/ORM/Configuration.php"/>
<file name="lib/Doctrine/ORM/Query/Lexer.php"/>
<file name="lib/Doctrine/ORM/Query/Parser.php"/>
<file name="lib/Doctrine/ORM/QueryBuilder.php"/>
<file name="lib/Doctrine/ORM/Tools/EntityGenerator.php"/>
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php" />
<file name="lib/Doctrine/ORM/Tools/EntityGenerator.php" />
<file name="lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php" />
<file name="lib/Doctrine/ORM/Tools/SchemaTool.php" />
</errorLevel>
</DeprecatedConstant>
<DeprecatedInterface>
<errorLevel type="suppress">
<!-- Remove on 3.0.x -->
<referencedClass name="Doctrine\ORM\Cache\MultiGetRegion"/>
<referencedClass name="Doctrine\ORM\Mapping\Annotation"/>
</errorLevel>
</DeprecatedInterface>
<DeprecatedMethod>
<errorLevel type="suppress">
<!-- We're calling the deprecated method for BC here. -->
<file name="lib/Doctrine/ORM/Internal/SQLResultCasing.php"/>
<referencedMethod name="Doctrine\DBAL\Platforms\AbstractPlatform::getIdentitySequenceName"/>
<referencedMethod name="Doctrine\DBAL\Platforms\AbstractPlatform::usesSequenceEmulatedIdentityColumns"/>
<!-- We need to keep the calls for DBAL 2.13 compatibility. -->
<referencedMethod name="Doctrine\DBAL\Cache\QueryCacheProfile::getResultCacheDriver"/>
<referencedMethod name="Doctrine\DBAL\Cache\QueryCacheProfile::setResultCacheDriver"/>
<referencedMethod name="Doctrine\DBAL\Configuration::getResultCacheImpl"/>
<referencedMethod name="Doctrine\DBAL\Configuration::setResultCacheImpl"/>
<referencedMethod name="Doctrine\DBAL\Connection::getSchemaManager"/>
<referencedMethod name="Doctrine\DBAL\Platforms\AbstractPlatform::getGuidExpression"/>
<referencedMethod name="Doctrine\DBAL\Platforms\AbstractPlatform::supportsForeignKeyConstraints"/>
<!-- Remove on 3.0.x -->
<referencedMethod name="Doctrine\DBAL\Connection::getEventManager"/>
<referencedMethod name="Doctrine\DBAL\Schema\Schema::visit"/>
<referencedMethod name="Doctrine\DBAL\Schema\SchemaDiff::toSaveSql"/>
<referencedMethod name="Doctrine\DBAL\Schema\SchemaDiff::toSql"/>
<referencedMethod name="Doctrine\ORM\Internal\Hydration\AbstractHydrator::hydrateRow"/>
<referencedMethod name="Doctrine\ORM\Configuration::ensureProductionSettings"/>
<referencedMethod name="Doctrine\ORM\Configuration::newDefaultAnnotationDriver"/>
<referencedMethod name="Doctrine\ORM\EntityManager::createConnection"/>
<referencedMethod name="Doctrine\ORM\EntityManagerInterface::getPartialReference"/>
<referencedMethod name="Doctrine\ORM\Id\AbstractIdGenerator::generate"/>
<referencedMethod name="Doctrine\ORM\ORMInvalidArgumentException::invalidEntityName"/>
<referencedMethod name="Doctrine\ORM\ORMSetup::createDefaultAnnotationDriver"/>
<referencedMethod name="Doctrine\ORM\Query\SqlWalker::walkInExpression"/>
<referencedMethod name="Doctrine\ORM\Query\TreeWalkerAdapter::_getQueryComponents"/>
<referencedMethod name="Doctrine\ORM\Mapping\ClassMetadataInfo::isInheritanceTypeTablePerClass"/>
<file name="lib/Doctrine/ORM/Query/TreeWalkerChain.php"/>
</errorLevel>
</DeprecatedMethod>
<DeprecatedProperty>
<errorLevel type="suppress">
<referencedProperty name="Doctrine\ORM\Cache\Region\DefaultRegion::$cache"/>
<referencedProperty name="Doctrine\ORM\Mapping\Driver\AttributeDriver::$entityAnnotationClasses"/>
</errorLevel>
</DeprecatedProperty>
<DocblockTypeContradiction>
<errorLevel type="suppress">
<!-- We're catching invalid input here. -->
<file name="lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php"/>
<!-- DBAL 3.2 forward compatibility -->
<file name="lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php"/>
<file name="lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php"/>
<!-- https://github.com/vimeo/psalm/issues/8520 -->
<file name="lib/Doctrine/ORM/PersistentCollection.php"/>
</errorLevel>
</DocblockTypeContradiction>
<DuplicateClass>
<errorLevel type="suppress">
<file name="lib/Doctrine/ORM/Tools/Console/CommandCompatibility.php"/>
<file name="lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php"/>
</errorLevel>
</DuplicateClass>
<ForbiddenCode>
<errorLevel type="suppress">
<file name="lib/Doctrine/ORM/Tools/Debug.php"/>
</errorLevel>
</ForbiddenCode>
<InvalidArgument>
<errorLevel type="suppress">
<!-- Argument type changes in DBAL 3.2 -->
<referencedFunction name="Doctrine\DBAL\Cache\QueryCacheProfile::__construct"/>
<!-- https://github.com/vimeo/psalm/issues/9155 -->
<referencedFunction name="Doctrine\ORM\Mapping\ClassMetadata::addInheritedAssociationMapping"/>
</errorLevel>
</InvalidArgument>
<InvalidArrayAccess>
<errorLevel type="suppress">
<!-- https://github.com/vimeo/psalm/issues/9160 -->
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
</errorLevel>
</InvalidArrayAccess>
<InvalidArrayAssignment>
<errorLevel type="suppress">
<!-- https://github.com/vimeo/psalm/issues/9160 -->
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
</errorLevel>
</InvalidArrayAssignment>
<InvalidClass>
<errorLevel type="suppress">
<!-- Class name changes in DBAL 3. -->
<referencedClass name="Doctrine\DBAL\Platforms\PostgreSQLPlatform" />
</errorLevel>
</InvalidClass>
<InvalidParamDefault>
<errorLevel type="suppress">
<!-- Remove on 3.0.x -->
<file name="lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php"/>
</errorLevel>
</InvalidParamDefault>
<InvalidPropertyAssignmentValue>
<errorLevel type="suppress">
<!-- https://github.com/vimeo/psalm/issues/9155 -->
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
</errorLevel>
</InvalidPropertyAssignmentValue>
<MethodSignatureMismatch>
<errorLevel type="suppress">
<!-- See https://github.com/vimeo/psalm/issues/7357 -->
<file name="lib/Doctrine/ORM/Mapping/ReflectionReadonlyProperty.php"/>
</errorLevel>
</MethodSignatureMismatch>
<MissingDependency>
<errorLevel type="suppress">
<!-- DBAL 3.2 forward compatibility -->
<file name="lib/Doctrine/ORM/Internal/SQLResultCasing.php"/>
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
<file name="lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php"/>
</errorLevel>
</MissingDependency>
<MissingParamType>
<errorLevel type="suppress">
<!-- Persistence 2 compatibility -->
<file name="lib/Doctrine/ORM/EntityManager.php"/>
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php"/>
</errorLevel>
</MissingParamType>
<NonInvariantDocblockPropertyType>
<errorLevel type="suppress">
<!-- Remove on 3.0.x -->
<file name="lib/Doctrine/ORM/Query/AST/InListExpression.php"/>
<file name="lib/Doctrine/ORM/Query/AST/InSubselectExpression.php"/>
</errorLevel>
</NonInvariantDocblockPropertyType>
<PossiblyInvalidArgument>
<errorLevel type="suppress">
<!-- https://github.com/vimeo/psalm/issues/9155 -->
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
</errorLevel>
</PossiblyInvalidArgument>
<PropertyNotSetInConstructor>
<errorLevel type="suppress">
<!-- Remove on 3.0.x -->
<referencedProperty name="Doctrine\ORM\Cache\CacheKey::$hash"/>
</errorLevel>
<errorLevel type="suppress">
<directory name="lib/Doctrine/ORM/Query/AST" />
</errorLevel>
</PropertyNotSetInConstructor>
<PropertyTypeCoercion>
<errorLevel type="suppress">
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php"/>
</errorLevel>
</PropertyTypeCoercion>
<RedundantCastGivenDocblockType>
<errorLevel type="suppress">
<!-- Can be removed once the "getMaxResults" methods of those classes have native parameter types -->
<file name="lib/Doctrine/ORM/Query.php"/>
<file name="lib/Doctrine/ORM/QueryBuilder.php"/>
</errorLevel>
</RedundantCastGivenDocblockType>
<RedundantCondition>
<errorLevel type="suppress">
<!-- The SQLAnywherePlatform class may or may not exist depending on the DBAL version -->
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
</errorLevel>
</RedundantCondition>
<ReferenceConstraintViolation>
<errorLevel type="suppress">
<!-- https://github.com/vimeo/psalm/issues/9155 -->
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
</errorLevel>
</ReferenceConstraintViolation>
<TooManyArguments>
<errorLevel type="suppress">
<!-- Symfony cache supports passing a key prefix to the clear method. -->
<referencedFunction name="Psr\Cache\CacheItemPoolInterface::clear"/>
<!-- Persistence 2 compatibility -->
<referencedFunction name="Doctrine\Persistence\ObjectManager::clear"/>
<!-- Remove on 3.0.x -->
<referencedFunction name="Doctrine\Persistence\ObjectManager::refresh"/>
</errorLevel>
</TooManyArguments>
<TypeDoesNotContainType>
<errorLevel type="suppress">
<file name="lib/Doctrine/ORM/Internal/SQLResultCasing.php"/>
<file name="lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php"/>
</errorLevel>
</TypeDoesNotContainType>
<UndefinedClass>
<errorLevel type="suppress">
<referencedClass name="Doctrine\Common\Cache\ApcCache"/>
<referencedClass name="Doctrine\Common\Cache\ArrayCache"/>
<referencedClass name="Doctrine\Common\Cache\XcacheCache"/>
<!-- DBAL 2 compatibility -->
<referencedClass name="Doctrine\DBAL\Driver\ResultStatement"/>
<referencedClass name="Doctrine\DBAL\ForwardCompatibility\Result"/>
<referencedClass name="Doctrine\DBAL\Platforms\SQLAnywherePlatform"/>
<!-- DBAL 3.2 forward compatibility -->
<referencedClass name="Doctrine\DBAL\Platforms\PostgreSQLPlatform"/>
<referencedClass name="Doctrine\DBAL\Platforms\SQLServerPlatform"/>
<!-- Persistence 2 compatibility -->
<referencedClass name="Doctrine\Persistence\ObjectManagerAware"/>
<!-- Annotations 1 compatibility -->
<referencedClass name="Doctrine\Common\Annotations\CachedReader"/>
</errorLevel>
</UndefinedClass>
<UndefinedDocblockClass>
<errorLevel type="suppress">
<!-- DBAL 2 compatibility -->
<referencedClass name="Doctrine\DBAL\Driver\ResultStatement"/>
</errorLevel>
</UndefinedDocblockClass>
<UndefinedMethod>
<errorLevel type="suppress">
<!-- See https://github.com/doctrine/orm/issues/8884 -->
<referencedMethod name="Doctrine\DBAL\Platforms\AbstractPlatform::getGuidExpression"/>
</errorLevel>
</UndefinedMethod>
<MissingClosureReturnType>
<errorLevel type="suppress">
<file name="lib/Doctrine/ORM/Tools/Pagination/Paginator.php"/>
</errorLevel>
</MissingClosureReturnType>
</issueHandlers>
</psalm>

View File

@@ -1,21 +0,0 @@
#!/bin/bash
# This script is a small convenience wrapper for running the doctrine testsuite against a large bunch of databases.
# Just create the phpunit.xmls as described in the array below and configure the specific files <php /> section
# to connect to that database. Just omit a file if you don't have that database and the tests will be skipped.
configs[1]="mysql.phpunit.xml"
configs[2]='postgres.phpunit.xml'
configs[3]='sqlite.phpunit.xml'
configs[4]='oracle.phpunit.xml'
configs[5]='db2.phpunit.xml'
configs[6]='pdo-ibm.phpunit.xml'
configs[7]='sqlsrv.phpunit.xml'
for i in "${configs[@]}"; do
if [ -f "$i" ];
then
echo "RUNNING TESTS WITH CONFIG $i"
phpunit -c "$i" "$@"
fi;
done

View File

@@ -21,7 +21,6 @@ use Doctrine\ORM\Internal\Hydration\IterableResult;
use Doctrine\ORM\Mapping\MappingException as ORMMappingException;
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
use Doctrine\ORM\Query\Parameter;
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Persistence\Mapping\MappingException;
use LogicException;
@@ -90,7 +89,7 @@ abstract class AbstractQuery
* The parameter map of this query.
*
* @var ArrayCollection|Parameter[]
* @psalm-var ArrayCollection<int, Parameter>
* @phpstan-var ArrayCollection<int, Parameter>
*/
protected $parameters;
@@ -111,7 +110,7 @@ abstract class AbstractQuery
/**
* The map of query hints.
*
* @psalm-var array<string, mixed>
* @phpstan-var array<string, mixed>
*/
protected $_hints = [];
@@ -119,7 +118,7 @@ abstract class AbstractQuery
* The hydration mode.
*
* @var string|int
* @psalm-var string|AbstractQuery::HYDRATE_*
* @phpstan-var string|AbstractQuery::HYDRATE_*
*/
protected $_hydrationMode = self::HYDRATE_OBJECT;
@@ -157,7 +156,7 @@ abstract class AbstractQuery
* Second level query cache mode.
*
* @var int|null
* @psalm-var Cache::MODE_*|null
* @phpstan-var Cache::MODE_*|null
*/
protected $cacheMode;
@@ -254,7 +253,7 @@ abstract class AbstractQuery
/**
* @return int|null
* @psalm-return Cache::MODE_*|null
* @phpstan-return Cache::MODE_*|null
*/
public function getCacheMode()
{
@@ -263,7 +262,7 @@ abstract class AbstractQuery
/**
* @param int $cacheMode
* @psalm-param Cache::MODE_* $cacheMode
* @phpstan-param Cache::MODE_* $cacheMode
*
* @return $this
*/
@@ -311,7 +310,7 @@ abstract class AbstractQuery
* Get all defined parameters.
*
* @return ArrayCollection The defined query parameters.
* @psalm-return ArrayCollection<int, Parameter>
* @phpstan-return ArrayCollection<int, Parameter>
*/
public function getParameters()
{
@@ -344,14 +343,14 @@ abstract class AbstractQuery
* Sets a collection of query parameters.
*
* @param ArrayCollection|mixed[] $parameters
* @psalm-param ArrayCollection<int, Parameter>|mixed[] $parameters
* @phpstan-param ArrayCollection<int, Parameter>|mixed[] $parameters
*
* @return $this
*/
public function setParameters($parameters)
{
if (is_array($parameters)) {
/** @psalm-var ArrayCollection<int, Parameter> $parameterCollection */
/** @phpstan-var ArrayCollection<int, Parameter> $parameterCollection */
$parameterCollection = new ArrayCollection();
foreach ($parameters as $key => $value) {
@@ -558,9 +557,11 @@ abstract class AbstractQuery
// DBAL 2
if (! method_exists(QueryCacheProfile::class, 'setResultCache')) {
// @phpstan-ignore method.deprecated
if (! $profile->getResultCacheDriver()) {
$defaultHydrationCacheImpl = $this->_em->getConfiguration()->getHydrationCache();
if ($defaultHydrationCacheImpl) {
// @phpstan-ignore method.deprecated
$profile = $profile->setResultCacheDriver(DoctrineProvider::wrap($defaultHydrationCacheImpl));
}
}
@@ -609,9 +610,11 @@ abstract class AbstractQuery
// DBAL 2
if (! method_exists(QueryCacheProfile::class, 'setResultCache')) {
// @phpstan-ignore method.deprecated
if (! $profile->getResultCacheDriver()) {
$defaultResultCacheDriver = $this->_em->getConfiguration()->getResultCache();
if ($defaultResultCacheDriver) {
// @phpstan-ignore method.deprecated
$profile = $profile->setResultCacheDriver(DoctrineProvider::wrap($defaultResultCacheDriver));
}
}
@@ -677,6 +680,7 @@ abstract class AbstractQuery
$resultCacheDriver = DoctrineProvider::wrap($resultCache);
$this->_queryCacheProfile = $this->_queryCacheProfile
// @phpstan-ignore method.deprecated
? $this->_queryCacheProfile->setResultCacheDriver($resultCacheDriver)
: new QueryCacheProfile(0, null, $resultCacheDriver);
@@ -780,6 +784,7 @@ abstract class AbstractQuery
// Compatibility for DBAL 2
if (! method_exists($this->_queryCacheProfile, 'setResultCache')) {
// @phpstan-ignore method.deprecated
$this->_queryCacheProfile = $this->_queryCacheProfile->setResultCacheDriver(DoctrineProvider::wrap($cache));
return $this;
@@ -838,7 +843,7 @@ abstract class AbstractQuery
* @param class-string $class
* @param string $assocName
* @param int $fetchMode
* @psalm-param Mapping\ClassMetadata::FETCH_EAGER|Mapping\ClassMetadata::FETCH_LAZY $fetchMode
* @phpstan-param Mapping\ClassMetadata::FETCH_EAGER|Mapping\ClassMetadata::FETCH_LAZY $fetchMode
*
* @return $this
*/
@@ -864,7 +869,7 @@ abstract class AbstractQuery
*
* @param string|int $hydrationMode Doctrine processing mode to be used during hydration process.
* One of the Query::HYDRATE_* constants.
* @psalm-param string|AbstractQuery::HYDRATE_* $hydrationMode
* @phpstan-param string|AbstractQuery::HYDRATE_* $hydrationMode
*
* @return $this
*/
@@ -879,7 +884,7 @@ abstract class AbstractQuery
* Gets the hydration mode currently used by the query.
*
* @return string|int
* @psalm-return string|AbstractQuery::HYDRATE_*
* @phpstan-return string|AbstractQuery::HYDRATE_*
*/
public function getHydrationMode()
{
@@ -892,7 +897,7 @@ abstract class AbstractQuery
* Alias for execute(null, $hydrationMode = HYDRATE_OBJECT).
*
* @param string|int $hydrationMode
* @psalm-param string|AbstractQuery::HYDRATE_* $hydrationMode
* @phpstan-param string|AbstractQuery::HYDRATE_* $hydrationMode
*
* @return mixed
*/
@@ -941,7 +946,7 @@ abstract class AbstractQuery
* Get exactly one result or null.
*
* @param string|int|null $hydrationMode
* @psalm-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
* @phpstan-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
*
* @return mixed
*
@@ -979,7 +984,7 @@ abstract class AbstractQuery
* If there is no result, a NoResultException is thrown.
*
* @param string|int|null $hydrationMode
* @psalm-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
* @phpstan-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
*
* @return mixed
*
@@ -1077,8 +1082,8 @@ abstract class AbstractQuery
*
* @param ArrayCollection|mixed[]|null $parameters The query parameters.
* @param string|int|null $hydrationMode The hydration mode to use.
* @psalm-param ArrayCollection<int, Parameter>|array<string, mixed>|null $parameters
* @psalm-param string|AbstractQuery::HYDRATE_*|null $hydrationMode The hydration mode to use.
* @phpstan-param ArrayCollection<int, Parameter>|array<string, mixed>|null $parameters
* @phpstan-param string|AbstractQuery::HYDRATE_*|null $hydrationMode The hydration mode to use.
*
* @return IterableResult
*/
@@ -1115,8 +1120,8 @@ abstract class AbstractQuery
*
* @param ArrayCollection|array|mixed[] $parameters The query parameters.
* @param string|int|null $hydrationMode The hydration mode to use.
* @psalm-param ArrayCollection<int, Parameter>|mixed[] $parameters
* @psalm-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
* @phpstan-param ArrayCollection<int, Parameter>|mixed[] $parameters
* @phpstan-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
*
* @return iterable<mixed>
*/
@@ -1138,10 +1143,6 @@ abstract class AbstractQuery
throw new LogicException('Uninitialized result set mapping.');
}
if ($rsm->isMixed && count($rsm->scalarMappings) > 0) {
throw QueryException::iterateWithMixedResultNotAllowed();
}
$stmt = $this->_doExecute();
return $this->_em->newHydrator($this->_hydrationMode)->toIterable($stmt, $rsm, $this->_hints);
@@ -1152,8 +1153,8 @@ abstract class AbstractQuery
*
* @param ArrayCollection|mixed[]|null $parameters Query parameters.
* @param string|int|null $hydrationMode Processing mode to be used during the hydration process.
* @psalm-param ArrayCollection<int, Parameter>|mixed[]|null $parameters
* @psalm-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
* @phpstan-param ArrayCollection<int, Parameter>|mixed[]|null $parameters
* @phpstan-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
*
* @return mixed
*/
@@ -1171,8 +1172,8 @@ abstract class AbstractQuery
*
* @param ArrayCollection|mixed[]|null $parameters
* @param string|int|null $hydrationMode
* @psalm-param ArrayCollection<int, Parameter>|mixed[]|null $parameters
* @psalm-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
* @phpstan-param ArrayCollection<int, Parameter>|mixed[]|null $parameters
* @phpstan-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
*
* @return mixed
*/
@@ -1235,6 +1236,7 @@ abstract class AbstractQuery
// Support for DBAL 2
if (! method_exists($this->_hydrationCacheProfile, 'getResultCache')) {
// @phpstan-ignore method.deprecated
$cacheDriver = $this->_hydrationCacheProfile->getResultCacheDriver();
assert($cacheDriver !== null);
@@ -1252,8 +1254,8 @@ abstract class AbstractQuery
*
* @param ArrayCollection|mixed[]|null $parameters
* @param string|int|null $hydrationMode
* @psalm-param ArrayCollection<int, Parameter>|mixed[]|null $parameters
* @psalm-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
* @phpstan-param ArrayCollection<int, Parameter>|mixed[]|null $parameters
* @phpstan-param string|AbstractQuery::HYDRATE_*|null $hydrationMode
*
* @return mixed
*/
@@ -1316,7 +1318,7 @@ abstract class AbstractQuery
* automatically generated for you.
*
* @return string[] ($key, $hash)
* @psalm-return array{string, string} ($key, $hash)
* @phpstan-return array{string, string} ($key, $hash)
*/
protected function getHydrationCacheId()
{

View File

@@ -21,15 +21,13 @@ class AssociationCacheEntry implements CacheEntry
* The entity class name
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var string
* @psalm-var class-string
* @var class-string
*/
public $class;
/**
* @param string $class The entity class.
* @param class-string $class The entity class.
* @param array<string, mixed> $identifier The entity identifier.
* @psalm-param class-string $class
*/
public function __construct($class, array $identifier)
{

View File

@@ -15,7 +15,7 @@ use Doctrine\ORM\Persisters\Entity\EntityPersister;
/**
* Contract for building second level cache regions components.
*
* @psalm-import-type AssociationMapping from ClassMetadata
* @phpstan-import-type AssociationMapping from ClassMetadata
*/
interface CacheFactory
{

View File

@@ -26,8 +26,7 @@ class CollectionCacheKey extends CacheKey
* The owner entity class
*
* @readonly Public only for performance reasons, it should be considered immutable.
* @var string
* @psalm-var class-string
* @var class-string
*/
public $entityClass;
@@ -40,12 +39,11 @@ class CollectionCacheKey extends CacheKey
public $association;
/**
* @param string $entityClass The entity class.
* @param class-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)
public function __construct($entityClass, $association, array $ownerIdentifier, string $filterHash = '')
{
ksort($ownerIdentifier);
@@ -53,6 +51,8 @@ class CollectionCacheKey extends CacheKey
$this->entityClass = (string) $entityClass;
$this->association = (string) $association;
parent::__construct(str_replace('\\', '.', strtolower($entityClass)) . '_' . implode(' ', $ownerIdentifier) . '__' . $association);
$filterHash = $filterHash === '' ? '' : '_' . $filterHash;
parent::__construct(str_replace('\\', '.', strtolower($entityClass)) . '_' . implode(' ', $ownerIdentifier) . '__' . $association . $filterHash);
}
}

View File

@@ -31,7 +31,7 @@ class DefaultCache implements Cache
/**
* @var QueryCache[]
* @psalm-var array<string, QueryCache>
* @phpstan-var array<string, QueryCache>
*/
private $queryCaches = [];

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