Compare commits

...

985 Commits

Author SHA1 Message Date
Grégoire Paris
1f7a7a58ae Merge pull request #8506 from greg0ire/drop-branch-alias
Drop branch alias
2021-02-23 09:17:20 +01:00
Grégoire Paris
51063f502f Drop branch alias
It should not conflict with the future, brand new 3.0.x.
2021-02-23 09:10:11 +01:00
Menno Holtkamp
e8c4d7b177 Add Doctrine\ORM\Query\Expr::mod() (#6747) 2020-09-22 15:21:21 +02:00
Alexander Berl
2a98a98cd3 Replace "Blacklist" with "Banlist" in join example (#8175) 2020-06-09 07:39:41 +02:00
Grégoire Paris
01de90c141 Use correct target branch info in PR templates (#8171)
The current branch for bugfixes is 2.7, and new features should go on
2.8.x, not master.
2020-06-04 22:19:41 +02:00
Guilliam Xavier
dddd899322 Show full XML filename for dataset in test failure report (#7346) 2020-05-31 19:03:45 +02:00
Guilherme Blanco
72bc09926d Updated persisters 2020-05-10 23:43:54 -04:00
Guilherme Blanco
49dd4c81d0 Updated persister->update() 2020-05-10 15:39:33 -04:00
Guilherme Blanco
3460805efe Disable embedded temporarily 2020-05-10 11:40:43 -04:00
Guilherme Blanco
722f4a86b3 More work towards embeddables 2020-05-09 16:04:35 -04:00
Guilherme Blanco
1af6270095 Initial work on adding support back to embeddables on ORM 3 2020-05-05 10:02:40 -04:00
Guilherme Blanco
9a8e1fb477 phpstan 2020-05-04 17:27:09 -04:00
Guilherme Blanco
426ddb87a5 PHPCS 2020-05-04 17:25:46 -04:00
Guilherme Blanco
e7d2ac5277 PHP 7.4 2020-05-04 16:35:32 -04:00
Guilherme Blanco
d1302eabad Moving Github actions to PHP 7.3, since DBAL requires 7.3 as minimum dependency 2020-05-04 15:23:33 -04:00
Guilherme Blanco
5592535a56 Introduced LazyDataType support. 2020-05-04 14:18:58 -04:00
Guilherme Blanco
a3e53b6a23 Updated composer.json and made unit tests run, not necessarily pass... (#7921)
* Updated composer.json and made unit tests run, not necessarily pass...

* Addressed code review comments. Fixed BC break in AbstractPlatform now relying on column name to be provided when generating the column sql definition. Switched a skipped embedded test to its proper group

* Several test fixes

* Update doctrine/dbal dep to concrete commit

dev-snapshot/develop/2018-11-26 is not found by composer

* Update Tidelift item to fix auto-verification

* Add Tidelift enterprise marketing language

* Adapt contributing guide to new target versions

* Set link to contribution guide for target branches

* Run Static analysis and coding standards in Github Actions (#8049)

* Run Static analysis and coding standards in Github Actions

* Remove static analysis from Travis.

* Run on PRs and Push to master branch

* Add name suggestions by Gregoire

* Downgrade version to lowest supported.

* Suggestions by Gabriel, Luis and Claudio

* Update .github/workflows/ci.yml

Co-Authored-By: Gabriel Caruso <carusogabriel34@gmail.com>

Co-authored-by: Gabriel Caruso <carusogabriel34@gmail.com>

* Fix: Give workflow a name (#8060)

* Updated composer.json and made unit tests run, not necessarily pass...

* Addressed code review comments. Fixed BC break in AbstractPlatform now relying on column name to be provided when generating the column sql definition. Switched a skipped embedded test to its proper group

* Several test fixes

* Several fixes to unit tests and codebase to make it run on DBAL 3.0.x

* Unit test suite now passes

* Test for 7.4

* Remove 7.2

* Finished fixing phpunit, phpstan and phpcs

* Make scrutinizer run with PHP 7.4

* Attempt to improve travis

* Take 2

* More work on travis

* Take 4

* xdebug

* xdebug

Co-authored-by: Simon Podlipsky <simon@podlipsky.net>
Co-authored-by: Benjamin Eberlei <kontakt@beberlei.de>
Co-authored-by: Blaine Bublitz <blaine@tidelift.com>
Co-authored-by: Jonathan H. Wage <jonwage@gmail.com>
Co-authored-by: Claudio Zizza <claudio@budgegeria.de>
Co-authored-by: Claudio Zizza <859964+SenseException@users.noreply.github.com>
Co-authored-by: Gabriel Caruso <carusogabriel34@gmail.com>
2020-05-01 14:17:07 -04:00
Benjamin Eberlei
8c259ea5cb Fix: Give workflow a name (#8060) 2020-03-04 23:32:11 +01:00
Benjamin Eberlei
7de263c740 Run Static analysis and coding standards in Github Actions (#8049)
* Run Static analysis and coding standards in Github Actions

* Remove static analysis from Travis.

* Run on PRs and Push to master branch

* Add name suggestions by Gregoire

* Downgrade version to lowest supported.

* Suggestions by Gabriel, Luis and Claudio

* Update .github/workflows/ci.yml

Co-Authored-By: Gabriel Caruso <carusogabriel34@gmail.com>

Co-authored-by: Gabriel Caruso <carusogabriel34@gmail.com>
2020-03-02 22:29:15 +01:00
Claudio Zizza
c7faafa192 Merge pull request #8021 from SenseException/contribute-version
Update target branches of CONTRIBUTING.md
2020-02-17 11:11:59 +01:00
Claudio Zizza
f9a01ae9c4 Set link to contribution guide for target branches 2020-02-14 23:16:20 +01:00
Claudio Zizza
c673a3daf2 Adapt contributing guide to new target versions 2020-02-14 21:33:29 +01:00
Jonathan H. Wage
e77091399a Merge pull request #8001 from phated/patch-2
Add Tidelift enterprise marketing language
2020-01-23 13:41:39 -06:00
Jonathan H. Wage
5b3f9ee3c7 Merge pull request #8000 from phated/patch-1
Update Tidelift item to fix auto-verification
2020-01-23 13:40:58 -06:00
Blaine Bublitz
eae20efb24 Add Tidelift enterprise marketing language 2020-01-23 11:19:36 -07:00
Blaine Bublitz
8d0c6a8746 Update Tidelift item to fix auto-verification 2020-01-23 10:58:45 -07:00
Benjamin Eberlei
ff65cae170 Merge pull request #7938 from simPod/fix-dbal-dep
Update doctrine/dbal dep to concrete commit
2020-01-07 23:54:53 +01:00
Simon Podlipsky
662a71b08a Update doctrine/dbal dep to concrete commit
dev-snapshot/develop/2018-11-26 is not found by composer
2019-12-01 12:04:16 +01:00
Luís Cobucci
b06efe3408 Merge pull request #7914 from lcobucci/update-branch-information
Add branch 2.8 to docs
2019-11-22 14:00:49 +01:00
Luís Cobucci
f12d24cce7 Add branch 2.8 to docs 2019-11-21 13:27:32 +01:00
Guilherme Blanco
6c7bb5a273 Merge pull request #7828 from andrews05/andrews05-jti-properties
Fix for TransientMetadata on joined subclass
2019-11-15 00:14:58 -05:00
Claudio Zizza
027344969e Merge pull request #7647 from SenseException/entity-readOnly
Add readOnly attribute to annotation example
2019-11-10 23:09:13 +01:00
Claudio Zizza
9190b73d72 Merge pull request #7613 from SenseException/dql-select-subheadlines
Add headlines for direct references to DQL examples
2019-11-06 21:38:35 +01:00
Grégoire Paris
df7e000ab0 Merge pull request #7669 from iliyaZelenko/patch-1
fix: information about units in DATE_ADD, DATE_SUB
2019-10-31 17:52:42 +01:00
Marco Pivetta
533d09467f Merge pull request #7883 from Pictor13/patch-1
Fix bullet list not rendering correctly on Github
2019-10-31 15:18:17 +01:00
Igor Pellegrini
c9fc364c2c Fix bullet list not rendering correctly on Github
As *rts*, if reading the tutorial on the Github repository, the items are not seen as elements of a bullet list, hence they are not rendered and they are collapsed in a single line of text.

Fix won't affect how it renders on [doctrine-project.org](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html).
2019-10-31 14:30:36 +01:00
andrews05
f2624e953e Skip TransientMetadata properties while inserting
This prevents an exception being thrown if a non-ORM property is declared on a joined subclass.
Fixes #7824.
2019-10-04 09:47:11 +13:00
mikeSimonson
d528f70568 Merge pull request #7840 from peter-gribanov/reflFieldValue
Remove not used variable $reflFieldValue in ObjectHydrator
2019-09-30 10:30:06 +02:00
Peter Gribanov
ccbe5ded06 remove not used variable $reflFieldValue in ObjectHydrator 2019-09-30 11:05:59 +03:00
Guilherme Blanco
21bc805dc9 Implemented and adopted ClassMetadataBuilder in both Annotation and XML drivers. Implemented and adopted PropertyMetadataBuilder in Annotation driver. 2019-08-21 22:42:00 -04:00
Guilherme Blanco
b07393ece8 Cleanup after AssociationBuilders and prep for ClassMetadataBuilder 2019-08-19 00:54:01 -04:00
Guilherme Blanco
1488955ee3 Merge pull request #7799 from doctrine/m2m-association-builder
Many to many association builder
2019-08-18 22:04:10 -04:00
Guilherme Blanco
5afceb9f10 Implemented AssociationBuilders 2019-08-18 22:03:18 -04:00
Marco Pivetta
4bfa22353a Merge pull request #7782 from doctrine/bump-phpstan
Update to PHPStan v0.11
2019-07-28 19:17:35 +02:00
Marco Pivetta
8c125b1065 Merge pull request #7776 from doctrine/chore/remove-hack-this-scope
Remove hack to access class scope inside closures
2019-07-28 15:03:06 +02:00
Gabriel Caruso
0187cf53a2 Remove hack to access class scope inside closures
This is possible since 5.4.
2019-07-28 13:27:09 +02:00
Gabriel Caruso
05d54788fd Update to PHPStan v0.11 2019-07-28 13:20:23 +02:00
Luís Cobucci
a896421be2 Merge pull request #7781 from tybulewicz/patch-1
Missing method `getUtc` added
2019-07-26 18:15:14 +02:00
Tomasz Tybulewicz
4993c4ae9b Missing method getUtc added 2019-07-26 10:51:47 +02:00
Luís Cobucci
376c5e1628 Merge pull request #7777 from doctrine/chore/fix-phpcs-errors
Fix Code Style issues in master branch
2019-07-26 10:04:48 +02:00
Guilherme Blanco
8601d9e525 Fixing build 2019-07-23 23:15:57 -04:00
Gabriel Caruso
4e988bb103 Fix Code Style issues in master branch 2019-07-21 21:35:59 +02:00
Guilherme Blanco
d606941284 Introduced ValueGeneratorMetadataBuilder 2019-07-19 00:19:46 -04:00
Guilherme Blanco
fa7802b1c7 Introduced FieldMetadataBuilder 2019-07-10 00:37:58 -04:00
Luís Cobucci
4f8027aa62 Merge pull request #7771 from Arman-Hosseini/patch-1
Remove year from license
2019-07-09 16:59:51 +02:00
Arman
8220bb3ced Update license year 2019-07-09 16:46:31 +02:00
Guilherme Blanco
57b72b1390 Merge pull request #7772 from lcobucci/fix-build
Fix build
2019-07-09 09:53:05 -04:00
Luís Cobucci
dabbfc70a9 Fix static analysis issues 2019-07-09 14:34:20 +02:00
Luís Cobucci
9906068426 Fix coding standard violations 2019-07-09 10:37:31 +02:00
Guilherme Blanco
b115284932 Introduced JoinTableMetadataBuilder 2019-07-04 00:51:09 -04:00
Guilherme Blanco
6971e74b4a Introduced JoinColumnMetadataBuilder. 2019-07-03 00:50:59 -04:00
Guilherme Blanco
99b7d1e9d4 Eliminated the differentiation between class declared versus inheritance declared 2019-07-02 23:09:33 -04:00
Guilherme Blanco
906c1465c2 Removed completeRuntimeMetadata() method from ClassMetadataFactory and moved to the appropriate location 2019-07-02 22:47:41 -04:00
Guilherme Blanco
04762015c6 Decoupled DiscriminatorColumnMetadataBuilder from drivers 2019-06-28 10:26:51 -04:00
Guilherme Blanco
f185a6f30f Added transient metadata builder. Fixed cache bug for missing column name for fields. More typehint 2019-06-27 00:04:59 -04:00
Guilherme Blanco
c35142f0ae Added TableMetadataBuilder 2019-06-25 23:37:06 -04:00
Guilherme Blanco
3cda3f1ae3 Eliminated AbstractClassMetadataFactory, as there is no purpose for abstracting 2019-06-23 23:58:16 -04:00
Guilherme Blanco
9b8b5d9bf6 Fixes for non-cached behavior 2019-06-23 23:41:51 -04:00
Guilherme Blanco
e1bb9e005d Simplified entity listeners. Implemented cache builder 2019-06-23 23:37:57 -04:00
Guilherme Blanco
b9880bb30f Optimized VersionFieldMetadata support. General fixes for phpstan. Moved validation and comppletion of FieldMetadata to corresponding methods. More optimizations around sequencing generation. 2019-06-21 00:56:21 -04:00
Luís Cobucci
becf73050e Remove unnecessary argument 2019-06-18 10:46:37 +02:00
Luís Cobucci
27f431c628 Fix coding standard violations 2019-06-18 10:45:44 +02:00
Guilherme Blanco
5b15a614a7 Expanded featureset of ClassMetadataBuildingContext. Added more typehints. Added parent ClalassMetadata to constructor. Optimized sequencing generation by delegating its creation to ValueGenerator. 2019-06-18 00:28:34 -04:00
Luís Cobucci
e747f7b9c4 Merge pull request #7725 from doctrine/sync-master
Sync bug fixes from v2.6
2019-06-18 02:17:21 +02:00
Darryl Hein
2b0e49d173 change variable name
to make it consistent throughout document
2019-06-18 01:59:09 +02:00
Sergiu Pirlici
b2f27f6310 Update ordered-associations.rst
Fixed some typos
2019-06-18 01:59:09 +02:00
Marc Plotz
3af277ca55 fix typo
`has to allow null values` vs `has to allows null values`
2019-06-18 01:59:08 +02:00
Claudio Zizza
fb50004d58 Fix of links and php version after review 2019-06-18 01:59:08 +02:00
Claudio Zizza
6bf8d61ffc Fix of links and anchors 2019-06-18 01:59:07 +02:00
Guilherme Blanco
057a97d93c Swap properties via entity manager mock 2019-06-18 01:59:07 +02:00
Marco Pivetta
b5c4c7aaec #7527 automated CS checks 2019-06-18 01:59:06 +02:00
Marco Pivetta
9bd6c59285 As an example result:
```
./phpbench.phar run tests/Doctrine/Performance/Query --iterations=50 --revs=50 --report=aggregate
PhpBench 0.15-dev (dcbe193). Running benchmarks.
Using configuration file: /home/ocramius/Documents/doctrine/doctrine2/phpbench.json

\Doctrine\Performance\Query\QueryBoundParameterProcessingBench

    benchExecuteParsedQueryWithInferredParameterTypeI49 P0 	[μ Mo]/r: 643.684 634.664 (μs) 	[μSD μRSD]/r: 17.700μs 2.75%
    benchExecuteParsedQueryWithDeclaredParameterTypeI49 P0 	[μ Mo]/r: 97.673 94.251 (μs) 	[μSD μRSD]/r: 8.259μs 8.46%

2 subjects, 100 iterations, 100 revs, 0 rejects, 0 failures, 0 warnings
(best [mean mode] worst) = 88.460 [370.679 364.458] 127.400 (μs)
⅀T: 37,067.880μs μSD/r 12.980μs μRSD/r: 5.603%
suite: 133f0e30090f815142331ebec6af18241694e7c0, date: 2018-12-19, stime: 10:47:10
+------------------------------------+--------------------------------------------------+--------+--------+------+-----+------------+-----------+-----------+-----------+-----------+----------+--------+-------+
| benchmark                          | subject                                          | groups | params | revs | its | mem_peak   | best      | mean      | mode      | worst     | stdev    | rstdev | diff  |
+------------------------------------+--------------------------------------------------+--------+--------+------+-----+------------+-----------+-----------+-----------+-----------+----------+--------+-------+
| QueryBoundParameterProcessingBench | benchExecuteParsedQueryWithInferredParameterType |        | []     | 50   | 50  | 5,970,568b | 604.680μs | 643.684μs | 634.664μs | 677.640μs | 17.700μs | 2.75%  | 6.59x |
| QueryBoundParameterProcessingBench | benchExecuteParsedQueryWithDeclaredParameterType |        | []     | 50   | 50  | 5,922,424b | 88.460μs  | 97.673μs  | 94.251μs  | 127.400μs | 8.259μs  | 8.46%  | 1.00x |
+------------------------------------+--------------------------------------------------+--------+--------+------+-----+------------+-----------+-----------+-----------+-----------+----------+--------+-------+
```

This indicates that the performance impact for NOT declaring parameter types
explicitly is *MASSIVE*.
2019-06-18 01:59:05 +02:00
Marco Pivetta
a988d5808e Note: this will still lead to the UnitOfWork#getSingleIdentifierValue() still being
called when not specifying the type of a DQL parameter being bound via
`Doctrine\ORM\Query#setParameter()`:

```php
$query->setParameter('foo', $theValue, $theType);
```

A full parameter bind is required in order to gain back performance:

```php
$query->setParameter('foo', $theValue, $theType);
```

This is up for discussion with patch reviewers.
2019-06-18 01:59:05 +02:00
Marco Pivetta
8c451a6a66 As previously reported by @flaushi in https://github.com/doctrine/doctrine2/pull/7471#discussion_r241949045, we discovered
that binding a parameter causes a `ClassMetadataFactory#getClassMetadata()` call, which in turn leads to large performance
regression when using any `object` type as parameter.

Following two snippets lead to an internal `ClassMetadataFactory#getClassMetadata()` call, which in turn leads to an
exception being thrown and garbage collected, plus multiple associated performance implications:

```php
$query->setParameter('foo', new DateTime());
$query->getResult();
```

```php
$query->setParameter('foo', new DateTime(), DateTimeType::NAME);
$query->getResult();
```

This is due to following portion of code:

434820973c/lib/Doctrine/ORM/Query.php (L406-L409)

Notice how `$value = $this->processParameterValue($value);` happens before attempting to infer the type for the parameter value.

That call leads to this segment being reached, which leads to the regression:

434820973c/lib/Doctrine/ORM/AbstractQuery.php (L423-L433)

Assuming the bound parameter type is provided, we can completely skip attempting to introspect the given object:

```php
$query->setParameter('foo', new DateTime(), DateTimeType::NAME);
$query->getResult();
```

Processing the parameter value is not needed in this case, so we can safely skip that logic for all known parameters.
In order to not introduce a BC break or change the `AbstractQuery#processParameterValue()` implementation, we could filter
out all parameters for which the type is given upfront, and later on merge them back in instead.

The test expectation to be set is for `UnitOfWork#getSingleIdentifierValue()` to never be called.
2019-06-18 01:59:05 +02:00
Michael Moravec
96d22a6ca8 Lock dependencies for Code Quality stage 2019-06-18 01:59:04 +02:00
Luís Cobucci
cc57d33e65 Isolate entities used by the new test
To ensure we don't have any unintended side-effect.
2019-06-18 01:59:04 +02:00
Tobias Schultze
55b06ea6e1 Fix applying collation on foreign key columns 2019-06-18 01:59:03 +02:00
Alex Denvir
35a9f20cc4 [XML] Fix default value of many-to-many order-by to ASC 2019-06-18 01:59:03 +02:00
Farhad Safarov
93a18c4b2e fix incorrect phpdoc typehint 2019-06-18 01:59:02 +02:00
James Titcumb
cdd64e7bcb $hydrationMode throughout can be a string as well as int (for custom modes) 2019-06-18 01:59:02 +02:00
Andreas Braun
6f07bbf482 Fix parameter value processing for objects with unloaded metadata 2019-06-18 01:59:01 +02:00
Luís Cobucci
31d9626b61 Use HTTPS endpoint for XML schema location 2019-06-18 01:59:01 +02:00
naitsirch
84170a735d Fixed URLs of doctrine-mapping.xsd in docs
Until now the references to the `doctrine-mapping.xsd` consisted of different URLs.

A grep of docs showed:
* /Users/robo/dev/php/Doctrine/doctrine-mapping.xsd
* http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd
* http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd
* https://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd

Now it is used http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd everywhere.
2019-06-18 01:59:00 +02:00
Michael Moravec
b58a73aed3 Add UPGRADE note for EntityRepository::count() 2019-06-18 01:59:00 +02:00
Jarek Jakubowski
d7a385105e Unnecessary newline removed, small improvements in text 2019-06-18 01:58:59 +02:00
Jarek Jakubowski
de18565fdc Add info about Doctrine not using constructor 2019-06-18 01:58:58 +02:00
Jarek Jakubowski
cecd03d920 Mention that Doctrine does not use Entities public API 2019-06-18 01:58:58 +02:00
Donovan Bourlard
ce9d4c739d Fix default value of one-to-many order-by to ASC, #7141 2019-06-18 01:58:57 +02:00
Nicolas FRANÇOIS
4ce24a4d66 Fix handling entities with post generated IDs as FK
This prevents a throw in UnitOfWork#addToIdentityMap because some fields
are null.
2019-06-18 01:58:57 +02:00
Guilherme Blanco
d964eb6d50 Fix mock creation 2019-06-18 01:58:56 +02:00
Luís Cobucci
4885e1c7fe Remove duplicated tag from PHPUnit config 2019-06-18 01:58:55 +02:00
Luís Cobucci
42f08f6e3e Remove useless nested switch case
This is simpler and doesn't make PHPCS go crazy when trying to indent
things properly.
2019-06-18 01:58:55 +02:00
Marco Pivetta
23a0608c47 Merge pull request #7703 from thomasbisignani/fix/comments-syntax
[Documentation] Fixed comments syntax
2019-05-28 01:42:25 +02:00
Marco Pivetta
2b734405d2 Merge pull request #7715 from sangio90/patch-1
Typo in class description
2019-05-28 00:27:44 +02:00
Marco Pivetta
0a34e4cef6 Merge pull request #7719 from bocharsky-bw/patch-1
Fix a few examples: Start i var from 1 instead of 0
2019-05-27 23:42:10 +02:00
Victor Bocharsky
b8ebde9d07 Start i var from 1 instead of 0
Because (0 % $batchSize) === 0 but we don't want to execute flush() and
clear() on the first iteration.
2019-05-27 19:49:18 +02:00
Jonathan H. Wage
a6a9455bdd Fix tidelift funding link. 2019-05-24 12:33:04 -05:00
Jonathan H. Wage
6a6370b843 Fix tidelift funding link. 2019-05-24 12:27:09 -05:00
Jonathan H. Wage
706de46ef1 Merge pull request #7720 from jwage/github-funding
Add .github/FUNDING.yml file.
2019-05-24 12:23:53 -05:00
Jonathan H. Wage
b4338ad0d8 Add .github/FUNDING.yml file. 2019-05-24 12:22:47 -05:00
Guido Sangiovanni
b762189c97 typo in class description
fixed typo in class description
2019-05-20 16:39:48 +02:00
Thomas Bisignani
398ddb426f [Documentation] Fixed comments syntax 2019-05-08 00:45:01 +02:00
Jonathan H. Wage
8bb91280ed Merge pull request #7695 from Vehsamrak/patch-1
Annotation fix in example block
2019-04-29 10:56:04 -05:00
Petr Karmashev
87a6eef400 Annotation fix in example block 2019-04-29 13:48:11 +03:00
Jonathan H. Wage
bf14cca3f3 Merge pull request #7687 from muglug/patch-2
Remove full stops in docblocks
2019-04-22 13:52:07 -05:00
Matthew Brown
5ef41cc923 Remove another full stop 2019-04-21 00:52:37 -04:00
Илья
01a4292b0d fix: information about units in DATE_ADD, DATE_SUB 2019-04-04 10:04:08 +03:00
Jonathan H. Wage
ebb53acda9 Merge pull request #7609 from SenseException/type-mapping
Add missing types to property mapping documentation
2019-04-02 09:52:45 -05:00
Claudio Zizza
d1bcb1f0a0 Add missing types to property mapping documentation 2019-04-01 21:10:58 +02:00
Marco Pivetta
04036f2244 Merge pull request #7648 from amaabdou/improvement/upgrade_doctrine_cs_6_0
Update doctrine cs to 6.0
2019-03-17 20:23:43 +01:00
Ahmed Abdou
6c0537325c remove un necessary returns 2019-03-17 19:18:14 +01:00
Ahmed Abdou
1ab9d0b194 Update doctrine cs to 6.0 2019-03-17 14:17:06 +01:00
Claudio Zizza
01f26bba53 Add readOnly attribute to annotation example 2019-03-14 20:49:05 +01:00
Marco Pivetta
d8f67108c9 Merge pull request #7632 from yethee/tests-for-gh-7629
Failing tests for #7926 - `scheduledForSynchronization` leaks memory when using `@ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
2019-03-02 19:17:36 +01:00
yethee
2167536792 Prevent memory leak on an empty commit 2019-03-02 15:02:03 +03:00
yethee
34933416d6 Failing tests 2019-03-02 14:51:44 +03:00
Claudio Zizza
93d55d7fbc Add headlines for direct references to DQL examples 2019-02-17 02:57:27 +01:00
Marco Pivetta
e8eaf8386d Merge pull request #7599 from Majkl578/travis-php7.4-3.0
[3.0] CI: Test against PHP 7.4snapshot instead of nightly (8.0)
2019-02-11 15:38:22 +01:00
Marco Pivetta
97e275ff31 Merge pull request #7603 from creocoder/patch-1
`AbstractQuery::getSingleScalarResult()` never conditionally returns `null`: corrected docblock accordingly
2019-02-11 15:36:56 +01:00
Alexander Kochetov
5e3db26738 Fix AbstractQuery::getSingleScalarResult() phpDoc
This method never return `null`.
2019-02-11 13:01:15 +03:00
Michael Moravec
71393f7d5a CI: Test against PHP 7.4snapshot instead of nightly (8.0) 2019-02-09 18:52:21 +01:00
Marco Pivetta
ed61f0e647 Merge pull request #7576 from SenseException/links-and-typos-master
Update information and links of documentation (master)
2019-01-24 11:42:57 +01:00
Claudio Zizza
11cfaf1233 Fix of links, anchors and php version 2019-01-23 21:30:20 +01:00
Marco Pivetta
08d34341c5 Merge pull request #7578 from SenseException/remove-codeigniter
Remove codeigniter Framework example (master)
2019-01-23 07:47:44 +01:00
Claudio Zizza
5ac805fc4d Remove codeigniter example from docs 2019-01-22 23:07:31 +01:00
Marco Pivetta
6615520bf7 Merge pull request #7559 from doctrine/malarzm-patch-1
Change Stackoverflow tag to doctrine-orm
2019-01-05 21:59:19 +01:00
Maciej Malarz
541fb5968d Change Stackoverflow tag to doctrine-orm 2019-01-05 21:28:16 +01:00
Marco Pivetta
22bf778711 Merge pull request #7558 from nico-incubiq/nico-incubiq-3.0-datetimeimmutable-version
Allow all datetime types to be used as version
2019-01-05 15:42:28 +01:00
Nicolas Severin
322516337e Allow all datetime types to be used as version 2019-01-05 12:01:21 +00:00
Marco Pivetta
d00453dc7e Merge pull request #7552 from Majkl578/repo-rename/3.0
[3.0] Migrate repository name doctrine/doctrine2 -> doctrine/orm
2019-01-03 17:28:36 +01:00
Michael Moravec
0cfc82ddae Migrate repository name doctrine/doctrine2 -> doctrine/orm 2019-01-03 09:07:49 +01:00
Luís Cobucci
e2189307f4 Merge pull request #7526 from greg0ire/support_channels
Add support metadata
2018-12-17 14:39:07 +01:00
Grégoire Paris
b5ba7cddd5 Add support metadata
This should result in more links available on Packagist.
2018-12-17 13:15:10 +01:00
Jonathan H. Wage
2269510e8a Merge pull request #7521 from doctrine/update-chat-link
Update chat link from Gitter to Slack.
2018-12-12 14:05:15 -06:00
Jonathan H. Wage
4bc261aa46 Update chat link from Gitter to Slack. 2018-12-12 20:04:01 +00:00
Marco Pivetta
d20dfcfa8d Merge pull request #7509 from chucky2305/bug/issue-7508
ISSUE-7508: changed phpdoc for parameter `$value`
2018-12-07 12:20:58 +01:00
max.schindler
8744d1936f ISSUE-7508: changed phpdoc for parameter $value to match the actual code 2018-12-07 08:24:55 +01:00
Marco Pivetta
a5ed7ed89c Merge pull request #7507 from mayflower/typos
fix typos in security.rst
2018-12-06 16:11:42 +01:00
Michael Moll
2e9f533746 fix typos in security.rst 2018-12-06 16:10:07 +01:00
Marco Pivetta
3e0b70b4dc Merge pull request #7494 from shadowhand/fix/cli-apcu-warning
Do not allow cache clearing with APCu
2018-12-05 13:18:31 +01:00
Woody Gilk
1feac20c72 Do not allow cache clearing with APCu 2018-12-02 15:15:30 -06:00
Marco Pivetta
3cef55ec39 Merge pull request #7497 from Majkl578/eliminate-common
Drop dependency on doctrine/common
2018-12-01 02:12:27 +01:00
Michael Moravec
cd57cafe47 Drop dependency on doctrine/common 2018-12-01 01:55:30 +01:00
Marco Pivetta
fa4d3bf799 Merge pull request #7488 from Majkl578/update-dbal
Update DBAL 3.x version from 2018-04-17 to 2018-11-26
2018-12-01 00:03:05 +01:00
Marco Pivetta
7c9ab76896 Merge pull request #7491 from thierrymarianne/remove-dead-code
Remove dead code
2018-11-27 21:08:50 +01:00
Thierry Marianne
c4d335ed10 Remove dead code 2018-11-27 20:36:03 +01:00
Michael Moravec
5d6b5a706f Update DBAL 3.x version from 2018-04-17 to 2018-11-26 2018-11-26 21:43:02 +01:00
Marco Pivetta
62de42cfa1 Merge pull request #7484 from TomasVotruba/docs
remove unneded docs
2018-11-21 11:22:34 +01:00
Tomas Votruba
f4cd3df403 remove unneded docs 2018-11-21 11:06:19 +01:00
Luís Cobucci
929bcaf704 Merge pull request #7475 from carusogabriel/file-permission
Fix file permission
2018-11-20 09:24:58 +01:00
Luís Cobucci
4594380bf4 Merge pull request #7474 from carusogabriel/if-statment
Remove unecessary need for if statment
2018-11-20 09:07:34 +01:00
Luís Cobucci
d250ee79c5 Merge pull request #7476 from BenMorel/patch-3
Replace APC with APCu
2018-11-16 00:26:33 +01:00
Benjamin Morel
4d7ffa0e4f Replace APC with APCu 2018-11-15 23:57:53 +01:00
Gabriel Caruso
65c13cf15b Fix file permission 2018-11-14 15:57:11 -02:00
Gabriel Caruso
fc62b8f997 Remove unecessary need for if statment 2018-11-14 15:54:16 -02:00
Guilherme Blanco
4d49b7778c Merge pull request #7469 from doctrine/sync-master-with-2.x
Sync master with 2.x
2018-11-12 00:01:57 -05:00
Alexandru Ungureanu
c780f014b9 Fixes small typo 2018-11-11 23:26:39 +01:00
Farhad Safarov
97248866ce JIRA to Github issues 2018-11-11 23:26:31 +01:00
Oguz Dumanoglu
dd8fcfd851 Fix a typo
There was a typo in Working with Associations page.
2018-11-11 23:25:19 +01:00
Thomas Landauer
54beb95f68 Some formatting improvements 2018-11-10 21:14:12 +01:00
Thomas Landauer
d0b47f3aa9 Update association-mapping.rst
Added info about owning and inverse side.
2018-11-10 20:40:57 +01:00
Michael Moravec
8a79638faa CI: Test against PHP 7.3 2018-11-10 20:38:27 +01:00
Marco Pivetta
6dc46e78cc Merge pull request #7413 from Majkl578/cs-5.0
Apply Doctrine CS 5.0
2018-11-04 22:41:39 +01:00
Michael Moravec
0c2ccec915 Apply Doctrine CS 5.0 2018-11-04 22:08:30 +01:00
Marco Pivetta
72971fd438 Merge pull request #7457 from Majkl578/drop-discriminator-autodiscovery
Drop automatic discriminator map discovery
2018-11-04 19:47:53 +01:00
Michael Moravec
cf94ec8136 Drop automatic discriminator map discovery 2018-11-02 22:32:43 +01:00
Marco Pivetta
d81284b506 Merge pull request #7440 from carusogabriel/dedicated-assertions
Use dedicated assertContainsOnlyInstancesOf PHPUnit assertion
2018-10-30 12:44:10 +01:00
Gabriel Caruso
b0825e490b Use dedicated assertContainsOnlyInstancesOf PHPUnit assertion 2018-10-22 12:04:43 -03:00
Marco Pivetta
91346c41e7 Merge pull request #7425 from mbessolov/patch-1
Minor grammar corrections in the documentation.
2018-10-15 15:21:38 +02:00
Marco Pivetta
1760b4f655 Merge pull request #7429 from carusogabriel/simplify-conditions
Simplify conditions
2018-10-15 12:43:29 +02:00
Marco Pivetta
e6a79ef9b2 Merge pull request #7430 from carusogabriel/use-in-array
Use `in_array` instead of `array_search` + comparison
2018-10-15 12:41:04 +02:00
Gabriel Caruso
15e49aff35 Use in_array instead of array_search + condition 2018-10-14 17:23:04 -03:00
Gabriel Caruso
5839553356 Simplify conditions 2018-10-14 17:21:21 -03:00
Michael Bessolov
5a9fe624b6 Minor grammar corrections in the documentation. 2018-10-10 11:50:09 -07:00
Marco Pivetta
b40c2c6b78 Merge pull request #7404 from doctrine/tidelift-readme
Add tidelift badge and links to the doctrine/orm readme.
2018-09-25 11:35:14 +02:00
Marco Pivetta
36aeed46f8 Merge pull request #7405 from Majkl578/2.x-into-master
Cherry-pick stuff from 2.x into master
2018-09-24 09:28:56 +02:00
Tim Lieberman
ce76688865 Fix for BC break #7366 when calling EM::find() with LockMode::OPTIMISTIC outside of a TX 2018-09-23 06:48:02 +02:00
sserbin
2f520244df Query\Expr::andX(): added string as allowed parameter type 2018-09-23 06:37:59 +02:00
Christophe Coevoet
a59ae2e5e3 Fix the computation of commit order for circular dependencies
When finding a circular dependencies, we must ensure that all dependencies
of a node have been visited before adding it to the sorted list.
2018-09-23 05:51:54 +02:00
Christophe Coevoet
2431bc4076 Add a unit test reproducing the commit order regression 2018-09-23 05:50:51 +02:00
Christophe Coevoet
6219f72dc6 Add a test reproducing GH7259 2018-09-23 05:49:47 +02:00
Bob den Otter
6ff677d2ab Fix docblock in inheritance-mapping.rst 2018-09-23 05:47:56 +02:00
philippe-unitiz
730543f17e Fix constructor and add() argument types in Query\Base 2018-09-23 05:47:56 +02:00
Guilliam Xavier
1157a845ec correct load-only DOMDocument constructor in test 2018-09-23 05:47:56 +02:00
Benjamin Morel
f62cccbfd1 Typo fix 2018-09-23 05:47:55 +02:00
Pierre-Louis FORT
a20373449c Handle removed parameters by tree walker in Paginator 2018-09-23 05:47:55 +02:00
Michael Moravec
362ccb4d24 Fix #7286: StringPrimary no longer accepts aggregate functions as argument 2018-09-23 05:46:37 +02:00
Michael Moravec
2df74442a0 Fix compatibility with DBAL 2.8 where OFFSET 0 is no longer generated (doctrine/dbal#3157) 2018-09-23 04:28:04 +02:00
Michael Moravec
b9feae09c0 Use non-deprecated version of Lexer and Inflector 2018-09-23 04:24:29 +02:00
Jonathan H. Wage
5c773554dd Add tidelift badge and links to the doctrine/orm readme. 2018-09-21 01:32:25 +01:00
Marco Pivetta
bfa65207b0 Merge pull request #7388 from AndreyMashukov/issue-7359-added-test-for-filter-disable
#7359 Added test for filter disable, refactored code and test
2018-09-05 12:04:20 +02:00
AMashukov
53b7f9d6f8 Closes #7359 Added test for filter disable, refactored code and test 2018-09-05 12:23:39 +03:00
Michael Moravec
afd79c189f Merge pull request #7381 from Majkl578/homepage
Update homepage
2018-09-01 03:27:57 +02:00
Michael Moravec
8d83dfa05c Update homepage 2018-09-01 01:07:01 +02:00
Jonathan H. Wage
d311888ef9 Merge pull request #7380 from doctrine/doctrine-project-json
Add .doctrine-project.json to root of the project.
2018-08-31 18:02:41 -05:00
Jonathan H. Wage
46a880ac0f Add .doctrine-project.json to root of the project. 2018-08-31 20:05:15 +01:00
Michael Moravec
f4c84897ba Merge pull request #7373 from SenseException/remove-yaml-remnants
Remove remnants of yaml from documentation
2018-08-29 18:09:50 +02:00
Claudio Zizza
890d544161 Remove remnants of yaml from documentation 2018-08-25 23:36:22 +02:00
Marco Pivetta
87ac04d10e Merge pull request #7229 from ThomasLandauer/patch-1
Added `UNIQUE INDEX` to generated SQL schema
2018-08-21 12:46:34 +02:00
Luís Cobucci
7b261676d2 Merge branch 'fix-partial-reference-docblock'
Applying https://github.com/doctrine/doctrine2/pull/7360 in master
2018-08-19 16:29:28 +02:00
Luís Cobucci
da69537408 Document getPartialReference() properly
According to the current implementation that method also returns `null`,
however the interface's documentation was incorrect.
2018-08-19 16:29:03 +02:00
Marco Pivetta
d6ec5a3861 Merge branch 'fix/#7225-correct-type-hint-for-identifier-criteria'
Close #7225
2018-08-12 10:07:28 +02:00
Hannes Giesenow
82972f697a fixed type hint 2018-08-12 10:07:14 +02:00
Hannes Giesenow
0538f93913 Fixed typehint 2018-08-12 10:07:14 +02:00
Marco Pivetta
0977c8926a Merge pull request #7339 from guilliamxavier/patch-1
Fix renamed depended test method
2018-08-08 11:19:45 +02:00
Guilliam Xavier
2500025ee0 Fix renamed depended test method 2018-08-08 10:35:43 +02:00
Marco Pivetta
5e57fcf9ee Merge pull request #7337 from vladyslavstartsev/patch-1
small fix - `as` in lowercase
2018-08-07 20:53:13 +02:00
vladyslavstartsev
7d34b64885 fixed non camelCase method name in Xml 2018-08-07 18:47:52 +03:00
vladyslavstartsev
2245ad2751 small fix - as in lowercase 2018-08-07 18:28:44 +03:00
Marco Pivetta
68635faf83 Merge pull request #7335 from PowerKiKi/docs-fix
Correct method names and broken link in docs
2018-08-06 14:15:20 +02:00
Adrien Crivelli
6f3ca36b08 Correct method names and broken link in docs
The methods name were incorrectly prefixed with a `\_` and the link
syntax was broken and its URL appeared in plain text in rendered HTML.
2018-08-06 20:23:56 +09:00
Marco Pivetta
cb3d4caec2 Merge pull request #7333 from ostrolucky/fix-2935
Fix #2935 [DDC-2236] Add note that Paginator might screw aggreg. queries
2018-08-05 17:11:16 +02:00
Gabriel Ostrolucký
863dabe73f Fix #2935 [DDC-2236] Add note that Paginator might screw aggreg. queries 2018-08-04 23:33:50 +02:00
Marco Pivetta
5ac6a83560 Merge pull request #7331 from doctrine/fix-2351
#2351 [DDC-1702] Fix EBNF of InExpression (StateFieldPath -> Arithmetic)
2018-08-03 01:47:13 +02:00
Gabriel Ostrolucký
7ad0dcbd88 #2351 [DDC-1702] Fix EBNF of InExpression (StateFieldPath -> Arithmetic) 2018-08-03 00:14:19 +02:00
Marco Pivetta
1d649ad952 Merge pull request #7330 from Majkl578/drop-UuidGenerator
Drop UuidGenerator
2018-08-02 18:55:23 +02:00
Michael Moravec
c4c489e7d9 Drop UuidGenerator 2018-08-02 15:22:41 +02:00
Marco Pivetta
f319f10d2e Merge pull request #7327 from greg0ire/fix_inaccurate_comment
Fix inaccurate description of the `ORMException` interface
2018-07-31 08:55:25 +02:00
Grégoire Paris
1b5bd54290 Fix inaccurate comment 2018-07-31 08:36:57 +02:00
Marco Pivetta
847d5bc666 Merge pull request #7313 from gamingumar/patch-1
typo fix in getting started guide
2018-07-17 15:36:47 +02:00
UmaR Aamer
e540c4a8c4 typo fix in getting started guide
changed rasily to easily
2018-07-17 17:54:12 +05:00
Michael Moravec
b361aa438e Merge pull request #7308 from janvernieuwe/patch-1
Update Bug.md
2018-07-13 15:39:32 +02:00
janvernieuwe
396b7f6718 Update Bug.md
typo
2018-07-13 14:33:53 +02:00
Marco Pivetta
39c5dcb79d Merge pull request #7302 from localheinz/fix/attribute
Fix: Attributes vs. annotations
2018-07-09 23:41:02 +02:00
Marco Pivetta
c17339e64e Merge pull request #7301 from localheinz/fix/format
Fix: Consistently format inversedBy and mappedBy attributes
2018-07-09 23:39:52 +02:00
Andreas Möller
4179a9676f Fix: Attributes vs. annotations 2018-07-09 17:01:14 +02:00
Andreas Möller
e16500ae72 Fix: Consistently format inversedBy and mappedBy attributes 2018-07-09 16:59:44 +02:00
Marco Pivetta
f7309d898f Merge pull request #7295 from afoeder/task/fix-2ndlevelcache-apidoc-links
[DOC] Fix links to API doc for 2nd level cache
2018-07-04 15:06:08 +02:00
Adrian Föder
28f78a0e60 [DOC] Fix links to API doc for 2nd level cache 2018-07-04 14:42:05 +02:00
Marco Pivetta
8bcd13f5c7 Merge pull request #7283 from BackEndTea/patch-1
Add a polyfill for ctype
2018-07-03 10:51:10 +02:00
Marco Pivetta
079f398bd2 Merge pull request #7288 from SenseException/patch-2
Fix of variable typo in cache usage example
2018-07-03 10:47:28 +02:00
Marco Pivetta
035d9edf95 Merge pull request #7075 from BreiteSeite/fix/#7068-entitymanager-find-with-pessimistic-lock-does-not-check-for-transaction
Fix for #7068: `EntityManager::find()` with pessimistic lock should check for transaction
2018-07-03 09:43:14 +02:00
Marco Pivetta
984641d20f Merge pull request #7287 from afoeder/patch-1
Streamline documentation code block type hints for readability
2018-07-03 09:38:20 +02:00
Marco Pivetta
f584bae121 Merge pull request #7292 from greg0ire/mapped_superclass
Use a more concrete, less confusing example
2018-07-03 09:36:12 +02:00
Grégoire Paris
9ce1f0d13f Use a more concrete, less confusing example
I picked a toothbrush because you usually do not share it with other
persons, feel free to propose something else.
2018-07-03 09:01:10 +02:00
Michael Kühn
0cbc87a888 Fix for #7068: EntityManager::find() with pessimistic lock should check for transaction 2018-07-03 03:09:37 +02:00
Claudio Zizza
f4ed9534cc Fix of variable typo in cache usage example 2018-07-02 18:38:47 +02:00
Adrian Föder
497bbfcec8 [TASK] Streamline code block type hints for readability
This corrects a mistake with a given type hint in
the PHP code blocks as well as adds further for
consistency and brevity.
2018-07-02 16:43:32 +02:00
Marco Pivetta
2d194dee53 Merge pull request #7285 from mkurzeja/fix-flush-phpdoc
Removed outdated entity passed phpdoc for EntityManager::flush
2018-07-02 08:53:06 +02:00
Michał Kurzeja
76bc652d88 Removed outdated entity passed phpdoc for EntityManager::flush 2018-07-02 08:27:13 +02:00
Gert de Pagter
d98d8bb0c2 Require the ext 2018-07-01 20:34:43 +02:00
Gert de Pagter
55f238f790 Add a polyfill for ctype 2018-07-01 17:54:47 +02:00
Marco Pivetta
2726636e55 Merge pull request #7272 from odahcam/patch-1
Fixed anchor typo
2018-06-24 03:47:02 +02:00
Luiz Machado
305308278a fixed anchor typo 2018-06-23 22:25:33 -03:00
Marco Pivetta
c5191fa3f9 Merge pull request #7255 from SenseException/arbitrary-join-doc
Extend documentation of arbitrary joins
2018-06-11 10:20:37 +02:00
Claudio Zizza
e5b88b3fe5 Extend documentation of arbitrary joins 2018-06-10 22:55:38 +02:00
Michael Moravec
fae518aaef Merge pull request #7237 from jvasseur/patch-1
Removed redundant `Doctrine\ORM\EntityRepository#__construct()` phpdoc
2018-05-23 20:25:31 +02:00
Jérôme Vasseur
5756a7fc73 Fix EntityRepository constructor phpdoc
Remove redundant phpdoc from EntityRepository constructor
2018-05-23 19:36:51 +02:00
Thomas Landauer
3d9a4b8ed8 Added UNIQUE INDEX to generated SQL schema
When I tried the example code, I got this unique index too.

Plus my `ALTER TABLE` statement was a little different from the one in the docs:
> ALTER TABLE cart ADD CONSTRAINT FK_BA388B79395C3F3 FOREIGN KEY (customer_id) REFERENCES customer (id)
Should I change that too?
2018-05-18 23:18:50 +02:00
Marco Pivetta
12b28571f5 Merge pull request #7224 from hkdobrev/patch-1
Remove obsolete backslashes from underscores
2018-05-15 14:37:34 +02:00
Haralan Dobrev
ec573d1b75 Remove obsolete backslashes from underscores
These backslashes were not correctly migrated when updating the website and it prevents search for some important terms like the query hints.
2018-05-15 14:55:47 +03:00
Marco Pivetta
347e33e345 Merge pull request #7218 from garak/patch-1
Fix typo
2018-05-09 12:14:59 +02:00
Massimiliano Arione
6ad04f7d51 Fix typo 2018-05-09 11:02:19 +02:00
Jonathan H. Wage
f6cc1290d2 Merge pull request #7216 from Majkl578/issue-templates
Add issue and PR templates
2018-05-07 21:13:11 -05:00
Michael Moravec
bbd2460e06 Add issue and PR templates 2018-05-07 22:53:58 +02:00
Marco Pivetta
9019297c55 Merge pull request #7208 from someniatko/someniatko-patch-1
Better PHPDoc for AbstractQuery cache methods
2018-04-28 15:04:34 +02:00
someniatko
1ed8bc705f Fix PHPDoc whitespacing in AbstractQuery 2018-04-27 17:49:55 +03:00
someniatko
063c402dd5 Better PHPDoc for AbstractQuery cache methods
Updated useResultCache() and setResultCacheLifetime() docs to clearly state $lifetime is measured in seconds;
Added description to useResultCache()'s params. Renamed $bool => $useCache.
2018-04-27 14:16:18 +03:00
Michael Moravec
46b695d67c Merge pull request #7201 from greg0ire/adapt_to_signature_bc_break
Adapt to new signatures
2018-04-18 00:37:37 +02:00
Grégoire Paris
b881f14b4d Lock DBAL to a specific branch
From now on, a new branch will be created on each BC-break
2018-04-17 23:56:20 +02:00
Grégoire Paris
e2ea883786 Adapt to new signatures
This should fix the build with the latest ORM version
2018-04-17 23:56:20 +02:00
Marco Pivetta
77e3e5c96c Merge pull request #6743 from greg0ire/split_orm_exception
Split orm exception
2018-04-13 16:18:30 +01:00
mikeSimonson
c7718efff8 Merge pull request #7177 from doctrine/feature/docs-cleanup
Cleanup and add sidebar.rst
2018-04-12 22:27:08 +02:00
Jonathan H. Wage
42dc7830d7 Add sidebar.rst for documentation sidebar. 2018-04-12 19:06:39 +01:00
Grégoire Paris
10aac31e8d Avoid extending \Exception directly 2018-04-12 19:38:30 +02:00
Grégoire Paris
16a1877d58 cs 2018-04-12 19:38:30 +02:00
Grégoire Paris
6d282cdc43 Avoid directly extending \Exception 2018-04-12 19:38:30 +02:00
Grégoire Paris
491a382f91 Use named constructor 2018-04-12 19:38:30 +02:00
Grégoire Paris
563833340a Move ORMException inside the Exception namespace 2018-04-12 19:38:30 +02:00
Grégoire Paris
b128753960 Return, don't throw 2018-04-12 19:38:30 +02:00
Grégoire Paris
79f17d02f7 cs 2018-04-12 19:38:30 +02:00
Grégoire Paris
28e7e5392c Move exceptions in an Exception sub-namespace 2018-04-12 19:38:30 +02:00
Grégoire Paris
46d342d0cf Add missing extension 2018-04-12 19:38:30 +02:00
Grégoire Paris
3fd15f0cc7 Instanciate self 2018-04-12 19:38:30 +02:00
Grégoire Paris
8c16a20fd2 Make method static 2018-04-12 19:38:29 +02:00
Grégoire Paris
6ec3ff02b7 Get rid of ORMException instanciation 2018-04-12 19:38:29 +02:00
Grégoire Paris
39634ad91e Remove unused use statement 2018-04-12 19:38:29 +02:00
Grégoire Paris
1e60554556 Add missing use statements 2018-04-12 19:38:29 +02:00
Grégoire Paris
ed62eb8672 Extract MatchingAssociationFieldRequiresObject 2018-04-12 19:38:29 +02:00
Grégoire Paris
0998a46480 cs 2018-04-12 19:38:29 +02:00
Grégoire Paris
50b35fc6aa Ensure all exceptions implement ORMException 2018-04-12 19:38:29 +02:00
Grégoire Paris
9f4a6922a4 Use new phpunit API 2018-04-12 19:38:29 +02:00
Grégoire Paris
9d30fdf9c7 Refactor ORMException into an interface 2018-04-12 19:38:29 +02:00
Grégoire Paris
d6da264404 Extract invalid result cache driver exception 2018-04-12 19:38:29 +02:00
Grégoire Paris
fbca71af39 Extract cache not configured exceptions 2018-04-12 19:38:29 +02:00
Grégoire Paris
25b5aa6570 Extract QueryCacheUsesNonPersistentCache 2018-04-12 19:38:29 +02:00
Grégoire Paris
c030a213f5 Extract MetadataCacheUsesNonPersistentCache 2018-04-12 19:38:28 +02:00
Grégoire Paris
2f0b5a503a Split cache exception class 2018-04-12 19:38:28 +02:00
Grégoire Paris
cf13e0d10f Extract unrecognized field exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
c2c6c623f3 Extract invalid orientation exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
5db00b15d2 Extract CantUseInOperatorOnCompositeKeys exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
d2a679a780 Extract unrecognized identifier fields exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
398e1128f2 Extract missing identifier field exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
4132f408df Extrace mismatched event manager exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
c0453603e1 Extract invalid hydrate mode exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
d9b0ab7b41 Extract entity manager closed exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
119610b81e Extract unknown entity namespace exception 2018-04-12 19:38:28 +02:00
Grégoire Paris
59b5e5ae6c Extract invalid entity repository exception 2018-04-12 19:38:27 +02:00
Grégoire Paris
b7a2434ef7 Extract Proxy classes always regenerating exception 2018-04-12 19:38:27 +02:00
Grégoire Paris
82796e8711 Extract NotSupported exception 2018-04-12 19:38:27 +02:00
Grégoire Paris
145d5139cb Extract missing mapping driver implementation 2018-04-12 19:38:27 +02:00
Grégoire Paris
ea12b6f82f extract findByRequiresParameter 2018-04-12 19:38:27 +02:00
Grégoire Paris
ae166d773b Find better naming for find by call exception 2018-04-12 19:38:27 +02:00
Grégoire Paris
de31b2abc9 Extract invalidFindByInverseAssociation 2018-04-12 19:38:27 +02:00
Grégoire Paris
b1bec0ee6c Use better suited parent exception 2018-04-12 19:38:27 +02:00
Grégoire Paris
9b8f9786d9 Rename method to something more concise 2018-04-12 19:38:27 +02:00
Grégoire Paris
fdfd2de658 Add missing type hint 2018-04-12 19:38:27 +02:00
Grégoire Paris
fcf012075a Split the ORMException class 2018-04-12 19:38:24 +02:00
Jonathan H. Wage
2ac4142e5f Cleanup docs so the index and title is consistent across all projects. 2018-04-11 04:24:51 +01:00
Marco Pivetta
967d34473e Merge pull request #7185 from afoeder/master
[FEATURE] Mention and link identifier generation strategies
2018-04-10 13:19:57 +02:00
Adrian Föder
dd3c5c8dc3 [FEATURE] Mention and link identifier generation strategies 2018-04-10 12:06:57 +02:00
Marco Pivetta
c4c59df1b4 Merge pull request #7173 from doctrine/malarzm-patch-1
Fix Criteria's orderBy example
2018-04-04 11:00:44 +02:00
Maciej Malarz
ac92e9f8d3 Fix Criteria's orderBy example 2018-04-04 10:31:49 +02:00
Marco Pivetta
54833ec31b Merge pull request #7171 from javiereguiluz/patch-8
Fixed a minor reStructuredText syntax issue
2018-04-03 14:14:50 +02:00
Javier Eguiluz
1b6a1ee315 Fixed a minor reStructuredText syntax issue 2018-04-03 13:30:27 +02:00
Marco Pivetta
6fb6b9d32d Merge pull request #7170 from lcobucci/document-bc-break-due-to-return-type-declaration
Document BC-break due to type declaration
2018-04-03 11:22:38 +02:00
Luís Cobucci
1f0660dcfd Document BC-break due to type declaration
Identifier generators and value generation plan are now using type
declaration as much as possible.
2018-04-03 10:33:01 +02:00
Marco Pivetta
1afbf141fc Merge pull request #7163 from delboy1978uk/master
Add constructor types to SqlWalker and TreeWalker
2018-03-29 14:14:39 +02:00
Derek Stephen McLean
d372416350 use inheritdoc 2018-03-29 11:33:05 +02:00
Derek Stephen McLean
f6581657de Update TreeWalker.php 2018-03-28 16:35:58 +02:00
Derek Stephen McLean
935f3606a2 Fix docblock in SqlWalker 2018-03-28 16:28:19 +02:00
Jonathan H. Wage
cf8f71e56e Merge pull request #7158 from guilbaudc2/patch-1
Proposed corrected typo in demo code.
2018-03-25 18:35:31 -05:00
Cathy Guilbaud
b01bb234f1 Proposed corrected typo in demo code.
changed $payed to $paid.
2018-03-25 17:10:49 -04:00
Jonathan H. Wage
0bb3624404 Merge pull request #7156 from Pierstoval/dto
Minor fixes for getting started doc
2018-03-24 14:25:58 -05:00
Alex Rock Ancelet
5f6d758ddc Minor fixes for getting started doc 2018-03-24 14:57:51 +01:00
Marco Pivetta
88f6485dea Merge pull request #7154 from ogizanagi/patch-1
Fix getting started syntax issue causing rendering glitches
2018-03-23 23:10:40 +01:00
Maxime Steinhausser
15a149c9f6 Fix getting started syntax issue causing rendering glitches 2018-03-23 22:24:01 +01:00
Marco Pivetta
d199c92c95 Merge pull request #7150 from erusso87/patch-1
Redundant condition to check if a query is cacheable
2018-03-22 15:58:46 +01:00
Ezequiel Russo
c98f40251a Redundant If term
It's redundant to check the `$this->cacheable` property.
2018-03-22 14:01:49 +01:00
Marco Pivetta
41292e85df Merge pull request #7136 from carusogabriel/doctrine-cs
Some fixes from PHPStan l2
2018-03-20 10:26:40 +01:00
Gabriel Caruso
dfd9d1b9e7 Some fixes from PHPStan l2 2018-03-19 22:28:39 -03:00
Marco Pivetta
3570057358 Merge pull request #7139 from deeky666/fix-typo
Fix typo in upgrade notes
2018-03-19 12:33:10 +01:00
Steve Müller
7eb6e00940 fix typo 2018-03-19 11:27:05 +01:00
Marco Pivetta
f5a0b568f3 Merge pull request #7137 from doctrine/docs/remove-leftover-sentence-in-getting-started
Removing leftover sentence in `getting-started.rst`
2018-03-19 00:16:31 +01:00
Marco Pivetta
64dffe0ede Removing leftover sentence in getting-started.rst
Ref: https://github.com/doctrine/doctrine2/pull/6902/files#r175304353
2018-03-18 23:57:36 +01:00
Marco Pivetta
8836954787 Merge pull request #6902 from Pierstoval/dto-and-vo
Documentation about getters/setters to DTOs and Value Objects
2018-03-18 16:53:07 +01:00
Alex Rock Ancelet
3ce3aa978f More and more fixes \o/ 2018-03-18 13:12:32 +01:00
Alex Rock Ancelet
31e19239d1 Moar fixes, thanks @greg0ire 2018-03-16 23:20:57 +01:00
Alex Rock Ancelet
86dc7f46a1 More english misunderstanding fixes 2018-03-16 23:12:23 +01:00
Alex Rock Ancelet
042cff9f22 Make updates after @greg0ire, @mheki and @ostrolucky's comments 2018-03-16 23:06:21 +01:00
Alex Rock Ancelet
5f7210b441 WIP to document using DTOs and entities as ValueObjects 2018-03-16 19:53:13 +01:00
Marco Pivetta
3ac8930613 Merge pull request #7132 from dbrumann/patch-1
Fixes a typo
2018-03-15 10:42:38 +01:00
Denis Brumann
29c86ff5e9 Fixes a typo 2018-03-15 10:09:25 +01:00
Marco Pivetta
43c252458b Merge pull request #7122 from Majkl578/dev/tests/typing-setup-teardown-tests
Tests: Return types for setUp, tearDown and all test methods
2018-03-09 10:40:11 +01:00
Michael Moravec
a754acb44a Tests: Return types for setUp, tearDown and all test methods 2018-03-08 19:00:58 +01:00
Marco Pivetta
1a14c85c54 Merge pull request #7121 from Majkl578/dev/scrutinizer-update
Update Scrutinizer config to use our CS setup
2018-03-08 17:46:30 +01:00
Michael Moravec
9f572d4a4a Update Scrutinizer config to use our CS setup 2018-03-08 15:49:36 +01:00
Marco Pivetta
1bbdc5b597 Merge pull request #7046 from carusogabriel/cs-fixes
[CS] Fix CS in tests
2018-03-08 10:33:27 +01:00
Gabriel Caruso
1b845c7c84 [CS] Apply Doctrine CS 4.0 in tests 2018-03-08 05:32:59 -03:00
Michael Moravec
f3c72dc2d1 CS: Fix excludes for tests 2018-03-08 03:51:38 +01:00
Marco Pivetta
e5ef92555b Merge pull request #7114 from carusogabriel/remove-tools-phpcs
Remove tools from PHPCs
2018-03-04 17:25:22 +01:00
Gabriel Caruso
2be99346b1 Remove tools from PHPCs 2018-03-04 13:10:53 -03:00
Marco Pivetta
ec508aff81 Merge branch 'fix/#7113-#7095-remove-dead-code-leftovers-in-classmetadata'
Close #7113
2018-03-04 13:24:35 +01:00
Marco Pivetta
9f8af8ee4c #7113 #7095 removed unused imports 2018-03-04 13:24:20 +01:00
Michael Moravec
a0cd82b9bc Remove dead code leftovers after #7095 2018-03-04 13:21:43 +01:00
Marco Pivetta
89e39b8192 Merge pull request #7112 from Majkl578/cs-4.0
Apply Doctrine CS 4.0, version composer.lock
2018-03-04 13:17:28 +01:00
Michael Moravec
554489c7e8 Start versioning composer.lock and use it for CS/SA analysis on CI 2018-03-04 04:06:58 +01:00
Michael Moravec
bb1fe1d6c9 [CS] Apply Doctrine CS 4.0
* Exclude abstract/exception naming sniff
* Exclude EntityManagerInterface from interface naming sniff
* Use inline comments for single `@var` annotations
* Use short type casts
* Remove empty comments
* Apply other fixes
2018-03-04 03:37:55 +01:00
Marco Pivetta
cf548e9b02 Merge pull request #7111 from greg0ire/nitpicks_contrib
Nitpicks on `CONTRIBUTING.md`
2018-03-03 23:30:17 +01:00
Marco Pivetta
70d6150412 Merge pull request #7110 from Majkl578/dev/drop-sandbox
Drop tools/sandbox
2018-03-03 23:29:34 +01:00
Grégoire Paris
09d3226db9 Add verbs
It feels less awkward.
2018-03-03 21:16:39 +01:00
Grégoire Paris
449a6ead69 Add missing article 2018-03-03 21:16:39 +01:00
Michael Moravec
99c6a510e6 Drop tools/sandbox 2018-03-03 21:06:01 +01:00
Marco Pivetta
d00cabafbf Merge pull request #7107 from Majkl578/dev/update-contributing
Update README & CONTRIBUTING for 3.0 changes and workflow
2018-03-03 12:35:15 +01:00
Michael Moravec
61778f95d4 CONTRIBUTING.md: Update with newer instructions & workflow 2018-03-02 21:31:09 +01:00
Michael Moravec
f100bcec5f README.md: Add warning about changes in 3.0 and branch info 2018-03-02 21:31:09 +01:00
Marco Pivetta
f4ef0a1d5f Merge pull request #7048 from malukenho/enhancement/remove-redundant-docs
Remove redundant php-docs
2018-03-02 09:50:43 +01:00
Marco Pivetta
bbc1ed93b1 Merge branch 'fix/#7082-entity-persister-confuses-pdo-data-types'
Close #7082
Close #7062
2018-02-27 09:05:23 +01:00
Marco Pivetta
2343a58ffe #7062 #7082 adapting test case to new ORM master (3.x) suite and mapping changes 2018-02-27 09:03:06 +01:00
Marius Klocke
bd6ae78940 Add a failing test for issue 7062 2018-02-27 08:34:24 +01:00
Marco Pivetta
a0e414ba57 Merge pull request #7088 from Majkl578/dev/drop-pdo-dependency
Drop explicit PDO dependency
2018-02-26 00:19:03 +01:00
Marco Pivetta
d952c1247e Merge pull request #7095 from doctrine/EntityRepository3
[EntityRepository] Cleanup named native features
2018-02-26 00:12:54 +01:00
Benjamin Eberlei
07a5861503 Remove Named Native Query feature 2018-02-25 23:06:44 +01:00
Luís Cobucci
45c3805edf Merge branch 'port/patch-association-indentifier-not-quoted'
Port https://github.com/doctrine/doctrine2/pull/7093, only introducing
the tests since quoting issues have been solved already in `master`.
2018-02-25 20:31:13 +01:00
Jan Langer
aadf295b9a Fix updating entities with quoted identifier association 2018-02-25 20:11:40 +01:00
Luís Cobucci
91acb40433 Merge pull request #7054 from cb8/foreign-id
Fix ID generation of foreign keys

Ports https://github.com/doctrine/doctrine2/pull/6701 using v3.0 structure.
2018-02-25 19:37:49 +01:00
Charles Bell
5fde371852 Avoid flattening of post-insert IDs
When setting deferred ID values, the original data should contain
complete objects (as it would with non-deferred IDs).
2018-02-25 19:30:37 +01:00
Charles Bell
67fe52f36c Fix ID generation of foreign keys 2018-02-25 19:30:35 +01:00
Vašek Henzl
849d0ac3cc Add failing tests for #6531
Tests are based on examples from "Composite and Foreign Keys as Primary Key" tutorial:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html
2018-02-25 19:19:33 +01:00
Marco Pivetta
3e1d124f23 Merge pull request #7092 from lcobucci/declare-some-types
Declare some types
2018-02-25 19:08:20 +01:00
Luís Cobucci
408704b845 Declare types in Sequence\Generator 2018-02-25 19:03:13 +01:00
Luís Cobucci
f6fde34297 Use object type declaration in ValueGenerationPlan 2018-02-25 19:03:13 +01:00
Luís Cobucci
b0cade71ba Use object type declaration in ValueGenerationExecutor 2018-02-25 19:03:13 +01:00
Marco Pivetta
46ea9d1b52 Merge pull request #7091 from carusogabriel/cs-fixes-lib
Fix from CS for lib and tools
2018-02-25 17:37:50 +01:00
Gabriel Caruso
9e57633204 Fix from CS for lib and tools 2018-02-25 09:35:34 -03:00
Marco Pivetta
faab3225bd Merge pull request #7090 from greg0ire/patch-2
Use proper grammar
2018-02-24 20:54:50 +01:00
Grégoire Paris
86f3b6afe7 Use proper grammar
Not sure what idiot wrote it that way.
2018-02-24 20:24:26 +01:00
Marco Pivetta
3d3f8b7a8b Merge pull request #7089 from greg0ire/patch-2
Proofread upgrade file
2018-02-24 15:45:14 +01:00
Grégoire Paris
98b9a7dd34 Proofread upgrade file 2018-02-24 15:41:46 +01:00
Marco Pivetta
6e4daa3997 Merge pull request #7085 from doctrine/tighten-owning-side-resolution
[RFC] Tighten owning side resolution
2018-02-23 16:13:49 +01:00
Guilherme Blanco
9179aeb343 Break unit tests as per @lcobucci request 2018-02-23 10:04:53 -05:00
Guilherme Blanco
0b04aa9000 Added unit tests on both Annotations and XML drivers. Fixed bug with table names not accepting dashes (included unit tests). 2018-02-23 00:19:04 -05:00
Michael Moravec
e6fa8622d7 Drop explicit PDO dependency 2018-02-22 23:34:43 +01:00
Guilherme Blanco
df794b648f Tighten owning side resolution. Fixed bug with potential double owning side in OneToOne when JoinColumns were mapped on both association sides. In that case, the ownership was determined based on association flow (in A -> B, A:b was owning, while in B -> A, B:a was owning). 2018-02-22 00:25:26 -05:00
Luís Cobucci
695edb9fdc Add missing function import 2018-02-19 22:07:22 +01:00
Luís Cobucci
d376afb53c Add @group to delete query test 2018-02-19 22:05:26 +01:00
Marco Pivetta
0822f8a456 Merge branch 'fix/#6988-#6304-ensure-inheritance-middle-layer-is-hydrated'
Close #6988
Close #6304
2018-02-19 12:10:20 +01:00
Luís Cobucci
bbf0c0355d Extract private method to retrieve discriminator values 2018-02-19 12:10:02 +01:00
Luís Cobucci
cbfd52e2fe Remove loose comparison on discriminator values
According to mapping drivers the discriminator values can always be
converted to strings so it's safe to assume that we can actually do a
strict comparison during hydration.
2018-02-19 12:08:32 +01:00
Toni Cornelissen
6cc43d884b Use partial discriminator map on multi-inheritance
Hydrator was ignoring data from subclasses when using multiple
inheritance levels. With this patch it will now use the discriminator
values from all subclasses of the class being hydrated.
2018-02-19 12:07:37 +01:00
Marco Pivetta
e7e4247395 #6988 #6304 adapted test case to ORM test suite changes in 3.x
- `em` protected property
 - annotation namespace change
 - `QueryBuilder` instantiation
2018-02-19 12:02:28 +01:00
Kevin Bond
3035470d06 Inheritance middle-layer doesn't get hydrated with HYDRATE_OBJECT 2018-02-19 11:51:39 +01:00
Marco Pivetta
92445d095e Merge branch 'fix/#7077-#7053-allow-alias-less-DQL-delete-statement'
Close #7077
Close #7053
2018-02-19 11:32:55 +01:00
Marco Pivetta
4e2a2975c2 #7077 #7053 in ORM 3.x, everything is quoted by default, so the test needs adaptation 2018-02-19 11:32:02 +01:00
Luís Cobucci
e479e0daf4 Use early-returns to improve readability of the Parser 2018-02-19 11:23:24 +01:00
Luís Cobucci
f41c6083c3 Fix BC-break on delete queries with nasty workaround
The `v2.5.x` series of the ORM allowed to have DELETE DQLs without using
an alias, even though it didn't follow the grammar rules of the parser.
We fixed that issue on `v2.6.0` however that was a BC-breaking change
and lots of people were relying on this faulty behaviour.

This workaround fixes the BC-break, without even trying to be elegant.
In `v2.7.0.` we should raise a deprecation notice to notify people that
we'll drop that "feature" in `v3.0`.
2018-02-19 11:22:04 +01:00
Carnage
ab03f16e03 Adds sql generation test 2018-02-19 11:20:58 +01:00
Luís Cobucci
f351f5ab3b Merge pull request #7065 from Majkl578/dev/dbal-compat
Fix compatibility with DBAL develop
2018-02-18 02:29:54 +01:00
Michael Moravec
6aabdec97b Fix compatibility with DBAL develop
* ResultStatement signature BC break
* PDO::FETCH_* -> FetchMode::*
* PDO::PARAM_* -> ParameterType::*
* AbstractPlatform::DATE_INTERVAL_UNIT_* -> DateIntervalUnit::*
* AbstractPlatform::TRIM_* -> TrimMode::*
2018-02-18 02:16:16 +01:00
Luís Cobucci
df0cc3452b Fix incorrect value in L2C+lock test
Which was causing the optimistic lock to fail in MySQL since it was
trying to update the data with exact same value.
2018-02-17 19:50:11 +01:00
Luís Cobucci
65ebadec49 Merge pull request #7069 from wtorsi/master
Test for Second level cache with Version, DDC #7067
2018-02-17 18:54:28 +01:00
‘Andrey Lukin’
38032c166e Add version fields into L2C data 2018-02-17 18:38:05 +01:00
‘Andrey Lukin’
35d8c87fad Add test for L2C using optimistic locks
As explained in #7067, fields with `@ORM\Version` annotation were not
being added to L2C cached data.
2018-02-17 18:38:04 +01:00
Luís Cobucci
ec265bf3a3 Merge pull request #7076 from lcobucci/fix-build
Make mocks compatible with latest version of interface
2018-02-17 18:37:03 +01:00
Luís Cobucci
9f7df926cf Make mocks compatible with latest version of interface
Since we changed the signature in DBAL v3.x-dev we must apply the
changes here too.
2018-02-17 18:17:28 +01:00
Marco Pivetta
09266d5361 Merge pull request #7064 from carusogabriel/https
Use HTTPS instead of HTTP
2018-02-14 11:11:58 +01:00
Gabriel Caruso
46e27d0cde Use HTTPS instead of HTTP 2018-02-14 07:57:14 -02:00
Jefersson Nathan
a31ce59097 Remove redundant php-docs
Signed-off-by: Jefersson Nathan <admin@phpse.net>
2018-02-12 14:19:19 +01:00
Marco Pivetta
0a00a3f044 Merge pull request #7057 from Majkl578/fix/composer-cs-constraint
Fix CS constraint in composer.json
2018-02-11 02:25:21 +01:00
Michael Moravec
e64820f21e Fix CS constraint in composer.json 2018-02-11 02:21:39 +01:00
Marco Pivetta
0b7d878cd3 Merge pull request #7056 from Majkl578/cs-3.0-lib
[CS] Apply Doctrine CS 3.0
2018-02-11 00:03:20 +01:00
Michael Moravec
0151657ea1 [CS] Apply Doctrine CS 3.0
* Import all functions and constants in `use`
* Remove useless comments
* Use new with parenthesis
* Unqualified class references in annotations
2018-02-09 22:38:17 +01:00
Luís Cobucci
06ffd851c7 Merge pull request #7055 from lcobucci/fix-date-issues-once-and-for-all
Fix date issues once and for all
2018-02-09 17:47:06 +01:00
Luís Cobucci
97534219db Add missing tests for day calculation
For the DATE_SUB() and DATE_ADD() functions.
2018-02-09 17:17:10 +01:00
Luís Cobucci
df94e79ece Fix date calculation in tests (again)
Now using PHP to calculate the expected date manipulation, keeping a day
as delta since PHP resets the hour when performing operations with
days/weeks/months/years.

February is a wonderful month, isn't it?
2018-02-09 17:17:10 +01:00
Marco Pivetta
4509c770da Merge pull request #7049 from coudenysj/remove-yaml-documentation
Remove the YAML metadata driver from the documentation
2018-02-08 13:27:30 +01:00
Jachim Coudenys
bc0c0986c5 Remove the YAML metadata driver from the documentation
The code was removed in #5932
2018-02-08 13:14:16 +01:00
mikeSimonson
e0ee4b1ad7 Merge pull request #6943 from mikeSimonson/xsd-mapping
replacing all the sequence by choice
2018-02-06 22:47:15 +01:00
Marco Pivetta
bcc9da2f4a Merge pull request #7040 from coudenysj/query-cache-documentation
Fix the result cache documentation
2018-02-06 12:25:10 +01:00
Jachim Coudenys
e351954ec6 Fix the result cache documentation (it caches raw data, not hydrated entities) 2018-02-06 11:49:50 +01:00
Marco Pivetta
1a435b2de4 Merge pull request #7045 from Cladis/patch-2
Change bug reporting link from dead Jira to GitHub
2018-02-06 11:42:46 +01:00
Cladis
8b66f88661 Change bug reporting link from dead Jira to GitHub
As per the desc, I am not sure I have chosen the best location though (not sure if it is general enough).
2018-02-06 12:39:59 +02:00
Marco Pivetta
1c7770794b Merge pull request #7044 from Cladis/patch-1
Fixing link to DDC-213 from Jira to Github
2018-02-06 11:38:53 +01:00
Cladis
692a6d941f Fixing link to DDC-213 from Jira to Github
As per the desc; I previously reported this in #7043
2018-02-06 12:36:30 +02:00
mike
af0b0dbdc3 Removing all the occurence of any
If someone wants to override the doctrine mapping that person should
write his own mapping file
2018-02-06 00:03:24 +01:00
mike
193563e3ed replacing all the sequence by choice
The order is never important in the declaration
2018-02-05 22:52:03 +01:00
Marco Pivetta
eef6308b19 Merge pull request #7034 from carusogabriel/patch-1
PHPUnit 7
2018-02-02 13:23:10 +01:00
Gabriel Caruso
1751560970 Fix test for PHPUnit 7 2018-02-02 08:13:48 -02:00
Gabriel Caruso
bc44d8bceb [WIP] PHPUnit 7 2018-02-02 07:39:03 -02:00
Marco Pivetta
9d27f22ee6 Merge pull request #7033 from malukenho/enhancement/remove-useless-condition
Remove comparison with `null` as we do it with `instanceof`
2018-02-02 10:18:42 +01:00
Jefersson Nathan
e2d077c62d Remove comparison with null as we do it with instanceof
There is no need to check against a white-list type and a black-list at
the same time.

Signed-off-by: Jefersson Nathan <admin@phpse.net>
2018-02-02 09:50:08 +01:00
Luís Cobucci
7d37fe0060 Merge pull request #7032 from Majkl578/fix/7031-tests-february
QueryDqlFunctionTest: Increase delta for testDateAdd() to work in February
2018-02-02 07:41:24 +01:00
Michael Moravec
8cc949808a QueryDqlFunctionTest: Increase delta for testDateAdd() to work in February 2018-02-02 03:08:24 +01:00
Marco Pivetta
7d93958cba Merge pull request #7028 from malukenho/hotfix/remove-unused-return
Remove useless `return` statement
2018-02-01 14:17:16 +01:00
Marco Pivetta
43eebb270f Merge pull request #7029 from malukenho/hotfix/remove-redundant-check
Remove redundant check for DateTime instance
2018-02-01 13:23:56 +01:00
Jefersson Nathan
52769aa118 Remove redundant check for DateTime instance
Signed-off-by: Jefersson Nathan <admin@phpse.net>
2018-02-01 12:59:16 +01:00
Jefersson Nathan
762fdd166e Remove unused return statement
Signed-off-by: Jefersson Nathan <admin@phpse.net>
2018-02-01 12:21:38 +01:00
Michael Moravec
2de6c807c8 Merge pull request #7020 from Majkl578/fix/phpstan-0.9.2
SchemaValidator: Fixed bug in inverse JoinTable column name
2018-01-30 22:48:22 +01:00
Michael Moravec
c181836233 Merge pull request #7023 from malukenho/remove-return-from-void-methods
Avoid `returning` on void methods
2018-01-30 22:40:57 +01:00
Jefersson Nathan
a346c3f84e Avoid return on void methods
Signed-off-by: Jefersson Nathan <admin@phpse.net>
2018-01-30 20:48:57 +01:00
Michael Moravec
93558d4786 SchemaValidator: Use more meaningful variable name 2018-01-30 02:14:32 +01:00
Rolando Caldas
579f084202 Exception Call to undefined method Doctrine\Common\Cache\MemcachedCache::setMemcache()
When memcached extension is loaded Doctrine\ORM\Tools\Setup.php  calls
to setMemcache method. The MemcachedCache class has the setMemcached
method instead. Changed this call in Setup to setMemcached and $memcache
to $memcached to keep the name like the extension
2018-01-30 01:56:37 +01:00
Nicolas FRANÇOIS
79282317d1 Add test case for many-to-many collection deletion, when owning side has a composite PK 2018-01-30 01:50:45 +01:00
Michael Moravec
da7288e541 SchemaValidator: Fixed bug in inverse JoinTable column name 2018-01-29 17:10:01 +01:00
Marco Pivetta
c14dbc2409 Merge branch 'fix/#7013-green-phpstan-analysis'
Close #7013
2018-01-29 08:42:07 +01:00
Marco Pivetta
e559f823ea Documented that Doctrine\ORM\Mapping\Exporter\VariableExporter::INDENTATION has been removed 2018-01-29 08:40:42 +01:00
Michael Moravec
63d5a07f06 Fix issues found by PHPStan 2018-01-29 08:40:11 +01:00
Marco Pivetta
d72936caab Merge pull request #7014 from Majkl578/dev/fix-benchmark
Fix benchmark CI stage
2018-01-29 08:33:16 +01:00
Marco Pivetta
e98654342f Merge pull request #7018 from kimhemsoe/remove_named_query_support
Removed support for named queries
2018-01-29 07:55:05 +01:00
Kim Hemsø Rasmussen
217d28f767 Removed named queries from xsd 2018-01-29 00:48:34 +01:00
Kim Hemsø Rasmussen
e6557cbee3 Removed support for named queries 2018-01-29 00:42:19 +01:00
Michael Moravec
b44ba04d1f Fix benchmark CI stage 2018-01-27 08:01:13 +01:00
Michael Moravec
ee4e267595 Merge pull request #6903 from Majkl578/dev/ci-disable-tests
Travis: Allow failures for tests on non-SQLite RDBMS, disable SLC tests
2018-01-27 07:41:21 +01:00
Michael Moravec
13f173a126 Require symfony/console 3.2+ with $COLUMNS env support 2018-01-27 07:13:49 +01:00
Michael Moravec
7fc285dd32 Travis: Allow test failures on non-SQLite RDBMS, disable SLC tests 2018-01-27 07:13:48 +01:00
Michael Moravec
346d2380bd Fix CS issues from recent changes 2018-01-27 06:55:33 +01:00
Michael Moravec
d791f7f6ca Fix DDC3192Test after #6974 2018-01-27 05:31:55 +01:00
Michael Moravec
d455a023f8 Fix parse error in ORMException caused by #7008 2018-01-27 05:21:02 +01:00
Marco Pivetta
2ccf239628 Merge pull request #6967 from egircys/internal_phpdoc_fix
replace 'internal note:' with {@internal .. }}
2018-01-26 14:55:36 +01:00
Egidijus Gircys
d559c933e1 Merge branch 'master' into internal_phpdoc_fix 2018-01-26 12:51:23 +01:00
Marco Pivetta
45ea294233 Merge pull request #6981 from muglug/fix-signatures
Fix exporter signatures
2018-01-26 11:55:07 +01:00
Marco Pivetta
d4e02aadc0 Merge pull request #6983 from muglug/property-fixes
Fix property docblocks where type is easy to infer
2018-01-26 11:53:11 +01:00
Marco Pivetta
4476ec467d Merge pull request #7004 from coudenysj/patch-1
Fix the link to the 'Change Tracking Policies' documentation
2018-01-26 11:28:19 +01:00
Guilherme Blanco
ddb3cd17bd Merge pull request #7008 from greg0ire/remove_unused_exceptions
Remove unused exceptions
2018-01-24 14:30:49 -05:00
Grégoire Paris
3e8aa71554 Remove unused exceptions 2018-01-24 20:03:32 +01:00
Luís Cobucci
82c91a2606 Merge pull request #7005 from SenseException/patch-1
Update license's copyright
2018-01-24 10:20:48 +01:00
Claudio Zizza
2cd3f1f909 Update license's copyright 2018-01-23 21:56:11 +01:00
Jachim Coudenys
7968dfae76 Fix the link to the 'Change Tracking Policies' documentation 2018-01-23 14:15:39 +01:00
Marco Pivetta
577a590987 Merge pull request #6993 from caciobanu/master
Updated docblocks
2018-01-18 13:04:47 +01:00
Catalin Ciobanu
9e122e7a89 Updated docblock 2018-01-18 12:05:17 +02:00
Matthew Brown
9855f56bd5 Fix property types 2018-01-12 23:42:13 -05:00
Michael Moravec
ea95507da4 Merge pull request #6935 from Majkl578/dev/entity-namespace-removal
Remove support for entity namespaces (Foo:Bar)
2018-01-12 21:48:37 +01:00
Michael Moravec
98f51794d8 Merge pull request #6974 from carusogabriel/strict
Use $strict param in functions that have it
2018-01-12 21:38:48 +01:00
Michael Moravec
e3360573ab Merge pull request #6962 from carusogabriel/null-coalesce-operator
Use Null Coalesce Operator
2018-01-12 21:36:10 +01:00
Gabriel Caruso
8a75d3d6f6 Use $strict param in functions that have it 2018-01-12 06:10:09 -02:00
Gabriel Caruso
142fe6a01d Use Null Coalesce Operator 2018-01-12 05:58:20 -02:00
Matt Brown
872571f4a5 Add asserts for contravariance 2018-01-11 18:36:05 -05:00
Michael Moravec
63cb8018dd Remove support for entity namespace aliases 2018-01-11 23:16:38 +01:00
Marco Pivetta
a0071b17de Merge pull request #6956 from Majkl578/readme/update-versions
README: Update versions
2018-01-11 22:26:15 +01:00
Matt Brown
f2fab1ac36 Fix exporter signatures 2018-01-11 16:21:24 -05:00
Marco Pivetta
e3936d0411 Merge pull request #6964 from doctrine/cs
[CS] Ported lib/ to updated CS 2.0
2018-01-11 10:19:58 +01:00
Egidijus Gircys
37d4927118 replace 'internal note:' with the suggested phpdoc {@internal .. }} 2018-01-07 12:58:31 +01:00
Michael Moravec
dc7fca409c Stop allowing failures for CS errors coming from lib/ 2018-01-05 01:54:12 +01:00
Michael Moravec
cb590fc17e [CS] Port Mapping\* 2018-01-05 00:29:12 +01:00
Michael Moravec
ccdf44d9f1 [CS] Port Mapping\Factory\* 2018-01-05 00:29:10 +01:00
Michael Moravec
1fcb7b5005 [CS] Port Mapping\Exporter\* 2018-01-05 00:29:08 +01:00
Michael Moravec
f567970a85 [CS] Port Mapping\Driver\* 2018-01-05 00:29:05 +01:00
Michael Moravec
386fc0b010 [CS] Port Query\* 2018-01-05 00:29:02 +01:00
Michael Moravec
51300d63f4 [CS] Port Query\AST\* 2018-01-05 00:29:00 +01:00
Michael Moravec
0d1684873b [CS] Port Query\AST\Functions\* 2018-01-05 00:28:58 +01:00
Michael Moravec
066d135b21 [CS] Port Query\Filter\* 2018-01-05 00:28:56 +01:00
Michael Moravec
0cef113a5b [CS] Port Query\Expr\* 2018-01-05 00:28:41 +01:00
Michael Moravec
45a8a0c412 [CS] Port Query\Exec\* 2018-01-05 00:28:38 +01:00
Michael Moravec
afa2768f28 [CS] Port Tools\* 2018-01-05 00:28:37 +01:00
Michael Moravec
34ca9fc86e [CS] Port Tools\Pagination\* 2018-01-05 00:28:35 +01:00
Michael Moravec
75e25c1e7c [CS] Port Tools\Event\* 2018-01-05 00:28:33 +01:00
Michael Moravec
4952f82e0b [CS] Port Tools\Console\* 2018-01-05 00:28:31 +01:00
Michael Moravec
2bc1778f80 [CS] Port Utility\* 2018-01-05 00:28:29 +01:00
Michael Moravec
bacb18bd42 [CS] Port Sequencing\* 2018-01-05 00:28:26 +01:00
Michael Moravec
0c7745a0a6 [CS] Port Repository\* 2018-01-05 00:28:24 +01:00
Michael Moravec
f94e5eff85 [CS] Port Reflection\* 2018-01-05 00:28:22 +01:00
Michael Moravec
aef6f17d9c [CS] Port Proxy\* 2018-01-05 00:28:20 +01:00
Michael Moravec
654f3e30ce [CS] Port Persisters\* 2018-01-05 00:28:18 +01:00
Michael Moravec
5221e999c2 [CS] Port Internal\* 2018-01-05 00:28:16 +01:00
Michael Moravec
66cf6d9f58 [CS] Port Cache\* 2018-01-05 00:28:14 +01:00
Michael Moravec
4108b05401 [CS] Port Cache\Region\* 2018-01-05 00:28:12 +01:00
Michael Moravec
b227daa982 [CS] Port Cache\Persister\* 2018-01-05 00:28:10 +01:00
Michael Moravec
f138011843 [CS] Port Cache\Logging\* 2018-01-05 00:28:08 +01:00
Michael Moravec
0ec1e1ceb2 [CS] Port Event\* 2018-01-05 00:28:06 +01:00
Michael Moravec
bd8dd42336 [CS] Port Decorator\EntityManagerDecorator 2018-01-05 00:28:05 +01:00
Michael Moravec
0c0b3e9682 [CS] Port Configuration\MetadataConfiguration 2018-01-05 00:28:02 +01:00
Michael Moravec
557d7600b2 Port Annotation\* 2018-01-05 00:26:44 +01:00
Michael Moravec
37db536a66 [CS] Port UnitOfWork 2018-01-05 00:26:42 +01:00
Michael Moravec
05e7049c44 [CS] Port UnexpectedResultException 2018-01-05 00:26:41 +01:00
Michael Moravec
b9c3d3dfcf [CS] Port TransactionRequiredException 2018-01-05 00:26:39 +01:00
Michael Moravec
b497a079d3 [CS] Port QueryBuilder 2018-01-05 00:26:36 +01:00
Michael Moravec
0b4276f738 [CS] Port Query 2018-01-05 00:26:34 +01:00
Michael Moravec
c236f3e846 [CS] Port PessimisticLockException 2018-01-05 00:26:32 +01:00
Michael Moravec
3dab1396c5 [CS] Port PersistentObject 2018-01-05 00:26:29 +01:00
Michael Moravec
17c06f5d04 [CS] Port PersistentCollection 2018-01-05 00:26:27 +01:00
Michael Moravec
3f3996cc47 [CS] Port ORMInvalidArgumentException 2018-01-05 00:26:23 +01:00
Michael Moravec
a1037fee9b [CS] Port ORMException 2018-01-05 00:26:17 +01:00
Michael Moravec
b7776e1ca3 [CS] Port OptimisticLockException 2018-01-05 00:26:14 +01:00
Michael Moravec
34b8b4f086 [CS] Port NoResultException 2018-01-05 00:26:12 +01:00
Michael Moravec
3c9172bad8 [CS] Port NonUniqueResultException 2018-01-05 00:26:09 +01:00
Michael Moravec
d6332695fd [CS] Port NativeQuery 2018-01-05 00:26:07 +01:00
Michael Moravec
8796f460a7 [CS] Port AbstractQuery 2018-01-05 00:26:01 +01:00
Michael Moravec
36c4e7df43 [CS] Port LazyCriteriaCollection 2018-01-05 00:25:59 +01:00
Michael Moravec
67d275f451 [CS] Port Events 2018-01-05 00:25:58 +01:00
Michael Moravec
088d3b0217 [CS] Port EntityRepository 2018-01-05 00:25:55 +01:00
Michael Moravec
96ed87b2a5 [CS] Port EntityNotFoundException 2018-01-05 00:25:54 +01:00
Michael Moravec
a8235bcfc3 [CS] Port Cache 2018-01-05 00:25:51 +01:00
Michael Moravec
d2a70d030e [CS] Port Configuration 2018-01-05 00:25:48 +01:00
Michael Moravec
0bd7ffc266 [CS] Port EntityManagerAware 2018-01-05 00:25:45 +01:00
Michael Moravec
5411108c83 [CS] Port EntityManager 2018-01-05 00:25:32 +01:00
Michael Moravec
7681b89137 [CS] Port EntityManagerInterface 2018-01-05 00:25:07 +01:00
Michael Moravec
e42a888dad Use newer CS 2018-01-05 00:19:43 +01:00
Marco Pivetta
8be1e3f1d3 Merge pull request #6952 from Slamdunk/cs_explicit_indirect_variable
[CS] Add curly braces to indirect variables
2018-01-04 08:14:48 +01:00
Marco Pivetta
9452f024c7 Merge pull request #6963 from SenseException/schema-event-doc
[Documentation] Add documentation for ToolEvents
2018-01-04 07:54:07 +01:00
Claudio Zizza
f5b434af25 Add root namespace to full classname 2018-01-03 23:59:30 +01:00
Claudio Zizza
81b1f277a0 Update loadClassMetadata example and add namespaces 2018-01-03 23:59:19 +01:00
Claudio Zizza
dcdc8a5a45 Add ToolEvents of SchemaTool 2018-01-03 23:59:02 +01:00
Marco Pivetta
53ace82169 Merge pull request #6960 from hultberg/patch-1
fix UPGRADE instruction to correct version
2018-01-03 10:36:11 +01:00
Edvin Hultberg
83a312187b fix UPGRADE instruction to correct version
For v2.6.0, $className argument was removed from `AbstractEntityInheritancePersister#getSelectJoinColumnSQL()` via #6216. However, the documented minor BC break for upgrading to v2.6 was put under Upgrade to 2.5. This commit fixes this by moving it to v2.6
2018-01-03 10:33:54 +01:00
Michael Moravec
e48c033839 README: Update versions 2018-01-02 21:56:40 +01:00
Marco Pivetta
f53b0399f3 Merge pull request #6955 from doctrine/develop
Merge develop into master
2018-01-02 21:11:23 +01:00
Michael Moravec
a064d9fd17 Merge pull request #6909 from carusogabriel/combine_consecutive_unsets
Combine consecutive unsets
2018-01-02 19:55:14 +01:00
Michael Moravec
21d521e187 Merge pull request #6951 from Slamdunk/cs_no_whitespace_in_blank_line
[CS] Remove trailing whitespace at the end of blank lines
2018-01-02 19:50:55 +01:00
Michael Moravec
a67b533d00 Merge pull request #6950 from Slamdunk/cs_phpdoc_trim
[CS] PHPDoc: remove empty lines at start/end
2018-01-02 19:45:49 +01:00
Michael Moravec
ff6541503e Merge pull request #6949 from Slamdunk/cs_single_blank_line_at_eof
[CS] Exactly one line-feed at end-of-file
2018-01-02 19:43:17 +01:00
Michael Moravec
5f6cdb150f Merge pull request #6953 from Slamdunk/cs_method_argument_space
[CS] Method argument space: no space before comma, at least one space after
2018-01-02 19:41:36 +01:00
Michael Moravec
2537c7f52b SetupTest: Fix namespace name for dynamic directory name (introduced in cebe3005) 2018-01-02 18:12:16 +01:00
Filippo Tessarotto
a0d8a05a7b Apply method_argument_space 2018-01-02 10:28:19 +01:00
Filippo Tessarotto
d1fedbf05d Apply explicit_indirect_variable 2018-01-02 10:09:21 +01:00
Filippo Tessarotto
3102d97173 Apply no_whitespace_in_blank_line 2018-01-02 10:00:37 +01:00
Filippo Tessarotto
77edd5310c Apply phpdoc_trim 2018-01-02 09:55:15 +01:00
Filippo Tessarotto
24114afb14 Apply single_blank_line_at_eof 2018-01-02 09:52:06 +01:00
Marco Pivetta
d1cf9a7617 Merge pull request #6947 from Slamdunk/visibility
[CS] Require explicit visibility
2018-01-02 09:46:23 +01:00
Marco Pivetta
9800ca7657 Merge pull request #6948 from Slamdunk/cs_is_null
[CS] is_null($var) -> null === $var
2018-01-02 09:45:26 +01:00
Filippo Tessarotto
cfba9efd4e Apply visibility 2018-01-02 09:40:23 +01:00
Filippo Tessarotto
85ab80a039 Apply is_null 2018-01-02 09:39:46 +01:00
Marco Pivetta
d1e561eb13 Merge pull request #6936 from Majkl578/dev/entity-same-namespace-removal
Remove support for same-namespace class resolution
2018-01-02 09:38:25 +01:00
Michael Moravec
cd590f2f33 Remove support for same-namespace class resolution 2018-01-01 21:13:55 +01:00
Michael Moravec
d4ed772b07 Require PHP 7.2, drop <7.2 in Composer & on Travis 2018-01-01 20:30:36 +01:00
Marco Pivetta
324dfa4e23 Merge pull request #6945 from carusogabriel/clean-up
Whitespaces clean-up in docs
2018-01-01 19:08:24 +01:00
Marco Pivetta
391e101cba Merge pull request #6929 from carusogabriel/null-coalesce-operator
[CS] Clean elses
2018-01-01 19:06:49 +01:00
Marco Pivetta
63b8c4db3b Merge pull request #6931 from Slamdunk/cs_phpdoc_opening_closing
[CS] Standardize docblock asterisks
2018-01-01 19:06:17 +01:00
Marco Pivetta
fee52ddcfa Merge pull request #6925 from Slamdunk/co_braces
[CS] Phpdoc (and related) blocks indentation
2018-01-01 13:48:20 +01:00
Filippo Tessarotto
9ad525a34f Apply braces 2018-01-01 11:15:38 +01:00
Filippo Tessarotto
d0f998ce45 Apply phpdoc_opening_closing 2018-01-01 11:00:01 +01:00
Gabriel Caruso
1ffde77a87 Remove extra lines 2017-12-31 17:42:54 -02:00
Gabriel Caruso
f4c84883ec Trailing whitespaces 2017-12-31 17:42:14 -02:00
Gabriel Caruso
46836d38ac [CS] Clean elses 2017-12-31 17:39:11 -02:00
Gabriel Caruso
57ee603fec Combine consecutive unsets 2017-12-31 17:35:00 -02:00
Luís Cobucci
cebe3005a6 Use a valid directory to not break the test 2017-12-31 18:37:19 +01:00
Luís Cobucci
111898a269 Mark test as incomplete
So that we can check if they're still relevant and, if so, adapt them.
2017-12-31 18:37:18 +01:00
Luís Cobucci
a0342c87dd Add assertion to ManyToManyBasicAssociationTest#testUpdateDeleteSizeSubselectQueries 2017-12-31 18:37:18 +01:00
Luís Cobucci
7da3c2d678 Revert sync with master changes
Removing changes introduced in #6767, which we should sort out before
of merging `develop` into `master`.
2017-12-31 18:37:18 +01:00
Michael Moravec
81ace85f29 Replace spl_object_hash() with more efficient spl_object_id() 2017-12-31 18:37:18 +01:00
Filippo Tessarotto
b01a9a3ea1 Apply line_ending 2017-12-31 18:37:18 +01:00
Filippo Tessarotto
945e98dcaf Apply ternary_operator_spaces 2017-12-31 18:37:17 +01:00
Filippo Tessarotto
52a5ac4bb8 Apply no_null_property_initialization 2017-12-31 18:37:17 +01:00
Filippo Tessarotto
75c1cfc0f4 Apply no_unused_imports 2017-12-31 18:37:17 +01:00
Filippo Tessarotto
489eb411a3 Apply align_multiline_comment 2017-12-31 18:37:17 +01:00
Filippo Tessarotto
2bc55103fd Apply lowercase_keywords 2017-12-31 18:37:16 +01:00
Filippo Tessarotto
368e10a4df Apply lowercase_constants 2017-12-31 18:37:16 +01:00
Filippo Tessarotto
5d496f145e Apply blank_line_after_namespace 2017-12-31 18:37:16 +01:00
Filippo Tessarotto
b7f2147015 Apply no_alias_functions 2017-12-31 18:37:16 +01:00
Filippo Tessarotto
2cb9df201f Apply no_empty_statement 2017-12-31 18:37:16 +01:00
Filippo Tessarotto
fc8942786d Apply blank_line_after_opening_tag 2017-12-31 18:37:15 +01:00
Filippo Tessarotto
a580ef9911 Apply escape_implicit_backslashes,heredoc_to_nowdoc 2017-12-31 18:37:15 +01:00
Filippo Tessarotto
d9e419f4a2 Apply bare heredoc_to_nowdoc 2017-12-31 18:37:15 +01:00
Filippo Tessarotto
7b574c25d2 Apply elseif 2017-12-31 18:37:15 +01:00
Gabriel Caruso
8d3736ddae Combine consecutives issets 2017-12-31 18:37:15 +01:00
Guilherme Blanco
d05e8e8285 Ephemeral UnitOfWork 2017-12-31 18:37:14 +01:00
Michael Moravec
e376962ab5 Also run Scrutinizer under PHP 7.2 2017-12-31 18:37:14 +01:00
Gabriel Caruso
5798192e61 Use Null Coalesce Operator 2017-12-31 18:37:14 +01:00
Michael Moravec
e4ce75a8dc Remove code generation tools & commands 2017-12-31 18:37:14 +01:00
Claudio Zizza
c4eb2b016d Remove copy method from EntityManager 2017-12-31 18:37:14 +01:00
Gabriel Caruso
ede29990e3 Refactoring more tests 2017-12-31 18:37:13 +01:00
Marco Pivetta
01bb774273 #6867 as per discussion with @guilhermeblanco, dropping ObjectManagerAware support, as the ClassMetadata API radically changed 2017-12-31 18:37:13 +01:00
Marco Pivetta
29beae2daa Ensuring that the ObjectManagerAware and EntityManagerAware objects are initialized even if they are un-initialized proxies 2017-12-31 18:37:13 +01:00
Marco Pivetta
28941f37cd Ensuring that ObjectManagerAware and EntityManagerAware are equally handled 2017-12-31 18:37:13 +01:00
Marco Pivetta
d1ceb55c68 Hardening DDC2231 test - both ObjectManagerAware and EntityManagerAware should work 2017-12-31 18:37:12 +01:00
Marco Pivetta
575639cb49 Forgot to set the EntityManager instance also when dealing with EntityManagerAware objects (was only using ObjectManagerAware) 2017-12-31 18:37:12 +01:00
Marco Pivetta
55863d6101 Verifying that the entity in DDC2231Test is actually EntityManagerAware 2017-12-31 18:37:12 +01:00
Guilherme Blanco
aa9f11e11d Fixes after rebase 2017-12-31 18:37:12 +01:00
Marco Pivetta
cd1d527b57 Static analysis fixes as reported by scrutinizer-ci 2017-12-31 18:37:12 +01:00
Marco Pivetta
a25fdb56fc Making sure the ProxyFactory#createProxy() is always given a ClassMetadata instance
Ref: https://github.com/doctrine/doctrine2/pull/6719#discussion_r140646281
2017-12-31 18:37:11 +01:00
Marco Pivetta
36e6526cd9 Documented removal of getProxyDir, getProxyNamespace and getAutoGenerateProxyClasses methods 2017-12-31 18:37:11 +01:00
Marco Pivetta
059d7ad08d BC Break: Removing getProxyDir, getProxyNamespace and getAutoGenerateProxyClasses methods
Also cleans up the `Doctrine\ORM\Configuration` class, which used weird array access to save some memory (no longer true since PHP 5.4+)
2017-12-31 18:37:11 +01:00
Marco Pivetta
9b91c2dc6c Adding missing trailing comma as per @jaapio's review
Ref: https://github.com/doctrine/doctrine2/pull/6719#discussion_r140642661
2017-12-31 18:37:11 +01:00
Marco Pivetta
c0be5ab403 Removing NonLoadingPersister specifics that are not to be used in benchmarks 2017-12-31 18:37:11 +01:00
Marco Pivetta
83e7e07464 Ignoring phpbench.phar and the associated public key 2017-12-31 18:37:10 +01:00
Marco Pivetta
0ce63c0160 Cleaning up performance tests before attempting a fix of the ProxyInitializationTimeBench 2017-12-31 18:37:10 +01:00
Marco Pivetta
45b7cd0d01 Clarifying that also reflection now triggers lazy-loading 2017-12-31 18:37:10 +01:00
Marco Pivetta
67d6da5226 Documenting introduced BC breaks in the proxy refactoring 2017-12-31 18:37:10 +01:00
Marco Pivetta
4e06a15dc8 Marking the StaticProxyFactory as internal, fixing type hint documentation 2017-12-31 18:37:10 +01:00
Marco Pivetta
3411950c6c Removing erroneous documentation about final methods, c__lone and __wakeup details that no longer hold true 2017-12-31 18:37:09 +01:00
Marco Pivetta
8315460083 Cleaning documentation around proxy behavior 2017-12-31 18:37:09 +01:00
Marco Pivetta
e7ace6f8a0 Replacing generated proxy example with a stub resembling current state 2017-12-31 18:37:09 +01:00
Marco Pivetta
52cc90b205 Removing reference to previous proxy model 2017-12-31 18:37:09 +01:00
Marco Pivetta
f00c433746 Removing documented quirks about proxy lazy-loading semantics combined with reflection: now always holding true 2017-12-31 18:37:09 +01:00
Marco Pivetta
62d664b6b1 Removing FAQ entry for item that no longer holds true about public property lazy-loading semantics 2017-12-31 18:37:09 +01:00
Marco Pivetta
7f292d3ee0 s/lazy-load/lazy-loading 2017-12-31 18:37:08 +01:00
Marco Pivetta
4c0f6fc513 Updating documentation about proxy serialization 2017-12-31 18:37:08 +01:00
Marco Pivetta
5eea2a6944 func_get_args() now works within proxies: YAY! 2017-12-31 18:37:08 +01:00
Marco Pivetta
a30a0b9cb6 Removing redundant/conflicting proxy documentation, correcting proxy performance/autoloading docs 2017-12-31 18:37:08 +01:00
Marco Pivetta
566b777834 Adapting proxy configuration documentation to the new changes in the proxy handling in ORM v3 2017-12-31 18:37:08 +01:00
Marco Pivetta
cae465b850 Using AUTOGENERATE_EVAL during test suite runs 2017-12-31 18:37:07 +01:00
Marco Pivetta
e3592b5ca7 Verifying friend object "Comparable" behavior when using proxies that access each other's private state 2017-12-31 18:37:07 +01:00
Marco Pivetta
08661094fc Verifying that ghost object friend objects are not initialized when not reading lazy state 2017-12-31 18:37:07 +01:00
Marco Pivetta
4e7d5c84e3 Removing fixed TODO about identifier handling 2017-12-31 18:37:07 +01:00
Marco Pivetta
aeff25f7df Verifying that identifier order being swapped does not cause identifier references to be lost 2017-12-31 18:37:07 +01:00
Marco Pivetta
4810a308eb Verifying that identifiers are preserved when using EntityManager#getReference() 2017-12-31 18:37:07 +01:00
Marco Pivetta
092457fb2e Extracting NormalizeIdentifierTest assets to a Model namespace 2017-12-31 18:37:06 +01:00
Marco Pivetta
8af59cd3de Marking utility classes as internal 2017-12-31 18:37:06 +01:00
Marco Pivetta
ded2e05be7 Inlining variables that are only used once 2017-12-31 18:37:06 +01:00
Marco Pivetta
07844788ca Minimal NormalizeIdentifier documentation 2017-12-31 18:37:06 +01:00
Marco Pivetta
fe0df7f47d Using NormalizeIdentifier inside the UnitOfWork instead of relying on an additional internal method 2017-12-31 18:37:06 +01:00
Marco Pivetta
076c184d7e Implemented NormalizeIdentifier as per specification
Also made sure the `EntityManager` does not ruin identifiers when `getReference` is being called
2017-12-31 18:37:05 +01:00
Marco Pivetta
449111cecb Completing specification for nested reference identifier normalization 2017-12-31 18:37:05 +01:00
Marco Pivetta
567879d932 Simplified spec for an identifier normalizer 2017-12-31 18:37:05 +01:00
Marco Pivetta
58f11eaec7 Simplifying generateProxyClasses code 2017-12-31 18:37:05 +01:00
Marco Pivetta
d79c6672c5 Removing duplicate TODO that was moved to a private method documentation 2017-12-31 18:37:05 +01:00
Marco Pivetta
f2645f0157 Removing solved TODOs and improved documentation around why we work with an un-managed proxy anyway 2017-12-31 18:37:05 +01:00
Marco Pivetta
a28197a321 Removing solved TODO in the Parser changes 2017-12-31 18:37:04 +01:00
Marco Pivetta
1e40657862 Removing unused import 2017-12-31 18:37:04 +01:00
Marco Pivetta
d1b2f62b3c Dead code removal 2017-12-31 18:37:04 +01:00
Marco Pivetta
4e42bfc45f Removed ClassUtils shim: class has been internalized 2017-12-31 18:37:04 +01:00
Marco Pivetta
245e1dc2ea Verifying all of the StaticClassNameConverterTest API 2017-12-31 18:37:04 +01:00
Marco Pivetta
82062b6df3 Basic tests for the StaticClassNameConverterTest 2017-12-31 18:37:03 +01:00
Marco Pivetta
3e3b7cf1f2 Replacing ClassUtils shim usage with a new StaticClassNameConverter with less features 2017-12-31 18:37:03 +01:00
Marco Pivetta
1e7a0574fe Removing all unused proxy-related components 2017-12-31 18:37:03 +01:00
Marco Pivetta
df583fa2cb Improving performance of the StaticProxyFactory by caching all internal components that do not require repeated fetch/build steps 2017-12-31 18:37:03 +01:00
Marco Pivetta
c3ffd0cd22 Using the LazyLoadingGhostFactory to trigger proxy generation 2017-12-31 18:37:03 +01:00
Marco Pivetta
a81754342a Rewriting StaticProxyFactory so its constructor just receives a GhostObjectFactory as constructor argument, and that's it 2017-12-31 18:37:02 +01:00
Marco Pivetta
5ae48b3799 SetupTest was using invalid proxy paths 2017-12-31 18:37:02 +01:00
Marco Pivetta
05463f43ca setProxyNamespace() should also update the wrapped ProxyManager\Configuration instance 2017-12-31 18:37:02 +01:00
Marco Pivetta
d1cb92e497 Adding Doctrine\ORM\Configuration API as per test specification 2017-12-31 18:37:02 +01:00
Marco Pivetta
820ffc5f2a Verifying that the Doctrine\ORM\Configuration builds separate and independent ghost object factory instances 2017-12-31 18:37:02 +01:00
Marco Pivetta
e510015692 Changing auto-generation flag should also change the ProxyManager\Configuration referenced generator strategy 2017-12-31 18:37:02 +01:00
Marco Pivetta
68cf7661ad Extracting temporary dir generation to a private method 2017-12-31 18:37:01 +01:00
Marco Pivetta
1ccc4ffcfc Setting a proxy path should update the ProxyManager\Configuration instance too 2017-12-31 18:37:01 +01:00
Marco Pivetta
e645a67ab6 Beginning work on the Configuration overhaul - we want to manage a ProxyManager\Configuration instance in the ORM config 2017-12-31 18:37:01 +01:00
Marco Pivetta
f26a43c58a Replace ClassUtils with a temporary, local, deprecated shim that knows about ProxyManager proxy class names 2017-12-31 18:37:01 +01:00
Marco Pivetta
ee47d37f7c The NotifyPropertyChanged API should only be used once we decided to overwrite the entity data, in which case the UnitOfWork is indeed tracking entity state 2017-12-31 18:37:01 +01:00
Marco Pivetta
d18144bef1 Stop registering cloned proxies (real instance being managed) as managed 2017-12-31 18:37:00 +01:00
Marco Pivetta
f0d7fa5344 Correcting ReferenceProxyTest: proxy identifiers are no longer unset while cloning, but they are not considered managed 2017-12-31 18:37:00 +01:00
Marco Pivetta
7e6e89a8f7 Explicit BC break: we no longer call __wakeup on proxies 2017-12-31 18:37:00 +01:00
Marco Pivetta
dd4684d72e Adding stub implementation of logic that converts a flat identifier into a deep identifier 2017-12-31 18:37:00 +01:00
Marco Pivetta
b33abd3c14 SecondLevelCacheManyToOneTest should not cause more queries for fetching associated identifiers (which are already available) 2017-12-31 18:37:00 +01:00
Marco Pivetta
3d204ac1f4 Adding ocramius/proxy-manager dependency 2017-12-31 18:36:59 +01:00
Marco Pivetta
247e7ec711 Correcting metadata factory tests - fetching a class by name does indeed fetch the class even if prefixed 2017-12-31 18:36:59 +01:00
Marco Pivetta
1cc5b8ee91 Correcting DDC-1238 to remove non-sensical semantics that cleared proxy data after detach operations 2017-12-31 18:36:59 +01:00
Marco Pivetta
012a4e2668 Documenting DDC-1022 tests to be removed, as proxy behavior changed around __clone and __wakeup semantics 2017-12-31 18:36:59 +01:00
Marco Pivetta
1308662ce5 Removing DDC-1238 related code. Issue seems to be invalid, as cloning a proxy should NOT modify its state, but just make it non-managed 2017-12-31 18:36:59 +01:00
Marco Pivetta
fa5292bf7c Hardening DDC3223Test with additional pre- and post-conditions 2017-12-31 18:36:59 +01:00
Marco Pivetta
310bed63b1 Correcting DDC2231Test, since proxies no longer initialize if no state is mutated 2017-12-31 18:36:58 +01:00
Marco Pivetta
d36438b21e The DefaultQueryCache still contained instanceof Proxy checks - replaced with GhostObjectInterface checks 2017-12-31 18:36:58 +01:00
Marco Pivetta
fea7f52362 Correcting DDC1690Test: even if a proxy is not yet loaded, it must have notify property listeners to function correctly 2017-12-31 18:36:58 +01:00
Marco Pivetta
5ef465820c Corrected DDC1228Test, which was quite broken and relying on the old Proxy API 2017-12-31 18:36:58 +01:00
Marco Pivetta
51da2adf74 Correcting DDC1193Test, which was using the old Proxy API 2017-12-31 18:36:58 +01:00
Marco Pivetta
79f51bf51c Cleaning up ReferenceProxyTest, which no longer reflects current invariants 2017-12-31 18:36:57 +01:00
Marco Pivetta
2045869985 Fixed reference to non-existing method 2017-12-31 18:36:57 +01:00
Marco Pivetta
7141cb7f9e Transient fields should be skipped by proxy initialization semantics 2017-12-31 18:36:57 +01:00
Marco Pivetta
662a8e43f0 Cascade operations do not apply to non-initialized proxies: no associations are set there 2017-12-31 18:36:57 +01:00
Marco Pivetta
c6bb99113e Hardening ProxiesLikeEntitiesTest by adding some precondition checks 2017-12-31 18:36:57 +01:00
Marco Pivetta
1f0d55686f ORM proxy names may be looked up in the class metadata factory - the parser should not manually do class_exists checks unless strictly required 2017-12-31 18:36:56 +01:00
Marco Pivetta
7fab08bc70 Correcting reference to non-existing method 2017-12-31 18:36:56 +01:00
Marco Pivetta
642574e17d Fixing faulty test that was expecting a different entity to bbe hydrated during proxy initialization 2017-12-31 18:36:56 +01:00
Marco Pivetta
bd53f1980c Correcting ProxyFactoryTests, which were opinionated around past proxy definition 2017-12-31 18:36:56 +01:00
Marco Pivetta
291457f1aa Proxy identifier must be set when the proxy is instantiated 2017-12-31 18:36:56 +01:00
Marco Pivetta
a68c3b4239 Prevent setting any values in un-initialized proxies 2017-12-31 18:36:56 +01:00
Marco Pivetta
b5b3e30d6a Ensuring that the BasicFunctionalTest relies on the GhostObjectInterface API 2017-12-31 18:36:55 +01:00
Marco Pivetta
b45c4fb441 Stubbing out a retry on the s/Proxy/GhostObjectInterface replacement patch 2017-12-31 18:36:55 +01:00
Michael Moravec
3c9737b3d6 Use Generators instead of AppendIterator for properties iteration 2017-12-31 18:36:55 +01:00
Marco Pivetta
5f90854ea6 #6653 removing unused variable as per @alcaeus' review
Ref: https://github.com/doctrine/doctrine2/pull/6653#discussion_r135503849
2017-12-31 18:36:55 +01:00
Marco Pivetta
3127a2a787 #6653 adding note to UPGRADE.md about the removal of Doctrine\ORM\Version 2017-12-31 18:36:55 +01:00
Marco Pivetta
8e46fcda86 Removing build references to the Version class, which is finally gone-gone-gone 2017-12-31 18:36:54 +01:00
Marco Pivetta
6d4168f189 Dropping references to the ORM Version class - using PackageVersions instead 2017-12-31 18:36:54 +01:00
Marco Pivetta
6dabfa3984 Adding ocramius/package-versions as a replacement for the internal ORM Version class 2017-12-31 18:36:54 +01:00
Marco Pivetta
f5a95710a4 #1577 clarifying session user fetching as per @Majkl578's review
Ref: https://github.com/doctrine/doctrine2/pull/1577#discussion_r124162444
2017-12-31 18:36:54 +01:00
Marco Pivetta
5de0435d99 #1577 rephrasing reference to detach that is now clear() instead
Ref: https://github.com/doctrine/doctrine2/pull/1577#discussion_r124126422 - @lcobucci's review
2017-12-31 18:36:54 +01:00
Marco Pivetta
a6526abadb #1577 removed detach reference from the docs, as per @lcobucci's review
Ref: https://github.com/doctrine/doctrine2/pull/1577#discussion_r124127083
2017-12-31 18:36:53 +01:00
Marco Pivetta
ee6b58be97 #1577 removing references to detach and merge cascade operations in newer metadata driver implementations 2017-12-31 18:36:53 +01:00
Marco Pivetta
37c0225f7d #1577 re-enabling clear($entityName) tests 2017-12-31 18:36:53 +01:00
Marco Pivetta
4c95f57996 Corrected XmlExporter order of exported cascades 2017-12-31 18:36:53 +01:00
Marco Pivetta
e5cb4e5455 #1577 removing merge and detach related mapping operations in cascades in tests 2017-12-31 18:36:53 +01:00
Marco Pivetta
165f395aef #1577 merge and detach are no longer accepted cascade mappings 2017-12-31 18:36:52 +01:00
Marco Pivetta
911ec07f33 #1577 removing all references to merge operations in the docs 2017-12-31 18:36:52 +01:00
Marco Pivetta
784653ad6f #1577 removing documentation about merge/detach methods, replaced by clear() documentation only 2017-12-31 18:36:52 +01:00
Marco Pivetta
434bb7f68d #1577 removing references to merge/detach cascade operations 2017-12-31 18:36:52 +01:00
Marco Pivetta
a13dd43f96 #1577 removing cascade-merge and cascade-detach from mapping examples 2017-12-31 18:36:52 +01:00
Marco Pivetta
30463c452b #1577 removing cascade-merge and cascade-detach from mapping examples 2017-12-31 18:36:52 +01:00
Marco Pivetta
e4c9057a47 #1577 removing <cascade-merge/> and <cascade-detach/> from the XSD 2017-12-31 18:36:51 +01:00
Marco Pivetta
8f993266fe #1577 removing detach() calls references from the batch processing docs, adding links to existing batch processing utilities 2017-12-31 18:36:51 +01:00
Marco Pivetta
c14bc2f34f #1577 re-wording 'working with sessions' section, so that users are discouraged from storing entities in sessions 2017-12-31 18:36:51 +01:00
Marco Pivetta
065fdfdde6 #1577 re-adding merge() and detach(), since a release of doctrine/common is required to completely remove those methods from the ObjectManager interface first 2017-12-31 18:36:51 +01:00
Marco Pivetta
854d069627 #1577 adding upgrade notes about the BC break caused by merge() and detach() semantics removal 2017-12-31 18:36:51 +01:00
Marco Pivetta
909993ae3e #1577 remove newly introduced tests around merge/detach semantics, which were dropped 2017-12-31 18:36:50 +01:00
Marco Pivetta
3f29ff74ee Removing clear($entityName) functionality (for now) 2017-12-31 18:36:50 +01:00
Marco Pivetta
5dfe5069ab Disabling test around the EntityManager#clear($entityName) functionality (improvement needed) 2017-12-31 18:36:50 +01:00
Marco Pivetta
df397e1d68 Removing EntityManager#detach() 2017-12-31 18:36:50 +01:00
Marco Pivetta
98d93ad74a Removing tests around the detach functionality 2017-12-31 18:36:50 +01:00
Marco Pivetta
f26bfadaef Note about sections to be removed 2017-12-31 18:36:49 +01:00
Marco Pivetta
b80a676e9a Adding @TODO about batch-processing and detach() operations: clear() may deal with it directly. 2017-12-31 18:36:49 +01:00
Marco Pivetta
16a085ff67 Adding TODO: serialization of entities is something the ORM shouldn't deal with (directly) anymore 2017-12-31 18:36:49 +01:00
Marco Pivetta
f6b2e3fe63 Removing merge operations from the UnitOfWork 2017-12-31 18:36:49 +01:00
Marco Pivetta
cf4d4cc260 Removing EntityManager#merge() logic 2017-12-31 18:36:49 +01:00
Marco Pivetta
06a94e2688 Removing tests around EntityManager#merge() and similar operations 2017-12-31 18:36:49 +01:00
Marco Pivetta
edf3335e60 Removing functional test cases covering EntityManager#merge() semantics 2017-12-31 18:36:48 +01:00
Guilherme Blanco
4fb9f48f1a TableMetadata should only exist if ClassMetadata has a table. Started some concept work around Mapping Binders. 2017-12-31 18:36:48 +01:00
Marco Pivetta
8b40c6ef90 Removing is_array check on a type that can only have two possible states - using instanceof instead 2017-12-31 18:36:48 +01:00
Marco Pivetta
0f36bc769f Removing useless array_key_exists() calls, using ?? operator instead 2017-12-31 18:36:48 +01:00
Marco Pivetta
3a93402720 Removing useless post-array-population association hydration via array_walk() 2017-12-31 18:36:48 +01:00
Marco Pivetta
49d553808d Removing useless variable 2017-12-31 18:36:47 +01:00
Marco Pivetta
fa563476a3 Removing useless checking for never-used parameter, inlining merge operation 2017-12-31 18:36:47 +01:00
Marco Pivetta
c6116d4e55 Replacing possible O(n^2) operation from PersistentCollection diffing operations 2017-12-31 18:36:47 +01:00
Marco Pivetta
f2cf2ea203 Reverting dangerous index lookup operations - resultset may contain gaps in the results 2017-12-31 18:36:47 +01:00
Guilherme Blanco
8be6b5862e Moved class metadata binding to proper methods 2017-12-31 18:36:47 +01:00
Marco Pivetta
368a2f26e8 Avoiding fallback function lookup when counting expression parts in an OrderBy query builder expression 2017-12-31 18:36:46 +01:00
Marco Pivetta
eaebc57f7c Avoiding fallback function lookup when counting expression parts in a generic query builder expression 2017-12-31 18:36:46 +01:00
Marco Pivetta
4e2d1809ba Removed typical if (count(expr)) { issue from sql walker 2017-12-31 18:36:46 +01:00
Marco Pivetta
12d36551c5 Removed counting of sql parts when deciding whether to wrap parts in parentheses 2017-12-31 18:36:46 +01:00
Marco Pivetta
2417eb8e3f Removing counting in an iteration when generating aliases 2017-12-31 18:36:46 +01:00
Marco Pivetta
1cda08cf11 Removing some useless counting operations from the DQL parser 2017-12-31 18:36:45 +01:00
Marco Pivetta
1aeda7ffdb Removing counting from getSelectConditionStatementSQL 2017-12-31 18:36:45 +01:00
Marco Pivetta
5df39072db Removed counting of local variable when generating filter clauses for many to many collections 2017-12-31 18:36:45 +01:00
Marco Pivetta
b37e8d6fb7 Removing useless counting on whether subclasses are present 2017-12-31 18:36:45 +01:00
Marco Pivetta
48e8fdeb25 Fixing check of inheritance on a mapped superclass 2017-12-31 18:36:45 +01:00
Marco Pivetta
0b70c8f239 Removing useless counting of the discriminator map during metadata loading 2017-12-31 18:36:45 +01:00
Marco Pivetta
0768fa502f Quicker check on whether an identifier is composite - removes counting 2017-12-31 18:36:44 +01:00
Marco Pivetta
0e8fad8fc3 Removing counting of generated id fields when checking for composite identifiers 2017-12-31 18:36:44 +01:00
Marco Pivetta
7fca3b151b Avoiding counting scalars at every iteration - simply checking once is enough 2017-12-31 18:36:44 +01:00
Marco Pivetta
9a6eb7ddb8 Avoid repeated counting of root aliases in ArrayHydrator 2017-12-31 18:36:44 +01:00
Marco Pivetta
61845d390c Avoiding counting aliases when determining whether a query is simple or not 2017-12-31 18:36:44 +01:00
Marco Pivetta
d248dc4084 Removing counting operations in the UnitOfWork 2017-12-31 18:36:43 +01:00
Marco Pivetta
499147f256 Removing counting operations around parameter handling in QueryBuilder 2017-12-31 18:36:43 +01:00
Marco Pivetta
cb530da8db Removing useless counting around query resultset handling 2017-12-31 18:36:43 +01:00
Marco Pivetta
aa155c8cd4 Removing useless count() operations from the PersistentCollection internals 2017-12-31 18:36:43 +01:00
Marco Pivetta
b3a27357d6 Removing count() operations from the AbstractQuery implementations 2017-12-31 18:36:42 +01:00
Guilherme Blanco
58f212d85d Fixed broken tests 2017-12-31 18:36:42 +01:00
Guilherme Blanco
ca83c24d90 Removed PHP and Static PHP mapping drivers, since they will be irrelevant with the new ClassMetadataFactory 2017-12-31 18:36:42 +01:00
Guilherme Blanco
5b5caf7c58 More simplifications in ClassMetadataFactory. 2017-12-31 18:36:42 +01:00
Guilherme Blanco
c39a8d2fac ClassMetadataFactory changed to bring ClassMetadata instantiation closer to MappingDriver loading call. Changed how ReflectionService is called for ClassMetadata initialization, simplifying calls. 2017-12-31 18:36:42 +01:00
Usman Zafar
e9c7a49961 updated the heading for upgrade doc 2017-12-31 18:36:41 +01:00
Usman Zafar
e409a16d2c Reverted the public method on construct to protected. Updated the tests. 2017-12-31 18:36:41 +01:00
Guilherme Blanco
37eaea65d9 Some quick typehints 2017-12-31 18:36:41 +01:00
Usman Zafar
0b33ee53c1 change the em property to fix the tests and UPGRADE file as per the PR comments. 2017-12-31 18:36:41 +01:00
Guilherme Blanco
a84cac9787 More optimizations and preparation for ClassMetadataFactory replacement. Integration with ComponentMetadata started. 2017-12-31 18:36:41 +01:00
Michael Moravec
53ae602eeb Typehint EntityManagerInterface instead of EntityManager where possible 2017-12-31 18:36:40 +01:00
Usman Zafar
4e17974139 fixed the broken tests and updated the UPGRADE guide to notify about BC 2017-12-31 18:36:40 +01:00
mike
7b15963025 Add missing strict type declaration 2017-12-31 18:36:40 +01:00
mike
69893797f7 Remove another copyright header 2017-12-31 18:36:40 +01:00
mike
1c9221df0d removing copyright headers in every files 2017-12-31 18:36:39 +01:00
Usman Zafar
fb7f3bc01c added the test and updated the entitymanager 2017-12-31 18:36:39 +01:00
Michael Moravec
578b1d3dd2 Typehint EntityManagerInterface instead of EntityManager where possible 2017-12-31 18:36:38 +01:00
Usman Zafar
6b7a81690d added the final keyword EntityManager to indicate that extending EntityManager is not a valid extension point. 2017-12-31 18:36:38 +01:00
Guilherme Blanco
808e07d97c Added concept of SecondPass to ClassMetadataFactory 2017-12-31 18:36:38 +01:00
Guilherme Blanco
d5653b22b9 Added information of action items for later. 2017-12-31 18:36:38 +01:00
Guilherme Blanco
e626d1ca95 Fixed issue with associatied entities implementing __toString() 2017-12-31 18:36:38 +01:00
Michael Moravec
06d56de0e9 Drop AssignedGenerator (obsoleted by ValueGenerationPlan) 2017-12-31 18:36:38 +01:00
Michael Moravec
88fcda9a02 Added ValueGeneratorMetadata, implemented ValueGeneratorPlan 2017-12-31 18:36:37 +01:00
Michael Moravec
17e7c2a42e Fix type errors 2017-12-31 18:36:37 +01:00
Michael Moravec
6a9b817717 Enable strict types 2017-12-31 18:36:36 +01:00
Guilherme Blanco
38c21f361f Moved ClassMetadata::assignIdentifier to EntityPersister::setIdentifier. Renamed EntityPersister::getIdentifierValues to EntityPersister::getIdentifier 2017-12-31 18:36:35 +01:00
Guilherme Blanco
81ced236e5 Moved getIdentifierValues to EntityPersister 2017-12-31 18:36:35 +01:00
Guilherme Blanco
fa3d2f9102 Moved computation of FCQN resolution to Metadata building step. 2017-12-31 18:36:35 +01:00
Guilherme Blanco
2db53bdbfa Decoupled Generator and GeneratorStrategy 2017-12-31 18:36:35 +01:00
Guilherme Blanco
4a427b8b7b Eliminated the concept of ClassMetadataInterface temporarily until refactoring is complete. Replaced ObjectManagerAware with EntityManagerAware sinc eit was bound to the Common\Persistence namespace with hard dependencies. The same happened to PersistentObject. 2017-12-31 18:36:34 +01:00
Guilherme Blanco
802c94fa05 Moved MappingDriver to ORM to allow changes in its API 2017-12-31 18:36:34 +01:00
Guilherme Blanco
91ae8e25d3 Simplified RSM building for result class 2017-12-31 18:36:34 +01:00
Guilherme Blanco
e48f537590 Simplified logic and stored information around named native query. 2017-12-31 18:36:34 +01:00
Guilherme Blanco
b8d7d82b73 Implemented runtime resolution of __CLASS__ calls to SqlResultSetMapping, NativeNamedQuery and NamedQuery. Dropped isSelfClass from mappings 2017-12-31 18:36:34 +01:00
Guilherme Blanco
ff7a18aeb9 Simplified NamedQuery support 2017-12-31 18:36:33 +01:00
Luís Cobucci
ea6723eca8 Replace $this->assertXXX with self::assertXXX
Since PHPUnit test methods are all static
2017-12-31 18:36:33 +01:00
Guilherme Blanco
f954914db1 Consume custom repository class through methods only. 2017-12-31 18:36:33 +01:00
Guilherme Blanco
9c562b24d5 Removed EntityListenerBuilder 2017-12-31 18:36:33 +01:00
Guilherme Blanco
f2d1048e15 Removed direct access to ClassMetadata->name 2017-12-31 18:36:33 +01:00
Guilherme Blanco
abace42835 Removed direct access to ClassMetadata->name 2017-12-31 18:36:32 +01:00
Guilherme Blanco
c0da37443b Ensure we are using getClassName() which will be later available in ComponentMetadata 2017-12-31 18:36:32 +01:00
Guilherme Blanco
50efd6827b Return array of identifier field names instead of hardcoded identifier 2017-12-31 18:36:32 +01:00
Guilherme Blanco
f4d031ca4d Removed enqueueing for insert support from EntityPersister. There was no reason for that since concurrent inserts NEVER guarantee incremental order on a single INSERT statement. Any attempt to reliably implement is not accurate and thus I am removing any possibility of this ever becoming a reality. 2017-12-31 18:36:32 +01:00
Michael Moravec
df33284028 Move identifier generation to FieldMetadata 2017-12-31 18:36:31 +01:00
Guilherme Blanco
a5cf75c3ab Optimizations around EntityPersisters 2017-12-31 18:36:31 +01:00
Guilherme Blanco
f8061618ef Moved IdentifierFlattener temporarily to EntityManager and removed one todo 2017-12-31 18:36:31 +01:00
Guilherme Blanco
c197fb4ffe Revert "[3.0] Moved IdentifierGenerator to Property." 2017-12-31 18:36:31 +01:00
Michael Moravec
88a3f9bfb9 WIP 2017-12-31 18:36:31 +01:00
Michael Moravec
6cf0d72587 Populate FieldMetadata ID generator 2017-12-31 18:36:30 +01:00
Michael Moravec
e0e90ce5c4 OrmTestCase: Always use full AnnotationReader, drop legacy versions 2017-12-31 18:36:30 +01:00
Guilherme Blanco
bd50902da0 Removed sequence methods from class metadata 2017-12-31 18:36:30 +01:00
Guilherme Blanco
ef030bbfc2 Removed Instantiator from ClassMetadata and concentrate into UnitOfWork 2017-12-31 18:36:30 +01:00
Guilherme Blanco
c112f27362 Added generation strategy for class metadata 2017-12-31 18:36:30 +01:00
Guilherme Blanco
6cb027cd4f Quick fix 2017-12-31 18:36:29 +01:00
Marco Pivetta
4c63a562be #6118 upgrade notes mentioning the BC break in EntityManager#flush() 2017-12-31 18:36:29 +01:00
Marco Pivetta
af5281b6d7 #6118 removing UnitOfWork#commit\($entity\) signature 2017-12-31 18:36:29 +01:00
Marco Pivetta
c948b3e2e5 #6118 removing flush\($entity\) usage from the test suite 2017-12-31 18:36:29 +01:00
Marco Pivetta
e204b96d1d #6118 remove flush\($entity\)` signature 2017-12-31 18:36:29 +01:00
Marco Pivetta
ea2ec0740f #6118 remove reference to single entity flush operations 2017-12-31 18:36:28 +01:00
Marco Pivetta
2725e2e705 #6118 removing DDC-720 related tests for multiple flushed entities 2017-12-31 18:36:28 +01:00
Marco Pivetta
f40ea70ac4 #6118 removing DDC-720 related tests 2017-12-31 18:36:28 +01:00
Guilherme Blanco
2366b43b1e Removed Builders 2017-12-31 18:36:28 +01:00
Guilherme Blanco
6af9320dc8 Fixed tetss after rebase 2017-12-31 18:36:28 +01:00
Guilherme Blanco
7f1eedaaa6 Fix bugs related to rebase 2017-12-31 18:36:27 +01:00
Guilherme Blanco
46341a6e17 Quick fixes 2017-12-31 18:36:27 +01:00
Guilherme Blanco
d7fd378b3c Refactored Proxy support 2017-12-31 18:36:27 +01:00
Guilherme Blanco
8688b1626c Work on ClassMetadataFactory. Updated ProxyFactory reducing dependencies 2017-12-31 18:36:27 +01:00
Guilherme Blanco
bd1ff948b8 Quick rename 2017-12-31 18:36:26 +01:00
Guilherme Blanco
1505ef2c99 Removed isIdentifierComposite flag from ClassMetadata 2017-12-31 18:36:26 +01:00
Guilherme Blanco
213ea60923 More work on MappingFactory. Decoupled ProxyConfiguration. Centralized PersistentCollection creation. 2017-12-31 18:36:26 +01:00
Guilherme Blanco
e9406531a9 work 2017-12-31 18:36:26 +01:00
Guilherme Blanco
8b78a64e8a More work on cleanup 2017-12-31 18:36:26 +01:00
Guilherme Blanco
3bc4126246 Intermediate work for ClassMetadataFactory refactoring 2017-12-31 18:36:25 +01:00
Guilherme Blanco
e2c0f2b7c2 Simplified version field metadata setup. Implemented more exporters 2017-12-31 18:36:25 +01:00
Guilherme Blanco
bd5fb5e7d1 Added TransientMetadata support, allowing to track properties not directly mapped into ORM. This enables ChangeTrackingPolicy to assess changes happening to transient class members. Removed ReflectionPropertiesGetter hack. 2017-12-31 18:36:25 +01:00
Guilherme Blanco
fee3cd5367 Incorporated LocalColumnMetadata, simplifying runtime memory consumption over JoinColumnMetadata. Implemented more Exporters. 2017-12-31 18:36:25 +01:00
Guilherme Blanco
081986eae2 Ported AbstractClassMetadataFactory from Common to ORM, allowing us to change its implementation 2017-12-31 18:36:25 +01:00
Guilherme Blanco
941cf83a1a Encapsulated CacheMetadata from ClassMetadata into ComponentMetadata 2017-12-31 18:36:24 +01:00
Guilherme Blanco
656290d156 Encapsulated ReflectionClass 2017-12-31 18:36:24 +01:00
Guilherme Blanco
b80b30b10b More centralization around identifier flattening 2017-12-31 18:36:24 +01:00
Guilherme Blanco
946e35c2ec Minor optimizations 2017-12-31 18:36:24 +01:00
Guilherme Blanco
ad8d16a31f Fixes #6302 2017-12-31 18:36:23 +01:00
Guilherme Blanco
c404aa66ac Merged setAttributeOverride and setAssociationOverride into setPropertyOverride 2017-12-31 18:36:23 +01:00
Guilherme Blanco
9110eebadb Merged addInheritedProperty and addInheritedAssociation 2017-12-31 18:36:23 +01:00
Guilherme Blanco
830985e259 Merged addProperty and addAssociation 2017-12-31 18:36:23 +01:00
Guilherme Blanco
87f1aa7875 Merged associationMappings with properties 2017-12-31 18:36:23 +01:00
Guilherme Blanco
41919e69dc Quick changes 2017-12-31 18:36:22 +01:00
Guilherme Blanco
03927e8cff Changed isReadOnly to be private and also added wrapper method 2017-12-31 18:36:22 +01:00
Guilherme Blanco
000759790e Missing file from previous commit 2017-12-31 18:36:22 +01:00
Guilherme Blanco
99b92853cf Quick optimizations 2017-12-31 18:36:22 +01:00
Guilherme Blanco
e676d6c30e Removed ClassMetadata::getAssociationMapping and ClassMetadata::getAssociationMappings methods 2017-12-31 18:36:21 +01:00
Guilherme Blanco
6841c919fa Fixed DDC2780Test to be compliant with develop branch 2017-12-31 18:36:21 +01:00
Guilherme Blanco
347e2a55f4 Removed ClassMetadata::reflFields, delegating the work to Property instances 2017-12-31 18:36:21 +01:00
Guilherme Blanco
607a6691be Ignore .iml file 2017-12-31 18:36:21 +01:00
Guilherme Blanco
c1a46219ed Eliminated QuoteStrategy support completely and simplified SQL alias generation 2017-12-31 18:36:21 +01:00
Guilherme Blanco
0c16cce8bc Eliminated mapXToY methods and normalized into only addAssociation 2017-12-31 18:33:08 +01:00
Guilherme Blanco
6286b69fbd Introduced AssociationMetadata and its subclasses as classes. \o/ 2017-12-31 18:33:07 +01:00
Guilherme Blanco
4d12dbf30e Introduced AssociationMetadata and its subclasses as classes. \o/ 2017-12-31 18:33:07 +01:00
Guilherme Blanco
045e8b8782 Docs update 2017-12-31 18:33:07 +01:00
Guilherme Blanco
61e57aa5f4 Adios SimpleAnnotationReader! 2017-12-31 18:33:05 +01:00
Guilherme Blanco
aad3576953 Small code optimization 2017-12-31 18:30:15 +01:00
Guilherme Blanco
1d3af800df Fixed issue with EntityManagerDecoratorTest 2017-12-31 18:30:14 +01:00
Guilherme Blanco
51d6ff6c7f PHPUnit 6 WIP 2017-12-31 18:30:14 +01:00
Guilherme Blanco
56e93548f5 Added foreign key columns to the maps of columns to property names. 2017-12-31 18:30:14 +01:00
Guilherme Blanco
e28086d23b Removed ClassMetadata->containsForeignIdentifier 2017-12-31 18:30:13 +01:00
Guilherme Blanco
e805498f95 CacheMetadata is now immutable 2017-12-31 18:30:13 +01:00
Guilherme Blanco
f80561edc9 Improvement over last commit 2017-12-31 18:30:13 +01:00
Guilherme Blanco
c98970b7c3 Renamed ClassMetadata->enableCache to ClasMetadata->setCache 2017-12-31 18:30:12 +01:00
Guilherme Blanco
75f5260a89 Introduced CacheMetadata 2017-12-31 18:30:12 +01:00
Guilherme Blanco
d070fc62a7 Optimizations improvement over clear() 2017-12-31 18:30:12 +01:00
Guilherme Blanco
6b28e558cf Fixes #5855. Removed ability to EntityManager::clear($entityName), clear($entityClass), clear($proxyClass), clear($rootOfInheritance) 2017-12-31 18:30:11 +01:00
Guilherme Blanco
4bbe058e02 Fixed DDC-536 (GH #5044). Remove the _ prefix from private and protected members 2017-12-31 18:30:11 +01:00
Luís Cobucci
242f3f0343 Use objects instead of arrays for join tables and columns 2017-12-31 18:30:10 +01:00
Luís Cobucci
edd92d8ae6 Required development version of DBAL 2017-12-31 18:30:10 +01:00
Jáchym Toušek
9205519217 Fix typehints in EntityManagerInterface implementations 2017-12-31 18:30:10 +01:00
Jáchym Toušek
a9821eae7b EntityManager::transactional() doesn't use call_user_func 2017-12-31 18:30:10 +01:00
Jáchym Toušek
97378f7cdc Refactor EntityManagerTest 2017-12-31 18:30:09 +01:00
Jáchym Toušek
377d2dc190 EntityManager::transactional() catches Throwable 2017-12-31 18:30:09 +01:00
Jáchym Toušek
7e62f21a23 EntityManager::transactional() uses callable type-hint 2017-12-31 18:30:09 +01:00
Jáchym Toušek
e18d5da193 EntityManager::transactional() returns value returned by the closure 2017-12-31 18:30:09 +01:00
Guilherme Blanco
ffbb835b05 More optimizations and cleanup 2017-12-31 18:30:09 +01:00
Guilherme Blanco
fbf081814c Removed code duplication of helper methods, inlining calls. 2017-12-31 18:30:08 +01:00
Guilherme Blanco
9615382856 Removed ClassMetadata::GENERATOR_TYPE_* constants and created GeneratorType::* 2017-12-31 18:30:08 +01:00
Guilherme Blanco
8e6cf48908 Removed ClassMetadata::CHANGETRACKING_* constants and created ChangeTrackingPolicy::* 2017-12-31 18:30:08 +01:00
Guilherme Blanco
15d45cecbd Removed ClassMetadata::INHERITANCE_TYPE_* constants and created InheritanceType::* 2017-12-31 18:30:07 +01:00
Guilherme Blanco
7403ca0ce3 Removed ClassMetadata::CACHE_USAGE_* constants and created CacheUsage::* 2017-12-31 18:30:07 +01:00
Guilherme Blanco
30ec740011 Removed ClassMetadata::FETCH_* constants and created FetchMode::* 2017-12-31 18:30:07 +01:00
Guilherme Blanco
792d9cbe61 Removed relationToTargetKeyColumns and relationToSourceKeyColumns from association mapping 2017-12-31 18:30:07 +01:00
Guilherme Blanco
2ed4447b64 Eliminated sourceToTargetKeyColumns from association mapping 2017-12-31 18:30:06 +01:00
Guilherme Blanco
ef378ccd94 Eliminated targetToSourceKeyColumns from association mapping 2017-12-31 18:30:06 +01:00
Guilherme Blanco
7007d4c0fc Removed most of targetToSourceKeyColumns usages 2017-12-31 18:30:06 +01:00
Guilherme Blanco
3cb30021c5 Removed support for joinColumnFieldNames 2017-12-31 18:30:06 +01:00
Guilherme Blanco
169ff83b11 Implemented JoinTableMetadata 2017-12-31 18:30:05 +01:00
Guilherme Blanco
5908cac18f Removed QuoteStrategy::getTableName() 2017-12-31 18:30:05 +01:00
Guilherme Blanco
b7f0567273 Finalized TableMetadata implementation 2017-12-31 18:30:05 +01:00
Guilherme Blanco
8a4ca55e8b Introduced concept of TableMetadata. Still a few tests to finish fixing 2017-12-31 18:30:05 +01:00
Guilherme Blanco
e5b216c523 Decoupled unique constraint from unique index 2017-12-31 18:30:04 +01:00
Guilherme Blanco
2f7f3fbf59 Allow unique index creation from ORM mapping 2017-12-31 18:30:04 +01:00
Guilherme Blanco
e7aa7d5b39 Moved FieldMetadata creation out of ClassMetadata 2017-12-31 18:30:04 +01:00
Guilherme Blanco
36d8b337af Simplified property inheritance logic when loading class metadata 2017-12-31 18:30:03 +01:00
Guilherme Blanco
13e53d12a0 Checks for references, proxies and retrievals on EM. Removed todo from UnitOfWork 2017-12-31 18:30:03 +01:00
Guilherme Blanco
392850cf2f Merged sequenceGeneratorDefinition and customGeneratorDefinition into a single, unified structure generatorDefinition 2017-12-31 18:30:03 +01:00
Guilherme Blanco
47bfece156 Strict types 2017-12-31 18:30:03 +01:00
Guilherme Blanco
cda24bf8c3 Fixing remaining possible to be fixed unit tests 2017-12-31 18:30:03 +01:00
Guilherme Blanco
b4df1ec96f Starting the concept of Builders on Drivers 2017-12-31 18:30:02 +01:00
Guilherme Blanco
246349b8e5 Introduced JoinColumnMetadata and refactored most tests. Still 14 failing related to OO change. 2017-12-31 18:30:02 +01:00
Guilherme Blanco
48da5b8cc6 More work around JoinColumns. Should start AssociationMetadata changes by next commit 2017-12-31 18:30:02 +01:00
Marco Pivetta
af259157a2 s/should/**MUST** as per @afoeder's review
Ref: 0f76b969cd..8f5ebd93c1 (r70573803)
2017-12-31 18:30:01 +01:00
Luís Cobucci
0dcb732a3c Adding YAML removal as BC break. 2017-12-31 18:30:01 +01:00
Luís Cobucci
f54f4a5b97 Removing YAML mappings on docblocks and messages. 2017-12-31 18:30:01 +01:00
Luís Cobucci
1e6d30da83 Removing YAML drivers and all its references. 2017-12-31 18:30:01 +01:00
Luís Cobucci
4e2d754ae7 Removing YAML class metadata exporter and its references. 2017-12-31 18:30:01 +01:00
Luís Cobucci
e1ee929dad Removing Doctrine ORM 1 schema conversion tool.
This tool reads and writes YAML files so it should be removed.
2017-12-31 18:30:00 +01:00
Guilherme Blanco
6446a9626c Removed some methods from QuoteStrategy (beginning of the end of quoting saga). Renamed identity generator to become sequencing generators. 2017-12-31 18:30:00 +01:00
Guilherme Blanco
6fb1bdefec Fix for test 2017-12-31 18:30:00 +01:00
Guilherme Blanco
bd1c03fb15 Fixes and implemented incomplete tests 2017-12-31 18:30:00 +01:00
Guilherme Blanco
6aa543978c Fixes to bugs and made test more consistent 2017-12-31 18:30:00 +01:00
Guilherme Blanco
b9d38d94b9 More work related to ClassMetadataBuilder changes and some fixes to broken tests 2017-12-31 18:29:59 +01:00
Guilherme Blanco
7c39836ce6 Breaking everything with start migration to use ClassMetadataBuilder in Mapping Drivers 2017-12-31 18:29:59 +01:00
Guilherme Blanco
c498805966 Removed isCascadeXXX 2017-12-31 18:29:59 +01:00
Guilherme Blanco
32c28ffe90 Cosmetic 2017-12-31 18:29:59 +01:00
Guilherme Blanco
a5375e3a1a Cosmetic 2017-12-31 18:29:59 +01:00
Guilherme Blanco
c63a0ab56a Removed the need for FielMetadata::$currentClass property 2017-12-31 18:29:58 +01:00
Guilherme Blanco
a77cdaf5eb Switched versionField to versionProperty 2017-12-31 18:29:58 +01:00
Guilherme Blanco
d2835395ad Removed isVersioned property. 2017-12-31 18:29:58 +01:00
Guilherme Blanco
917e5ea8c7 Finalized changes to ensure everything breaking now is due to quoting being applied everywhere 2017-12-31 18:29:58 +01:00
Guilherme Blanco
8b856c799a Moved Discriminator Column to OO approach and refactored a bit for persisters 2017-12-31 18:29:57 +01:00
Guilherme Blanco
b97f85af46 Decoupled FieldMetadata into FieldMetadata and ColumnMetadata 2017-12-31 18:25:15 +01:00
Guilherme Blanco
80b05a889a Quick improvements 2017-12-31 18:25:15 +01:00
Guilherme Blanco
53ba16d747 Merged FieldMetadata and InheritedFieldMetadata into a single unit 2017-12-31 18:25:15 +01:00
Guilherme Blanco
1d2b5962b0 Refactored QuoteStrategy::getColumnName() 2017-12-31 18:25:15 +01:00
Guilherme Blanco
8d1e7b3fd5 Normalized quote strategy execution for discriminator columns and join columns 2017-12-31 18:25:14 +01:00
Guilherme Blanco
975ebef19d No more errors (just failures) for FieldMetadata 2017-12-31 18:25:14 +01:00
Guilherme Blanco
548865b621 More work towards FieldMetadata 2017-12-31 18:25:14 +01:00
Guilherme Blanco
db187bb8a9 Removed unused methods 2017-12-31 18:25:14 +01:00
Guilherme Blanco
5e29c80ca3 Removed traces of fieldMappings from codebase 2017-12-31 18:25:14 +01:00
Guilherme Blanco
08e2f779e3 Removed quoting support and make sure we always quote data. Still missing checks for discriminator column and version column. 2017-12-31 18:25:13 +01:00
Guilherme Blanco
7c4e5444d6 More fixed unit tests 2017-12-31 18:25:13 +01:00
Guilherme Blanco
169ac6d13d Converted ClassMetadtaa::setVersionMapping to use FieldMetadata instead of mapping 2017-12-31 18:25:13 +01:00
Guilherme Blanco
fe1e3c0fa9 Fixed a bunch of unit tests 2017-12-31 18:25:13 +01:00
Guilherme Blanco
97f077a120 More work related to FieldMetadata and InheritedFieldMetadata 2017-12-31 18:25:13 +01:00
Guilherme Blanco
0a0203fa43 Added InheritedFieldMetadata and got rid of most fieldMappings in the codebase 2017-12-31 18:25:12 +01:00
Guilherme Blanco
ecc711cb73 Moved all mapField to addProperty 2017-12-31 18:25:12 +01:00
Guilherme Blanco
83b91b81ca Commented embeddeds support until fields are complete. Embeddeds will be brought back with proper implementation 2017-12-31 18:25:12 +01:00
Guilherme Blanco
9f6dc1d8a8 Initial code for FieldMetadata 2017-12-31 18:25:12 +01:00
Guilherme Blanco
ac34415bf3 Fixed unit test 2017-12-31 18:25:12 +01:00
Guilherme Blanco
ed40837b45 Fixed unit test 2017-12-31 18:25:11 +01:00
Guilherme Blanco
2f69aece64 Upgrade file 2017-12-31 18:25:11 +01:00
Guilherme Blanco
516f2e1083 Fix for tableName in STI 2017-12-31 18:25:11 +01:00
Guilherme Blanco
a5d136d5e6 Added tableName on fields, association join columns and embeddeds. 2017-12-31 18:25:11 +01:00
Guilherme Blanco
db7ecb2721 Made fields, associations, join columns, version fields, identifiers, embeddeds and discriminator columns to hold its owning table name. 2017-12-31 18:25:11 +01:00
Guilherme Blanco
6adcb5ed68 Switched getSQLTableAlias to use table names instead of class names 2017-12-31 18:25:10 +01:00
Guilherme Blanco
ff6d24d104 Finalized inclusion of support for declaringClass 2017-12-31 18:25:10 +01:00
Guilherme Blanco
c73f4cff8e Added declaringClass and fixed almost all unit tests with the exception of EntityGeneratorTest. No explanation why it iss failing yet 2017-12-31 18:25:10 +01:00
Guilherme Blanco
aac92169b7 $this->assertXXX changes to self::assertXXX as PHPUnit test methods are all static 2017-12-31 18:25:09 +01:00
Guilherme Blanco
4f76085494 ClassMetadata::[]['type'] now holds a Type instance instead of string 2017-12-31 11:36:40 +01:00
Guilherme Blanco
c8ddbddc19 Some CS fixes 2017-12-31 11:32:36 +01:00
Guilherme Blanco
e4d363122a Optimized EntityPersister::getSelectColumnSQL() and EntityInheritancePersistence::getSelectJoinColumnSQL() 2017-12-31 11:32:36 +01:00
Guilherme Blanco
a568530c6b Removed ClassMetadata::getTypeOfColumn() method 2017-12-31 11:32:35 +01:00
Guilherme Blanco
55596e9d07 Removed ClassMetadata::$fieldMappings[$field][requireSQLConversion] 2017-12-31 11:32:35 +01:00
Guilherme Blanco
6eb2ca4689 Removed ClassMetadata::$namespace 2017-12-31 11:32:35 +01:00
Guilherme Blanco
8731c086f9 Removed ClassMetadata::$columnNames. Improved overall test suite by 10% due to less serialization/deserialization 2017-12-31 11:32:35 +01:00
Guilherme Blanco
2d36a5da6b Renamed setIdentifierValues to assignIdentifier 2017-12-31 11:32:35 +01:00
Guilherme Blanco
56b245e4a6 Removed ClassMetadataInfo. Before suite run: 7.19 seconds. After: 6.7 seconds 2017-12-31 11:32:31 +01:00
1585 changed files with 66414 additions and 81958 deletions

49
.doctrine-project.json Normal file
View File

@@ -0,0 +1,49 @@
{
"active": true,
"name": "Object Relational Mapper",
"shortName": "ORM",
"slug": "orm",
"docsSlug": "doctrine-orm",
"versions": [
{
"name": "3.0",
"branchName": "master",
"slug": "latest",
"upcoming": true
},
{
"name": "2.8",
"branchName": "2.8.x",
"slug": "2.8",
"upcoming": true
},
{
"name": "2.7",
"branchName": "2.7",
"slug": "2.7",
"current": true,
"aliases": [
"current",
"stable"
]
},
{
"name": "2.6",
"branchName": "2.6",
"slug": "2.6",
"maintained": false
},
{
"name": "2.5",
"branchName": "2.5",
"slug": "2.5",
"maintained": false
},
{
"name": "2.4",
"branchName": "2.4",
"slug": "2.4",
"maintained": false
}
]
}

1
.gitattributes vendored
View File

@@ -11,3 +11,4 @@ CONTRIBUTING.md export-ignore
phpunit.xml.dist export-ignore
run-all.sh export-ignore
phpcs.xml.dist export-ignore
composer.lock export-ignore

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
patreon: phpdoctrine
tidelift: packagist/doctrine/orm
custom: https://www.doctrine-project.org/sponsorship.html

37
.github/ISSUE_TEMPLATE/BC_Break.md vendored Normal file
View File

@@ -0,0 +1,37 @@
---
name: 💥 BC Break
about: Have you encountered an issue during upgrade? 💣
---
<!--
Before reporting a BC break, please consult the upgrading document to make sure it's not an expected change: https://github.com/doctrine/orm/blob/master/UPGRADE.md
-->
### BC Break Report
<!-- Fill in the relevant information below to help triage your issue. -->
| Q | A
|------------ | ------
| BC Break | yes
| Version | x.y.z
#### Summary
<!-- Provide a summary describing the problem you are experiencing. -->
#### Previous behavior
<!-- What was the previous (working) behavior? -->
#### Current behavior
<!-- What is the current (broken) behavior? -->
#### How to reproduce
<!--
Provide steps to reproduce the BC break.
If possible, also add a code snippet with relevant configuration, entity mappings, DQL etc.
Adding a failing Unit or Functional Test would help us a lot - you can submit it in a Pull Request separately, referencing this bug report.
-->

34
.github/ISSUE_TEMPLATE/Bug.md vendored Normal file
View File

@@ -0,0 +1,34 @@
---
name: 🐞 Bug Report
about: Something is broken? 🔨
---
### Bug Report
<!-- Fill in the relevant information below to help triage your issue. -->
| Q | A
|------------ | ------
| BC Break | yes/no
| Version | x.y.z
#### Summary
<!-- Provide a summary describing the problem you are experiencing. -->
#### Current behavior
<!-- What is the current (buggy) behavior? -->
#### How to reproduce
<!--
Provide steps to reproduce the bug.
If possible, also add a code snippet with relevant configuration, entity mappings, DQL etc.
Adding a failing Unit or Functional Test would help us a lot - you can submit one in a Pull Request separately, referencing this bug report.
-->
#### Expected behavior
<!-- What was the expected (correct) behavior? -->

View File

@@ -0,0 +1,18 @@
---
name: 🎉 Feature Request
about: You have a neat idea that should be implemented? 🎩
---
### Feature Request
<!-- Fill in the relevant information below to help triage your issue. -->
| Q | A
|------------ | ------
| New Feature | yes
| RFC | yes/no
| BC Break | yes/no
#### Summary
<!-- Provide a summary of the feature you would like to see implemented. -->

View File

@@ -0,0 +1,20 @@
---
name: ❓ Support Question
about: Have a problem that you can't figure out? 🤔
---
<!-- Fill in the relevant information below to help triage your issue. -->
| Q | A
|------------ | -----
| Version | x.y.z
<!--
Before asking question here, please try asking on Gitter or Slack first.
Find out more about Doctrine support channels here: https://www.doctrine-project.org/community/
Keep in mind that GitHub is primarily an issue tracker.
-->
### Support Question
<!-- Describe the issue you are facing here. -->

View File

@@ -0,0 +1,19 @@
---
name: 🐞 Failing Test
about: You found a bug and have a failing Unit or Functional test? 🔨
---
### Failing Test
<!-- Fill in the relevant information below to help triage your issue. -->
| Q | A
|------------ | ------
| BC Break | yes/no
| Version | x.y.z
#### Summary
<!-- Provide a summary of the failing scenario. -->

View File

@@ -0,0 +1,18 @@
---
name: ⚙ Improvement
about: You have some improvement to make Doctrine better? 🎁
---
### Improvement
<!-- Fill in the relevant information below to help triage your issue. -->
| Q | A
|------------ | ------
| New Feature | yes
| RFC | yes/no
| BC Break | yes/no
#### Summary
<!-- Provide a summary of the improvement you are submitting. -->

View File

@@ -0,0 +1,26 @@
---
name: 🎉 New Feature
about: You have implemented some neat idea that you want to make part of Doctrine? 🎩
---
<!--
Thank you for submitting new feature!
Pick the target branch based according to these criteria:
* submitting a bugfix: target the lowest active stable branch: 2.7
* submitting a new feature: target the next minor branch: 2.8.x
* submitting a BC-breaking change: target the master branch
-->
### New Feature
<!-- Fill in the relevant information below to help triage your issue. -->
| Q | A
|------------ | ------
| New Feature | yes
| RFC | yes/no
| BC Break | yes/no
#### Summary
<!-- Provide a summary of the feature you have implemented. -->

47
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: CI
on:
pull_request:
push:
branches:
- master
jobs:
coding-standards:
name: "Coding Standards"
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
extensions: mbstring
tools: composer, cs2pr
- name: composer install
run: "composer install --no-progress --no-suggest --no-interaction --prefer-dist --optimize-autoloader"
- name: phpcs
run: "php vendor/bin/phpcs -q --report=checkstyle --no-colors | cs2pr"
static-analysis:
name: "Static Analysis"
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '7.4'
extensions: mbstring
tools: composer, cs2pr
- name: composer install
run: "composer install --no-progress --no-suggest --no-interaction --prefer-dist --optimize-autoloader"
- name: phpstan
run: "php vendor/bin/phpstan analyse --error-format=checkstyle --no-progress | cs2pr"

6
.gitignore vendored
View File

@@ -7,11 +7,13 @@ lib/api/
lib/Doctrine/Common
lib/Doctrine/DBAL
/.settings/
*.iml
.buildpath
.project
.idea
*.iml
vendor/
composer.lock
composer.phar
/tests/Doctrine/Performance/history.db
/.phpcs-cache
phpbench.phar
phpbench.phar.pubkey

View File

@@ -3,20 +3,20 @@ build:
analysis:
environment:
php:
version: 7.1
version: 7.4
cache:
disabled: false
directories:
- ~/.composer/cache
project_setup:
override: true
tests:
override:
- php-scrutinizer-run
before_commands:
- "composer install --no-dev --prefer-source"
- phpcs-run
dependencies:
override:
- composer install --no-interaction --prefer-dist
tools:
external_code_coverage:
@@ -25,10 +25,8 @@ tools:
filter:
excluded_paths:
- docs
- tools
build_failure_conditions:
- 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed
- 'issues.severity(>= MAJOR).new.exists' # New issues of major or higher severity
- 'project.metric_change("scrutinizer.test_coverage", < 0)' # Code Coverage decreased from previous inspection
- 'patches.label("Unused Use Statements").new.exists' # No new unused imports patches allowed

View File

@@ -3,69 +3,60 @@ sudo: false
language: php
php:
- 7.1
- 7.2
- nightly
- 7.3
- 7.4
env:
- DB=sqlite
- DB=mariadb
- DB=mysql
- DB=pgsql
- DB=sqlite
before_install:
- mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{,.disabled} || echo "xdebug not available"
- composer self-update
- |
if [[ "$COVERAGE" != "1" ]]; then
phpenv config-rm ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini || echo "xdebug is not installed"
fi
- echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- travis_retry composer self-update
install: travis_retry composer update --prefer-dist
install:
- rm composer.lock
- travis_retry composer update --no-interaction --prefer-dist --no-suggest --no-progress
script:
- if [[ "$DB" == "mysql" || "$DB" == "mariadb" ]]; then mysql -e "CREATE SCHEMA doctrine_tests; GRANT ALL PRIVILEGES ON doctrine_tests.* to travis@'%'"; fi
- |
if [[ "$DB" == "mysql" || "$DB" == "mariadb" ]]; then
mysql -e "CREATE SCHEMA doctrine_tests; GRANT ALL PRIVILEGES ON doctrine_tests.* to travis@'%'";
fi
- ENABLE_SECOND_LEVEL_CACHE=0 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml
- ENABLE_SECOND_LEVEL_CACHE=1 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml --exclude-group performance,non-cacheable,locking_functional
# temporarily disabled
#- ENABLE_SECOND_LEVEL_CACHE=1 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml --exclude-group performance,non-cacheable,locking_functional
jobs:
include:
- stage: Test
env: DB=mariadb
addons:
mariadb: 10.1
- stage: Test
env: DB=mysql MYSQL_VERSION=5.7
php: 7.1
before_script:
- ./tests/travis/install-mysql-$MYSQL_VERSION.sh
sudo: required
- stage: Test
env: DB=mysql MYSQL_VERSION=5.7
php: 7.2
before_script:
- ./tests/travis/install-mysql-$MYSQL_VERSION.sh
sudo: required
- stage: Test
env: DB=mysql MYSQL_VERSION=5.7
php: nightly
before_script:
- ./tests/travis/install-mysql-$MYSQL_VERSION.sh
sudo: required
mariadb: "10.4"
- stage: Test
env: DB=sqlite DEPENDENCIES=low
install: travis_retry composer update --prefer-dist --prefer-lowest
install:
- travis_retry composer update --no-interaction --prefer-dist --no-suggest --no-progress --prefer-lowest
- stage: Test
if: type = cron
php: 7.3
env: DB=sqlite DEV_DEPENDENCIES
install:
- rm composer.lock
- composer config minimum-stability dev
- travis_retry composer update --prefer-dist
- travis_retry composer update --no-interaction --prefer-dist --no-suggest --no-progress
- stage: Test
env: DB=sqlite COVERAGE
before_script:
- mv ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini{.disabled,}
- if [[ ! $(php -m | grep -si xdebug) ]]; then echo "xdebug required for coverage"; exit 1; fi
script:
- ENABLE_SECOND_LEVEL_CACHE=0 ./vendor/bin/phpunit -v -c tests/travis/$DB.travis.xml --coverage-clover ./build/logs/clover.xml
@@ -73,29 +64,19 @@ jobs:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml
- stage: Code Quality
env: DB=none STATIC_ANALYSIS
install: travis_retry composer update --prefer-dist --prefer-stable
before_script:
- echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- echo "extension=redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- travis_retry composer require --dev --prefer-dist --prefer-stable phpstan/phpstan:^0.9
script: vendor/bin/phpstan analyse -l 1 -c phpstan.neon lib
- stage: Code Quality
env: DB=none BENCHMARK
before_script: wget https://phpbench.github.io/phpbench/phpbench.phar https://phpbench.github.io/phpbench/phpbench.phar.pubkey
script: php phpbench.phar run -l dots --report=default
- stage: Code Quality
env: DB=none CODING_STANDARDS
php: nightly
before_script:
- wget https://phpbench.github.io/phpbench/phpbench.phar https://phpbench.github.io/phpbench/phpbench.phar.pubkey
script:
- ./vendor/bin/phpcs
- php phpbench.phar run --bootstrap=tests/Doctrine/Tests/TestInit.php -l dots --report=default
allow_failures:
- php: nightly
# temporarily disabled
- env: DB=mysql
- env: DB=mariadb
- env: DB=pgsql
cache:
directories:
- $HOME/.composer/cache
- $HOME/.composer/cache

View File

@@ -1,79 +1,81 @@
# Contribute to Doctrine
# Contributing to Doctrine ORM
Thank you for contributing to Doctrine!
Thank you for contributing to Doctrine ORM!
Before we can merge your Pull-Request here are some guidelines that you need to follow.
Before we can merge your pull request here are some guidelines that you need to follow.
These guidelines exist not to annoy you, but to keep the code base clean,
unified and future proof.
## We only accept PRs to "master"
## Obtaining a copy
Our branching strategy is "everything to master first", even
bugfixes and we then merge them into the stable branches. You should only
open pull requests against the master branch. Otherwise we cannot accept the PR.
In order to submit a pull request, you will need to [fork the project][Fork] and obtain a
fresh copy of the source code:
There is one exception to the rule, when we merged a bug into some stable branches
we do occasionally accept pull requests that merge the same bug fix into earlier
branches.
```sh
git clone git@github.com:<your-github-name>/orm.git
cd orm
```
Then you will have to run a Composer installation in the project:
```sh
curl -sS https://getcomposer.org/installer | php
./composer.phar install
```
## Choosing the branch
* I am submitting a bugfix for a stable release
* Your PR should target the [lowest active stable branch (2.7)][2.7].
* I am submitting a new feature
* Your PR should target the [master branch (3.0)][Master].
* I am submitting a BC-breaking change
* Your PR must target the [master branch (3.0)][Master].
* Please also try to provide a deprecation path in a PR targeting the [2.8 branch][2.8].
Please always create a new branch for your changes (i.e. do not commit directly into `master`
in your fork), otherwise you would run into troubles with creating multiple pull requests.
## Coding Standard
We use PSR-1 and PSR-2:
We follow the [Doctrine Coding Standard][CS].
Please refer to this repository to learn about the rules your code should follow.
You can also use `vendor/bin/phpcs` to validate your changes locally.
* https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
* https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
## Tests
with some exceptions/differences:
* Keep the nesting of control structures per method as small as possible
* Align equals (=) signs
* Add spaces between assignment, control and return statements
* Prefer early exit over nesting conditions
* Add spaces around a negation if condition ``if ( ! $cond)``
## Unit-Tests
Please try to add a test for your pull-request.
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,
``DDC1234Test.php`` for example.
* If you want to contribute new functionality add unit- or functional tests
``tests/Doctrine/Tests/ORM/Functional/Ticket`` with the identifier of the issue,
i.e. ``GH1234Test.php`` for an issue with id `#1234`.
* If you want to contribute new functionality, add unit or functional tests
depending on the scope of the feature.
You can run the unit-tests by calling ``vendor/bin/phpunit`` from the root of the project.
It will run all the tests with an in memory SQLite database.
In order to do that, you will need a fresh copy of doctrine2, and you
will have to run a composer installation in the project:
```sh
git clone git@github.com:doctrine/doctrine2.git
cd doctrine2
curl -sS https://getcomposer.org/installer | php --
./composer.phar install
```
You can run the tests by calling ``vendor/bin/phpunit`` from the root of the project.
It will run all the tests with an in-memory SQLite database.
To run the testsuite against another database, copy the ``phpunit.xml.dist``
to for example ``mysql.phpunit.xml`` and edit the parameters. You can
take a look at the ``tests/travis`` folder for some examples. Then run:
vendor/bin/phpunit -c mysql.phpunit.xml
If you do not provide these parameters, the test suite will use an in-memory
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/doctrine2/tree/master/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2306Test.php` for an
example.
1. If you put a test into the `Ticket` namespace as described above, put the testcase
and all entities into the same file.
See [DDC2306Test][Test Example] for an example.
## Travis
## CI
We automatically run your pull request through [Travis CI](http://www.travis-ci.org)
against SQLite, MySQL and PostgreSQL. If you break the tests, we cannot merge your code,
so please make sure that your code is working before opening up a Pull-Request.
We automatically run all pull requests through [Travis CI][Travis].
* The test suite is ran against SQLite, MySQL, MariaDB and PostgreSQL on all supported PHP versions.
* The code is validated against our [Coding Standard](#coding-standard).
* The code is checked by a static analysis tool.
If you break the tests, we cannot merge your code,
so please make sure that your code is working before opening a pull request.
## Getting merged
@@ -82,3 +84,10 @@ everything as fast as possible, but cannot always live up to our own expectation
Thank you very much again for your contribution!
[Master]: https://github.com/doctrine/orm/tree/master
[2.8]: https://github.com/doctrine/orm/tree/2.8.x
[2.7]: https://github.com/doctrine/orm/tree/2.7
[CS]: https://github.com/doctrine/coding-standard
[Fork]: https://guides.github.com/activities/forking/
[Travis]: https://www.travis-ci.org
[Test Example]: https://github.com/doctrine/orm/tree/master/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2306Test.php

View File

@@ -1,4 +1,4 @@
Copyright (c) 2006-2015 Doctrine Project
Copyright (c) Doctrine Project
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

View File

@@ -1,14 +1,36 @@
| [Master][Master] | [2.5][2.5] |
|:----------------:|:----------:|
| [![Build status][Master image]][Master] | [![Build status][2.5 image]][2.5] |
| [![Coverage Status][Master coverage image]][Master coverage] | [![Coverage Status][2.5 coverage image]][2.5 coverage] |
[![Tidelift](https://tidelift.com/badges/github/doctrine/orm)](https://tidelift.com/subscription/pkg/packagist-doctrine-orm?utm_source=packagist-doctrine-orm&utm_medium=referral&utm_campaign=readme)
Doctrine 2 is an object-relational mapper (ORM) for PHP 7.1+ that provides transparent persistence
| [Master][Master] | [2.8][2.8] | [2.7][2.7] |
|:----------------:|:----------:|:----------:|
| [![Build status][Master image]][Master] | [![Build status][2.8 image]][2.8] | [![Build status][2.7 image]][2.7] |
| [![Coverage Status][Master coverage image]][Master coverage] | [![Coverage Status][2.8 coverage image]][2.8 coverage] | [![Coverage Status][2.7 coverage image]][2.7 coverage] |
##### :warning: You are browsing the code of upcoming Doctrine 3.0.
##### Things changed a lot here and major code changes should be expected. If you are rather looking for a stable version, refer to the [2.7 branch][2.7] for the current stable release or [2.8 branch][2.8] for the upcoming release. If you are submitting a pull request, please see the _[Which branch should I choose?](#which-branch-should-i-choose)_ section below.
-----
Doctrine 3 is an object-relational mapper (ORM) for PHP 7.2+ that provides transparent persistence
for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features
is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL),
inspired by Hibernate's HQL. This provides developers with a powerful alternative to SQL that maintains flexibility
without requiring unnecessary code duplication.
-----
### Which branch should I choose?
Please see [Choosing the branch](CONTRIBUTING.md#choosing-the-branch) to get more information about which branch
you should target your pull request at.
## Doctrine ORM for enterprise
Available as part of the Tidelift Subscription.
The maintainers of Doctrine ORM and thousands of other packages are working with Tidelift to deliver commercial support
and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve
code health, while paying the maintainers of the exact dependencies you use.
[Learn more.](https://tidelift.com/subscription/pkg/packagist-doctrine-orm?utm_source=packagist-doctrine-orm&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
## More resources:
@@ -16,11 +38,15 @@ without requiring unnecessary code duplication.
* [Documentation](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/index.html)
[Master image]: https://img.shields.io/travis/doctrine/doctrine2/master.svg?style=flat-square
[Master]: https://travis-ci.org/doctrine/doctrine2
[Master coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/doctrine2/master.svg?style=flat-square
[Master coverage]: https://scrutinizer-ci.com/g/doctrine/doctrine2/?branch=master
[2.5 image]: https://img.shields.io/travis/doctrine/doctrine2/2.5.svg?style=flat-square
[2.5]: https://github.com/doctrine/doctrine2/tree/2.5
[2.5 coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/doctrine2/2.5.svg?style=flat-square
[2.5 coverage]: https://scrutinizer-ci.com/g/doctrine/doctrine2/?branch=2.5
[Master image]: https://img.shields.io/travis/doctrine/orm/master.svg?style=flat-square
[Master]: https://travis-ci.org/doctrine/orm
[Master coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/orm/master.svg?style=flat-square
[Master coverage]: https://scrutinizer-ci.com/g/doctrine/orm/?branch=master
[2.8 image]: https://img.shields.io/travis/doctrine/orm/2.8.x.svg?style=flat-square
[2.8]: https://github.com/doctrine/orm/tree/2.8.x
[2.8 coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/orm/2.8.x.svg?style=flat-square
[2.8 coverage]: https://scrutinizer-ci.com/g/doctrine/orm/?branch=2.8.x
[2.7 image]: https://img.shields.io/travis/doctrine/orm/2.7.svg?style=flat-square
[2.7]: https://github.com/doctrine/orm/tree/2.7
[2.7 coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/orm/2.7.svg?style=flat-square
[2.7 coverage]: https://scrutinizer-ci.com/g/doctrine/orm/?branch=2.7

View File

@@ -11,7 +11,7 @@ Please read the documentation chapter on Security in Doctrine DBAL and ORM to
understand the assumptions we make.
- [DBAL Security Page](https://github.com/doctrine/dbal/blob/master/docs/en/reference/security.rst)
- [ORM Security Page](https://github.com/doctrine/doctrine2/blob/master/docs/en/reference/security.rst)
- [ORM Security Page](https://github.com/doctrine/orm/blob/master/docs/en/reference/security.rst)
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

View File

@@ -1,5 +1,343 @@
# Upgrade to 3.0
## BC Break: Removed ability to clear cache via console with some cache drivers
The console commands `orm:clear-cache:metadata`, `orm:clear-cache:result`,
and `orm:clear-cache:query` cannot be used with the `ApcCache`, `ApcuCache`,
or `XcacheCache` because the memory is only available to the webserver process.
## BC Break: `orm:run-dql` command's `$depth` parameter removed
The `$depth` parameter has been removed, the dumping functionality
is now provided by [`symfony/var-dumper`](https://github.com/symfony/var-dumper).
## BC Break: Dropped `Doctrine\ORM\Tools\Setup::registerAutoloadDirectory()`
This method used deprecated Doctrine Autoloader and has been removed. Please rely on Composer autoloading instead.
## BC Break: Dropped automatic discriminator map discovery
Automatic discriminator map discovery exhibited multiple flaws
that can't be reliably addressed and supported:
* discovered entries are not namespaced which leads to collisions,
* the class name is part of the discriminator map, therefore the class
must never be renamed.
As a consequence this feature has been dropped.
If your code relied on this feature, please build the discriminator map for
your inheritance tree manually where each entry is an unqualified lowercase
name of the member entities.
## BC Break: Missing type declaration added for identifier generators
The interfaces `Doctrine\ORM\Sequencing\Generator` and
`Doctrine\ORM\Sequencing\Planning\ValueGenerationPlan` now uses explicit type
declaration for parameters and return (as much as possible).
## BC Break: Removed possibility to extend the doctrine mapping xml schema with anything
If you want to extend it now you have to provide your own validation schema.
## BC Break: Entity Listeners no long support naming convention methods
If you want their behavior to be kept, please add the necessary Annotation methods (in case XML driver is used,
no changes are necessary).
## BC Break: Removed `Doctrine\ORM\Mapping\Exporter\VariableExporter` constants
This constant has been removed
* `Doctrine\ORM\Mapping\Exporter\VariableExporter::INDENTATION`
## BC Break: Removed support for named queries and named native queries
These classes have been removed:
* `Doctrine/ORM/Annotation/NamedQueries`
* `Doctrine/ORM/Annotation/NamedQuery`
* `Doctrine/ORM/Annotation/NamedNativeQueries`
* `Doctrine/ORM/Annotation/NamedNativeQuery`
* `Doctrine/ORM/Annotation/ColumnResult`
* `Doctrine/ORM/Annotation/FieldResult`
* `Doctrine/ORM/Annotation/EntityResult`
* `Doctrine/ORM/Annotation/SqlResultSetMapping`
* `Doctrine/ORM/Annotation/SqlResultSetMappings`
These methods have been removed:
* `Doctrine/ORM/Configuration::addNamedQuery()`
* `Doctrine/ORM/Configuration::getNamedQuery()`
* `Doctrine/ORM/Configuration::addNamedNativeQuery()`
* `Doctrine/ORM/Configuration::getNamedNativeQuery()`
* `Doctrine/ORM/Decorator/EntityManagerDecorator::createNamedQuery()`
* `Doctrine/ORM/Decorator/EntityManagerDecorator::createNamedNativeQuery()`
* `Doctrine/ORM/EntityManager::createNamedQuery()`
* `Doctrine/ORM/EntityManager::createNamedNativeQuery()`
* `Doctrine/ORM/EntityManagerInterface::createNamedQuery()`
* `Doctrine/ORM/EntityManagerInterface::createNamedNativeQuery()`
* `Doctrine/ORM/EntityRepository::createNamedQuery()`
* `Doctrine/ORM/EntityRepository::createNamedNativeQuery()`
* `Doctrine/ORM/Mapping/ClassMetadata::getNamedQuery()`
* `Doctrine/ORM/Mapping/ClassMetadata::getNamedQueries()`
* `Doctrine/ORM/Mapping/ClassMetadata::addNamedQuery()`
* `Doctrine/ORM/Mapping/ClassMetadata::hasNamedQuery()`
* `Doctrine/ORM/Mapping/ClassMetadata::getNamedNativeQuery()`
* `Doctrine/ORM/Mapping/ClassMetadata::getNamedNativeQueries()`
* `Doctrine/ORM/Mapping/ClassMetadata::addNamedNativeQuery()`
* `Doctrine/ORM/Mapping/ClassMetadata::hasNamedNativeQuery()`
* `Doctrine\ORM\Mapping\ClassMetadata::addSqlResultSetMapping()`
* `Doctrine\ORM\Mapping\ClassMetadata::getSqlResultSetMapping()`
* `Doctrine\ORM\Mapping\ClassMetadata::getSqlResultSetMappings()`
* `Doctrine\ORM\Mapping\ClassMetadata::hasSqlResultSetMapping()`
## BC Break: Removed support for entity namespace aliases
The support for namespace aliases has been removed.
Please migrate to using `::class` for referencing classes.
These methods have been removed:
* `Doctrine\ORM\Configuration::addEntityNamespace()`
* `Doctrine\ORM\Configuration::getEntityNamespace()`
* `Doctrine\ORM\Configuration::setEntityNamespaces()`
* `Doctrine\ORM\Configuration::getEntityNamespaces()`
* `Doctrine\ORM\Mapping\AbstractClassMetadataFactory::getFqcnFromAlias()`
* `Doctrine\ORM\ORMException::unknownEntityNamespace()`
## BC Break: Removed same-namespace class name resolution
Support for same-namespace class name resolution in mappings has been removed.
If you're using annotation driver, please migrate to references using `::class`.
If you're using XML driver, please migrate to fully qualified references.
These methods have been removed:
* Doctrine\ORM\Mapping\ClassMetadata::fullyQualifiedClassName()
## BC Break: Removed code generators and related console commands
These console commands have been removed:
* `orm:convert-mapping`
* `orm:generate:entities`
* `orm:generate-repositories`
These classes have been removed:
* `Doctrine\ORM\Tools\EntityGenerator`
* `Doctrine\ORM\Tools\EntityRepositoryGenerator`
The whole Doctrine\ORM\Tools\Export namespace with all its members has been removed as well.
## BC Break: proxies no longer implement `Doctrine\ORM\Proxy\Proxy`
Proxy objects no longer implement `Doctrine\ORM\Proxy\Proxy` nor
`Doctrine\Common\Persistence\Proxy`: instead, they implement
`ProxyManager\Proxy\GhostObjectInterface`.
These related classes have been removed:
* `Doctrine\ORM\Proxy\ProxyFactory` - replaced by `Doctrine\ORM\Proxy\Factory\StaticProxyFactory`
and `Doctrine\ORM\Proxy\Factory\ProxyFactory`
* `Doctrine\ORM\Proxy\Proxy`
* `Doctrine\ORM\Proxy\Autoloader` - we suggest using the composer autoloader instead
* `Doctrine\ORM\Reflection\RuntimePublicReflectionProperty`
These methods have been removed:
* `Doctrine\ORM\Configuration#getProxyDir()`
* `Doctrine\ORM\Configuration#getAutoGenerateProxyClasses()`
* `Doctrine\ORM\Configuration#getProxyNamespace()`
Proxy class names change: the generated proxies now follow
the [`ClassNameInflector`](https://github.com/Ocramius/ProxyManager/blob/2.1.1/src/ProxyManager/Inflector/ClassNameInflector.php)
naming.
Proxies are also always generated if not found: fatal errors due to missing
proxy classes should no longer occur with ORM default settings.
In addition to that, the following changes affect entity lazy-loading semantics:
* `final` methods are now allowed
* `__clone` is no longer called by the ORM
* `__wakeup` is no longer called by the ORM
* `serialize($proxy)` will lead to full recursive proxy initialization: please mitigate
the recursive initialization by implementing
the [`Serializable`](https://secure.php.net/manual/en/class.serializable.php) interface
* `clone $proxy` will lead to full initialization of the cloned instance, not the
original instance
* lazy-loading a detached proxy no longer causes the proxy identifiers to be reset
to `null`
* identifier properties are always set when the ORM produces a proxy instance
* calling a method on a proxy no longer causes proxy lazy-loading if the method does
not access any un-initialized proxy state
* accessing entity private state, even with reflection, will trigger lazy-loading
## BC Break: Removed `Doctrine\ORM\Version`
The `Doctrine\ORM\Version` class is no longer available: please refrain from checking the ORM version at runtime.
## BC Break: Removed `EntityManager#merge()` and `EntityManager#detach()` methods
Merge and detach semantics were a poor fit for the PHP "share-nothing" architecture.
In addition to that, merging/detaching caused multiple issues with data integrity
in the managed entity graph, which was constantly spawning more edge-case bugs/scenarios.
The following API methods were therefore removed:
* `EntityManager#merge()`
* `EntityManager#detach()`
* `UnitOfWork#merge()`
* `UnitOfWork#detach()`
Users are encouraged to migrate `EntityManager#detach()` calls to `EntityManager#clear()`.
In order to maintain performance on batch processing jobs, it is endorsed to enable
the second level cache (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/second-level-cache.html)
on entities that are frequently reused across multiple `EntityManager#clear()` calls.
An alternative to `EntityManager#merge()` is not provided by ORM 3.0, since the merging
semantics should be part of the business domain rather than the persistence domain of an
application. If your application relies heavily on CRUD-alike interactions and/or `PATCH`
restful operations, you should look at alternatives such as [JMSSerializer](https://github.com/schmittjoh/serializer).
## BC Break: Added the final keyword for `EntityManager`
Final keyword has been added to the ``EntityManager::class`` in order to ensure that EntityManager is not used as valid extension point. Valid extension point should be EntityManagerInterface.
## BC Break: ``EntityManagerInterface`` is now used instead of ``EntityManager`` in typehints
`Sequencing\Generator#generate()` now takes ``EntityManagerInterface`` as its first argument instead of ``EntityManager``. If you have any custom generators, please update your code accordingly.
## BC Break: Removed `EntityManager#flush($entity)` and `EntityManager#flush($entities)`
If your code relies on single entity flushing optimisations via
`EntityManager#flush($entity)`, the signature has been changed to
`EntityManager#flush()`.
Said API was affected by multiple data integrity bugs due to the fact
that change tracking was being restricted upon a subset of the managed
entities. The ORM cannot support committing subsets of the managed
entities while also guaranteeing data integrity, therefore this
utility was removed.
The `flush()` semantics remain the same, but the change tracking will be performed
on all entities managed by the unit of work, and not just on the provided
`$entity` or `$entities`, as the parameter is now completely ignored.
The same applies to `UnitOfWork#commit($entity)`, which now is simply
`UnitOfWork#commit()`.
If you would still like to perform batching operations over small `UnitOfWork`
instances, it is suggested to follow these paths instead:
* eagerly use `EntityManager#clear()` in conjunction with a specific second level
cache configuration (see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/second-level-cache.html)
* use an explicit change tracking policy (see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html)
## BC Break: Removed ``YAML`` mapping drivers.
If your code relies on ``YamlDriver`` or ``SimpleYamlDriver``, you **MUST** change to
annotation or XML drivers instead.
## BC Break: Changed methods in ``ClassMetadata``
* ``ClassMetadata::addInheritedProperty``
* ``ClassMetadata::setDiscriminatorColumn``
## BC Break: Removed methods in ``ClassMetadata``
* ``ClassMetadata::getTypeOfField`` (to be removed, part of Common API)
## BC Break: Removed methods in ``ClassMetadata``
* ``ClassMetadata::setTableName`` => Use ``ClassMetadata::setPrimaryTable(['name' => ...])``
* ``ClassMetadata::getFieldMapping`` => Use ``ClassMetadata::getProperty()`` and its methods
* ``ClassMetadata::getQuotedColumnName`` => Use ``ClassMetadata::getProperty()::getQuotedColumnName()``
* ``ClassMetadata::getQuotedTableName``
* ``ClassMetadata::getQuotedJoinTableName``
* ``ClassMetadata::getQuotedIdentifierColumnNames``
* ``ClassMetadata::getIdentifierColumnNames`` => Use ``ClassMetadata::getIdentifierColumns($entityManager)``
* ``ClassMetadata::setVersionMetadata``
* ``ClassMetadata::setVersioned``
* ``ClassMetadata::invokeLifecycleCallbacks``
* ``ClassMetadata::isInheritedField`` => Use ``ClassMetadata::getProperty()::isInherited()``
* ``ClassMetadata::isUniqueField`` => Use ``ClassMetadata::getProperty()::isUnique()``
* ``ClassMetadata::isNullable`` => Use ``ClassMetadata::getProperty()::isNullable()``
* ``ClassMetadata::getTypeOfColumn()`` => Use ``PersisterHelper::getTypeOfColumn()``
## BC Break: Removed ``quoted`` index from table, field and sequence mappings
Quoting is now always called. Implement your own ``Doctrine\ORM\Mapping\NamingStrategy`` to manipulate
your schema, tables and column names to your custom desired naming convention.
## BC Break: Removed ``ClassMetadata::$fieldMappings[$fieldName]['requireSQLConversion']``
ORM Type SQL conversion is now always being applied, minimizing the risks of error prone code in ORM internals
## BC Break: Removed ``ClassMetadata::$columnNames``
If your code relies on this property, you should search/replace from this:
$metadata->columnNames[$fieldName]
To this:
$metadata->getProperty($fieldName)->getColumnName()
## BC Break: Renamed ``ClassMetadata::setIdentifierValues()`` to ``ClassMetadata::assignIdentifier()``
Provides a more meaningful name to method.
## BC Break: Removed ``ClassMetadata::$namespace``
The namespace property in ClassMetadata was only used when using association
classes in the same namespace and it was used to speedup ClassMetadata
creation purposes. Namespace could be easily inferred by asking ``\ReflectionClass``
which was already stored internally.
### BC Break: Removed ``ClassMetadata::$isVersioned``
Switched to a method alternative: ``ClassMetadata::isVersioned()``
## BC Break: Removed ``Doctrine\ORM\Mapping\ClassMetadataInfo``
There was no reason to keep a blank class. All references are now pointing
to ``Doctrine\ORM\Mapping\ClassMetadata``.
## BC Break: Annotations classes namespace change
All Annotations classes got moved from ``Doctrine\ORM\Mapping`` into a more
pertinent namespace ``Doctrine\ORM\Annotation``. This change was done to add
room for Metadata namespace refactoring.
## Minor BC break: Mappings now store ``DBAL\Type`` instances instead of strings
This leads to manual ``ResultSetMapping`` building instances to also hold Types in meta results.
Example:
$rsm->addMetaResult('e ', 'e_discr', 'discr', false, Type::getType('string'));
## Enhancement: Mappings now store their declaring ``ClassMetadata``
Every field, association or embedded now contains a pointer to its declaring ``ClassMetadata``.
## Enhancement: Mappings now store their corresponding table name
Every field, association join column or inline embedded field/association holds a reference to its owning table name.
# Upgrade to 2.6
## Added `Doctrine\ORM\EntityRepository::count()` method
`Doctrine\ORM\EntityRepository::count()` has been added. This new method has different
signature than `Countable::count()` (required parameter) and therefore are not compatible.
If your repository implemented the `Countable` interface, you will have to use
`$repository->count([])` instead and not implement `Countable` interface anymore.
## Minor BC BREAK: `Doctrine\ORM\Tools\Console\ConsoleRunner` is now final
Since it's just an utilitarian class and should not be inherited.
@@ -13,13 +351,17 @@ now has a required parameter `$pathExpr`.
Method `Doctrine\ORM\Query\Parser#isInternalFunction()` was removed because
the distinction between internal function and user defined DQL was removed.
[#6500](https://github.com/doctrine/doctrine2/pull/6500)
[#6500](https://github.com/doctrine/orm/pull/6500)
## Minor BC BREAK: removed `Doctrine\ORM\ORMException#overwriteInternalDQLFunctionNotAllowed()`
Method `Doctrine\ORM\Query\Parser#overwriteInternalDQLFunctionNotAllowed()` was
removed because of the choice to allow users to overwrite internal functions, ie
`AVG`, `SUM`, `COUNT`, `MIN` and `MAX`. [#6500](https://github.com/doctrine/doctrine2/pull/6500)
`AVG`, `SUM`, `COUNT`, `MIN` and `MAX`. [#6500](https://github.com/doctrine/orm/pull/6500)
## Minor BC BREAK: removed $className parameter on `AbstractEntityInheritancePersister#getSelectJoinColumnSQL()`
As `$className` parameter was not used in the method, it was safely removed.
## PHP 7.1 is now required
@@ -35,11 +377,7 @@ As a consequence, automatic cache setup in Doctrine\ORM\Tools\Setup::create*Conf
## Minor BC BREAK: removed `Doctrine\ORM\Query\SqlWalker#walkCaseExpression()`
Method `Doctrine\ORM\Query\SqlWalker#walkCaseExpression()` was unused and part
of the internal API of the ORM, so it was removed. [#5600](https://github.com/doctrine/doctrine2/pull/5600).
## Minor BC BREAK: removed $className parameter on `AbstractEntityInheritancePersister#getSelectJoinColumnSQL()`
As `$className` parameter was not used in the method, it was safely removed.
of the internal API of the ORM, so it was removed. [#5600](https://github.com/doctrine/orm/pull/5600).
## Minor BC BREAK: query cache key time is now a float
@@ -64,8 +402,8 @@ either:
- map those classes as `MappedSuperclass`
## Minor BC BREAK: ``EntityManagerInterface`` instead of ``EntityManager`` in type-hints
As of 2.5, classes requiring the ``EntityManager`` in any method signature will now require
As of 2.5, classes requiring the ``EntityManager`` in any method signature will now require
an ``EntityManagerInterface`` instead.
If you are extending any of the following classes, then you need to check following
signatures:
@@ -158,7 +496,7 @@ the `Doctrine\ORM\Repository\DefaultRepositoryFactory`.
When executing DQL queries with new object expressions, instead of returning DTOs numerically indexes, it will now respect user provided aliases. Consider the following query:
SELECT new UserDTO(u.id,u.name) as user,new AddressDTO(a.street,a.postalCode) as address, a.id as addressId FROM User u INNER JOIN u.addresses a WITH a.isPrimary = true
Previously, your result would be similar to this:
array(
@@ -189,6 +527,7 @@ From now on, the resultset will look like this:
Added way to access the underlying QueryBuilder#from() method's 'indexBy' parameter when using EntityRepository#createQueryBuilder()
# Upgrade to 2.4
## BC BREAK: Compatibility Bugfix in PersistentCollection#matching()
@@ -233,6 +572,7 @@ Now parenthesis are considered, the previous DQL will generate:
SELECT 100 / (2 * 2) FROM my_entity
# Upgrade to 2.3
## Auto Discriminator Map breaks userland implementations with Listener
@@ -302,6 +642,7 @@ Also, following mapping drivers have been deprecated, please use their replaceme
* `Doctrine\ORM\Mapping\Driver\PHPDriver` => `Doctrine\Common\Persistence\Mapping\Driver\PHPDriver`
* `Doctrine\ORM\Mapping\Driver\StaticPHPDriver` => `Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver`
# Upgrade to 2.2
## ResultCache implementation rewritten
@@ -385,6 +726,7 @@ Also, Doctrine 2.2 now is around 10-15% faster than 2.1.
Previously EntityManager#find(null) returned null. It now throws an exception.
# Upgrade to 2.1
## Interface for EntityRepository
@@ -409,6 +751,7 @@ The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory
This is already done inside the ``$config->newDefaultAnnotationDriver``, so everything should automatically work if you are using this method. You can verify if everything still works by executing a console command such as schema-validate that loads all metadata into memory.
# Update from 2.0-BETA3 to 2.0-BETA4
## XML Driver <change-tracking-policy /> element demoted to attribute
@@ -417,6 +760,7 @@ We changed how the XML Driver allows to define the change-tracking-policy. The w
<entity change-tracking-policy="DEFERRED_IMPLICT" />
# Update from 2.0-BETA2 to 2.0-BETA3
## Serialization of Uninitialized Proxies
@@ -479,10 +823,12 @@ don't loose anything through this.
The default allocation size for sequences has been changed from 10 to 1. This step was made
to not cause confusion with users and also because it is partly some kind of premature optimization.
# Update from 2.0-BETA1 to 2.0-BETA2
There are no backwards incompatible changes in this release.
# Upgrade from 2.0-ALPHA4 to 2.0-BETA1
## EntityRepository deprecates access to protected variables
@@ -553,7 +899,6 @@ access all entities.
Xml and Yaml Drivers work as before!
## New inversedBy attribute
It is now *mandatory* that the owning side of a bidirectional association specifies the
@@ -617,7 +962,7 @@ you need to use the following, explicit syntax:
## XML Mapping Driver
The 'inheritance-type' attribute changed to take last bit of ClassMetadata constant names, i.e.
NONE, SINGLE_TABLE, INHERITANCE_TYPE_JOINED
NONE, SINGLE_TABLE, JOINED
## YAML Mapping Driver
@@ -649,6 +994,7 @@ The Collection interface in the Common package has been updated with some missin
that were present only on the default implementation, ArrayCollection. Custom collection
implementations need to be updated to adhere to the updated interface.
# Upgrade from 2.0-ALPHA3 to 2.0-ALPHA4
## CLI Controller changes
@@ -685,6 +1031,8 @@ With new required method AbstractTask::buildDocumentation, its implementation de
database schema without deleting any unused tables, sequences or foreign keys.
* Use "doctrine schema-tool --complete-update" to do a full incremental update of
your schema.
# Upgrade from 2.0-ALPHA2 to 2.0-ALPHA3
This section details the changes made to Doctrine 2.0-ALPHA3 to make it easier for you

View File

@@ -1,4 +1,6 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);
include('doctrine.php');

View File

@@ -1,21 +1,7 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
declare(strict_types=1);
require_once 'Doctrine/Common/ClassLoader.php';

View File

@@ -1,21 +1,6 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
declare(strict_types=1);
use Symfony\Component\Console\Helper\HelperSet;
use Doctrine\ORM\Tools\Console\ConsoleRunner;

View File

@@ -1,3 +0,0 @@
# Version class and file
project.version_class = Doctrine\\ORM\\Version
project.version_file = lib/Doctrine/ORM/Version.php

View File

@@ -38,29 +38,6 @@
</exec>
</target>
<target name="make-release" depends="check-git-checkout-clean,prepare,php">
<replace file="${project.version_file}" token="-DEV" value="" failOnNoReplacements="true" />
<exec executable="${php_executable}" outputproperty="doctrine.current_version" failonerror="true">
<arg value="-r" />
<arg value="require_once '${project.version_file}';echo ${project.version_class}::VERSION;" />
</exec>
<exec executable="${php_executable}" outputproperty="doctrine.next_version" failonerror="true">
<arg value="-r" />
<arg value="$parts = explode('.', str_ireplace(array('-DEV', '-ALPHA', '-BETA'), '', '${doctrine.current_version}'));
if (count($parts) != 3) {
throw new \InvalidArgumentException('Version is assumed in format x.y.z, ${doctrine.current_version} given');
}
$parts[2]++;
echo implode('.', $parts);
" />
</exec>
<git-commit file="${project.version_file}" message="Release ${doctrine.current_version}" />
<git-tag version="${doctrine.current_version}" />
<replace file="${project.version_file}" token="${doctrine.current_version}" value="${doctrine.next_version}-DEV" />
<git-commit file="${project.version_file}" message="Bump version to ${doctrine.next_version}" />
</target>
<target name="check-git-checkout-clean">
<exec executable="git" failonerror="true">
<arg value="diff-index" />

View File

@@ -1,9 +1,19 @@
{
"name": "doctrine/orm",
"type": "library",
"description": "Object-Relational-Mapper for PHP",
"keywords": ["orm", "database"],
"homepage": "http://www.doctrine-project.org",
"description": "PHP object relational mapper (ORM) that sits on top of a powerful database abstraction layer (DBAL). One of its key features is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL). This provides developers with a powerful alternative to SQL that maintains flexibility without requiring unnecessary code duplication.",
"keywords": [
"php",
"orm",
"mysql",
"object",
"data",
"mapper",
"mapping",
"query",
"dql"
],
"homepage": "https://www.doctrine-project.org/projects/orm.html",
"license": "MIT",
"authors": [
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
@@ -12,28 +22,38 @@
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
{"name": "Marco Pivetta", "email": "ocramius@gmail.com"}
],
"support": {
"chat": "https://www.doctrine-project.org/slack",
"docs": "https://www.doctrine-project.org/projects/orm.html",
"email": "doctrine-user@googlegroups.com",
"issues": "https://github.com/doctrine/orm/issues",
"rss": "https://github.com/doctrine/orm/releases.atom",
"source": "https://github.com/doctrine/orm"
},
"config": {
"sort-packages": true
},
"require": {
"php": "^7.1",
"ext-pdo": "*",
"doctrine/annotations": "~1.5",
"php": "^7.3",
"ext-ctype": "*",
"doctrine/annotations": "~1.7",
"doctrine/cache": "~1.6",
"doctrine/collections": "^1.4",
"doctrine/common": "^2.7.1",
"doctrine/dbal": "^2.6",
"doctrine/dbal": "dev-missed-commits",
"doctrine/event-manager": "^1.0",
"doctrine/inflector": "~1.0",
"doctrine/instantiator": "~1.1",
"symfony/console": "~3.0|~4.0"
"doctrine/persistence": "^1.1",
"doctrine/reflection": "^1.0",
"ocramius/package-versions": "^1.1.2",
"ocramius/proxy-manager": "^2.1.1",
"symfony/console": "~4.0|~5.0",
"symfony/var-dumper": "^4.1"
},
"require-dev": {
"doctrine/coding-standard": "^1.0",
"phpunit/phpunit": "^6.5",
"squizlabs/php_codesniffer": "^3.2",
"symfony/yaml": "~3.4|~4.0"
},
"suggest": {
"symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
"doctrine/coding-standard": "^6.0",
"phpstan/phpstan": "^0.11",
"phpunit/phpunit": "^7.0"
},
"autoload": {
"psr-4": { "Doctrine\\ORM\\": "lib/Doctrine/ORM" }
@@ -45,11 +65,6 @@
}
},
"bin": ["bin/doctrine"],
"extra": {
"branch-alias": {
"dev-master": "2.6.x-dev"
}
},
"archive": {
"exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor", "*.swp"]
}

4214
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

4
docs/.gitignore vendored
View File

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

3
docs/.gitmodules vendored
View File

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

View File

@@ -1,4 +1,4 @@
The Doctrine2 documentation is licensed under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US)
The Doctrine2 documentation is licensed under [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US)
Creative Commons Legal Code
@@ -337,7 +337,6 @@ BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
License is not intended to restrict the license of any rights under
applicable law.
Creative Commons Notice
Creative Commons is not a party to this License, and makes no warranty
@@ -359,5 +358,4 @@ Creative Commons Notice
available upon request from time to time. For the avoidance of doubt,
this trademark restriction does not form part of this License.
Creative Commons may be contacted at http://creativecommons.org/.
Creative Commons may be contacted at https://creativecommons.org/.

View File

@@ -1,18 +0,0 @@
# Doctrine ORM Documentation
## How to Generate:
Using Ubuntu 14.04 LTS:
1. Run ./bin/install-dependencies.sh
2. Run ./bin/generate-docs.sh
It will generate the documentation into the build directory of the checkout.
## Theme issues
If you get a "Theme error", check if the `en/_theme` subdirectory is empty,
in which case you will need to run:
1. git submodule init
2. git submodule update

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

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

@@ -1,711 +0,0 @@
What is new in Doctrine ORM 2.5?
================================
This document describes changes between Doctrine ORM 2.4 and 2.5.
It contains a description of all the new features and sections about
behavioral changes and potential backwards compatibility breaks.
Please review this document carefully when updating to Doctrine 2.5.
First note, that with the ORM 2.5 release we are dropping support
for PHP 5.3. We are enforcing this with Composer, servers without
at least PHP 5.4 will not allow installing Doctrine 2.5.
New Features and Improvements
-----------------------------
Events: PostLoad now triggered after associations are loaded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before Doctrine 2.5 if you had an entity with a ``@PostLoad`` event
defined then Doctrine would trigger listeners after the fields were
loaded, but before assocations are available.
- `DDC-54 <http://doctrine-project.org/jira/browse/DDC-54>`_
- `Commit #a90629 <https://github.com/doctrine/doctrine2/commit/a906295c65f1516737458fbee2f6fa96254f27a5>`_
Events: Add API to programatically add event listeners to Entity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When developing third party libraries or decoupled applications
it can be interesting to develop an entity listener without knowing
the entities that require this listener.
You can now attach entity listeners to entities using the
``AttachEntityListenersListener`` class, which is listening to the
``loadMetadata`` event that is fired once for every entity during
metadata generation:
.. code-block:: php
<?php
use Doctrine\ORM\Tools\AttachEntityListenersListener;
use Doctrine\ORM\Events;
$listener = new AttachEntityListenersListener();
$listener->addEntityListener(
'MyProject\Entity\User', 'MyProject\Listener\TimestampableListener',
Events::prePersist, 'onPrePersist'
);
$evm->addEventListener(Events::loadClassMetadata, $listener);
class TimestampableListener
{
public function onPrePersist($event)
{
$entity = $event->getEntity();
$entity->setCreated(new \DateTime('now'));
}
}
Embeddable Objects
~~~~~~~~~~~~~~~~~~
Doctrine now supports creating multiple PHP objects from one database table
implementing a feature called "Embeddable Objects". Next to an ``@Entity``
class you can now define a class that is embeddable into a database table of an
entity using the ``@Embeddable`` annotation. Embeddable objects can never be
saved, updated or deleted on their own, only as part of an entity (called
"root-entity" or "aggregate"). Consequently embeddables don't have a primary
key, they are identified only by their values.
Example of defining and using embeddables classes:
.. code-block:: php
<?php
/** @Entity */
class Product
{
/** @Id @Column(type="integer") @GeneratedValue */
private $id;
/** @Embedded(class = "Money") */
private $price;
}
/** @Embeddable */
class Money
{
/** @Column(type = "decimal") */
private $value;
/** @Column(type = "string") */
private $currency = 'EUR';
}
You can read more on the features of Embeddables objects `in the documentation
<http://docs.doctrine-project.org/en/latest/tutorials/embeddables.html>`_.
This feature was developed by external contributor `Johannes Schmitt
<https://twitter.com/schmittjoh>`_
- `DDC-93 <http://doctrine-project.org/jira/browse/DDC-93>`_
- `Pull Request #835 <https://github.com/doctrine/doctrine2/pull/835>`_
Second-Level-Cache
~~~~~~~~~~~~~~~~~~
Since version 2.0 of Doctrine, fetching the same object twice by primary key
would result in just one query. This was achieved by the identity map pattern
(first-level-cache) that kept entities in memory.
The newly introduced second-level-cache works a bit differently. Instead
of saving objects in memory, it saves them in a fast in-memory cache such
as Memcache, Redis, Riak or MongoDB. Additionally it allows saving the result
of more complex queries than by primary key. Summarized this feature works
like the existing Query result cache, but it is much more powerful.
As an example lets cache an entity Country that is a relation to the User
entity. We always want to display the country, but avoid the additional
query to this table.
.. code-block:: php
<?php
/**
* @Entity
* @Cache(usage="READ_ONLY", region="country_region")
*/
class Country
{
/**
* @Id
* @GeneratedValue
* @Column(type="integer")
*/
protected $id;
/**
* @Column(unique=true)
*/
protected $name;
}
In this example we have specified a caching region name called
``country_region``, which we have to configure now on the EntityManager:
.. code-block:: php
$config = new \Doctrine\ORM\Configuration();
$config->setSecondLevelCacheEnabled();
$cacheConfig = $config->getSecondLevelCacheConfiguration();
$regionConfig = $cacheConfig->getRegionsConfiguration();
$regionConfig->setLifetime('country_region', 3600);
Now Doctrine will first check for the data of any country in the cache
instead of the database.
- `Documentation
<http://docs.doctrine-project.org/en/latest/reference/second-level-cache.html>`_
- `Pull Request #808 <https://github.com/doctrine/doctrine2/pull/808>`_
Criteria API: Support for ManyToMany assocations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We introduced support for querying collections using the `Criteria API
<http://docs.doctrine-project.org/en/latest/reference/working-with-associations.html#filtering-collections>`_
in 2.4. This only worked efficently for One-To-Many assocations, not for
Many-To-Many. With the start of 2.5 also Many-To-Many associations get queried
instead of loading them into memory.
Criteria API: Add new contains() expression
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is now possible to use the Criteria API to check for string contains needle
using ``contains()``. This translates to using a ``column LIKE '%needle%'`` SQL
condition.
.. code-block:: php
<?php
use \Doctrine\Common\Collections\Criteria;
$criteria = Criteria::create()
->where(Criteria::expr()->contains('name', 'Benjamin'));
$users = $repository->matching($criteria);
Criteria API: Support for EXTRA_LAZY
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A collection that is marked as ``fetch="EXTRA_LAZY"`` will now return another
lazy collection when using ``Collection::matching($criteria)``:
.. code-block:: php
<?php
class Post
{
/** @OneToMany(targetEntity="Comment", fetch="EXTRA_LAZY") */
private $comments;
}
$criteria = Criteria::create()
->where(Criteria->expr()->eq("published", 1));
$publishedComments = $post->getComments()->matching($criteria);
echo count($publishedComments);
The lazy criteria currently supports the ``count()`` and ``contains()``
functionality lazily. All other operations of the ``Collection`` interface
trigger a full load of the collection.
This feature was contributed by `Michaël Gallego <https://github.com/bakura10>`_.
- `Pull Request #882 <https://github.com/doctrine/doctrine2/pull/882>`_
- `Pull Request #1032 <https://github.com/doctrine/doctrine2/pull/1032>`_
Mapping: Allow configuring Index flags
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is now possible to control the index flags in the DBAL
schema abstraction from the ORM using metadata. This was possible
only with a schema event listener before.
.. code-block:: php
<?php
/**
* @Table(name="product", indexes={@Index(columns={"description"},flags={"fulltext"})})
*/
class Product
{
private $description;
}
This feature was contributed by `Adrian Olek <https://github.com/adrianolek>`_.
- `Pull Request #973 <https://github.com/doctrine/doctrine2/pull/973>`_
SQLFilter API: Check if a parameter is set
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can now check in your SQLFilter if a parameter was set. This allows
to more easily control which features of a filter to enable or disable.
Extending on the locale example of the documentation:
.. code-block:: php
<?php
class MyLocaleFilter extends SQLFilter
{
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
if (!$targetEntity->reflClass->implementsInterface('LocaleAware')) {
return "";
}
if (!$this->hasParameter('locale')) {
return "";
}
return $targetTableAlias.'.locale = ' . $this->getParameter('locale');
}
}
This feature was contributed by `Miroslav Demovic <https://github.com/mdemo>`_
- `Pull Request #963 <https://github.com/doctrine/doctrine2/pull/963>`_
EXTRA_LAZY Improvements
~~~~~~~~~~~~~~~~~~~~~~~
1. Efficient query when using EXTRA_LAZY and containsKey
When calling ``Collection::containsKey($key)`` on one-to-many and many-to-many
collections using ``indexBy`` and ``EXTRA_LAZY`` a query is now executed to check
for the existance for the item. Prevoiusly this operation was performed in memory
by loading all entities of the collection.
.. code-block:: php
<?php
class User
{
/** @OneToMany(targetEntity="Group", indexBy="id") */
private $groups;
}
if ($user->getGroups()->containsKey($groupId)) {
echo "User is in group $groupId\n";
}
This feature was contributed by `Asmir Mustafic <https://github.com/goetas>`_
- `Pull Request #937 <https://github.com/doctrine/doctrine2/pull/937>`_
2. Add EXTRA_LAZY Support for get() for owning and inverse many-to-many
This was contributed by `Sander Marechal <https://github.com/sandermarechal>`_.
Improve efficiency of One-To-Many EAGER
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When marking a one-to-many association with ``fetch="EAGER"`` it will now
execute one query less than before and work correctly in combination with
``indexBy``.
Better support for EntityManagerInterface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Many of the locations where previously only the ``Doctrine\ORM\EntityManager``
was allowed are now changed to accept the ``EntityManagerInterface`` that was
introduced in 2.4. This allows you to more easily use the decorator pattern
to extend the EntityManager if you need. It's still not replaced everywhere,
so you still have to be careful.
DQL Improvements
~~~~~~~~~~~~~~~~
1. It is now possible to add functions to the ``ORDER BY`` clause in DQL statements:
.. code-block:: php
<?php
$dql = "SELECT u FROM User u ORDER BY CONCAT(u.username, u.name)";
2. Support for functions in ``IS NULL`` expressions:
.. code-block:: php
<?php
$dql = "SELECT u.name FROM User u WHERE MAX(u.name) IS NULL";
3. A ``LIKE`` expression is now suported in ``HAVING`` clause.
4. Subselects are now supported inside a ``NEW()`` expression:
.. code-block:: php
<?php
$dql = "SELECT new UserDTO(u.name, SELECT count(g.id) FROM Group g WHERE g.id = u.id) FROM User u";
5. ``MEMBER OF`` expression now allows to filter for more than one result:
.. code-block:: php
<?php
$dql = "SELECT u FROM User u WHERE :groups MEMBER OF u.groups";
$query = $entityManager->createQuery($dql);
$query->setParameter('groups', array(1, 2, 3));
$users = $query->getResult();
6. Expressions inside ``COUNT()`` now allowed
.. code-block:: php
<?php
$dql = "SELECT COUNT(DISTINCT CONCAT(u.name, u.lastname)) FROM User u";
7. Add support for ``HOUR`` in ``DATE_ADD()``/``DATE_SUB()`` functions
Custom DQL Functions: Add support for factories
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Previously custom DQL functions could only be provided with their
full-qualified class-name, preventing runtime configuration through
dependency injection.
A simplistic approach has been contributed by `Matthieu Napoli
<https://github.com/mnapoli>`_ to pass a callback instead that resolves
the function:
.. code-block:: php
<?php
$config = new \Doctrine\ORM\Configuration();
$config->addCustomNumericFunction(
'IS_PUBLISHED', function($funcName) use ($currentSiteId) {
return new IsPublishedFunction($currentSiteId);
}
);
Query API: WHERE IN Query using a Collection as parameter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When performing a ``WHERE IN`` query for a collection of entities you can
now pass the array collection of entities as a parameter value to the query
object:
.. code-block:: php
<?php
$categories = $rootCategory->getChildren();
$queryBuilder
->select('p')
->from('Product', 'p')
->where('p.category IN (:categories)')
->setParameter('categories', $categories)
;
This feature was contributed by `Michael Perrin
<https://github.com/michaelperrin>`_.
- `Pull Request #590 <https://github.com/doctrine/doctrine2/pull/590>`_
- `DDC-2319 <http://doctrine-project.org/jira/browse/DDC-2319>`_
Query API: Add support for default Query Hints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To configure multiple different features such as custom AST Walker, fetch modes,
locking and other features affecting DQL generation we have had a feature
called "query hints" since version 2.0.
It is now possible to add query hints that are always enabled for every Query:
.. code-block:: php
<?php
$config = new \Doctrine\ORM\Configuration();
$config->setDefaultQueryHints(
'doctrine.customOutputWalker' => 'MyProject\CustomOutputWalker'
);
This feature was contributed by `Artur Eshenbrener
<https://github.com/Strate>`_.
- `Pull Request #863 <https://github.com/doctrine/doctrine2/pull/863>`_
ResultSetMappingBuilder: Add support for Single-Table Inheritance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before 2.5 the ResultSetMappingBuilder did not work with entities
that are using Single-Table-Inheritance. This restriction was lifted
by adding the missing support.
YAML Mapping: Many-To-Many doesnt require join column definition
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In Annotations and XML it was not necessary using conventions for naming
the many-to-many join column names, in YAML it was not possible however.
A many-to-many definition in YAML is now possible using this minimal
definition:
.. code-block:: yaml
manyToMany:
groups:
targetEntity: Group
joinTable:
name: users_groups
Schema Validator Command: Allow to skip sub-checks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Schema Validator command executes two independent checks
for validity of the mappings and if the schema is synchronized
correctly. It is now possible to skip any of the two steps
when executing the command:
::
$ php vendor/bin/doctrine orm:validate-schema --skip-mapping
$ php vendor/bin/doctrine orm:validate-schema --skip-sync
This allows you to write more specialized continuous integration and automation
checks. When no changes are found the command returns the exit code 0
and 1, 2 or 3 when failing because of mapping, sync or both.
EntityGenerator Command: Avoid backups
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When calling the EntityGenerator for an existing entity, Doctrine would
create a backup file every time to avoid losing changes to the code. You
can now skip generating the backup file by passing the ``--no-backup``
flag:
::
$ php vendor/bin/doctrine orm:generate-entities src/ --no-backup
Support for Objects as Identifiers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is now possible to use Objects as identifiers for Entities
as long as they implement the magic method ``__toString()``.
.. code-block:: php
<?php
class UserId
{
private $value;
public function __construct($value)
{
$this->value = $value;
}
public function __toString()
{
return (string)$this->value;
}
}
class User
{
/** @Id @Column(type="userid") */
private $id;
public function __construct(UserId $id)
{
$this->id = $id;
}
}
class UserIdType extends \Doctrine\DBAL\Types\Type
{
// ...
}
Doctrine\DBAL\Types\Type::addType('userid', 'MyProject\UserIdType');
Behavioral Changes (BC Breaks)
------------------------------
NamingStrategy interface changed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``Doctrine\ORM\Mapping\NamingStrategyInterface`` changed slightly
to pass the Class Name of the entity into the join column name generation:
::
- function joinColumnName($propertyName);
+ function joinColumnName($propertyName, $className = null);
It also received a new method for supporting embeddables:
::
public function embeddedFieldToColumnName($propertyName, $embeddedColumnName);
Minor BC BREAK: EntityManagerInterface instead of EntityManager in type-hints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As of 2.5, classes requiring the ``EntityManager`` in any method signature will now require
an ``EntityManagerInterface`` instead.
If you are extending any of the following classes, then you need to check following
signatures:
- ``Doctrine\ORM\Tools\DebugUnitOfWorkListener#dumpIdentityMap(EntityManagerInterface $em)``
- ``Doctrine\ORM\Mapping\ClassMetadataFactory#setEntityManager(EntityManagerInterface $em)``
Minor BC BREAK: Custom Hydrators API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As of 2.5, ``AbstractHydrator`` does not enforce the usage of cache as part of
API, and now provides you a clean API for column information through the method
``hydrateColumnInfo($column)``.
Cache variable being passed around by reference is no longer needed since
Hydrators are per query instantiated since Doctrine 2.4.
- `DDC-3060 <http://doctrine-project.org/jira/browse/DDC-3060>`_
Minor BC BREAK: All non-transient classes in an inheritance must be part of the inheritance map
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As of 2.5, classes, if you define an inheritance map for an inheritance tree, you are required
to map all non-transient classes in that inheritance, including the root of the inheritance.
So far, the root of the inheritance was allowed to be skipped in the inheritance map: this is
not possible anymore, and if you don't plan to persist instances of that class, then you should
either:
- make that class as ``abstract``
- add that class to your inheritance map
If you fail to do so, then a ``Doctrine\ORM\Mapping\MappingException`` will be thrown.
- `DDC-3300 <http://doctrine-project.org/jira/browse/DDC-3300>`_
- `DDC-3503 <http://doctrine-project.org/jira/browse/DDC-3503>`_
Minor BC BREAK: Entity based EntityManager#clear() calls follow cascade detach
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Whenever ``EntityManager#clear()`` method gets called with a given entity class
name, until 2.4, it was only detaching the specific requested entity.
As of 2.5, ``EntityManager`` will follow configured cascades, providing a better
memory management since associations will be garbage collected, optimizing
resources consumption on long running jobs.
Updates on entities scheduled for deletion are no longer processed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In Doctrine 2.4, if you modified properties of an entity scheduled for deletion, UnitOfWork would
produce an ``UPDATE`` statement to be executed right before the ``DELETE`` statement. The entity in question
was therefore present in ``UnitOfWork#entityUpdates``, which means that ``preUpdate`` and ``postUpdate``
listeners were (quite pointlessly) called. In ``preFlush`` listeners, it used to be possible to undo
the scheduled deletion for updated entities (by calling ``persist()`` if the entity was found in both
``entityUpdates`` and ``entityDeletions``). This does not work any longer, because the entire changeset
calculation logic is optimized away.
Minor BC BREAK: Default lock mode changed from LockMode::NONE to null in method signatures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A misconception concerning default lock mode values in method signatures lead to unexpected behaviour
in SQL statements on SQL Server. With a default lock mode of ``LockMode::NONE`` throughout the
method signatures in ORM, the table lock hint ``WITH (NOLOCK)`` was appended to all locking related
queries by default. This could result in unpredictable results because an explicit ``WITH (NOLOCK)``
table hint tells SQL Server to run a specific query in transaction isolation level READ UNCOMMITTED
instead of the default READ COMMITTED transaction isolation level.
Therefore there now is a distinction between ``LockMode::NONE`` and ``null`` to be able to tell
Doctrine whether to add table lock hints to queries by intention or not. To achieve this, the following
method signatures have been changed to declare ``$lockMode = null`` instead of ``$lockMode = LockMode::NONE``:
- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#getSelectSQL()``
- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#load()``
- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#refresh()``
- ``Doctrine\ORM\Decorator\EntityManagerDecorator#find()``
- ``Doctrine\ORM\EntityManager#find()``
- ``Doctrine\ORM\EntityRepository#find()``
- ``Doctrine\ORM\Persisters\BasicEntityPersister#getSelectSQL()``
- ``Doctrine\ORM\Persisters\BasicEntityPersister#load()``
- ``Doctrine\ORM\Persisters\BasicEntityPersister#refresh()``
- ``Doctrine\ORM\Persisters\EntityPersister#getSelectSQL()``
- ``Doctrine\ORM\Persisters\EntityPersister#load()``
- ``Doctrine\ORM\Persisters\EntityPersister#refresh()``
- ``Doctrine\ORM\Persisters\JoinedSubclassPersister#getSelectSQL()``
You should update signatures for these methods if you have subclassed one of the above classes.
Please also check the calling code of these methods in your application and update if necessary.
.. note::
This in fact is really a minor BC BREAK and should not have any affect on database vendors
other than SQL Server because it is the only one that supports and therefore cares about
``LockMode::NONE``. It's really just a FIX for SQL Server environments using ORM.
Minor BC BREAK: __clone method not called anymore when entities are instantiated via metadata API
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As of PHP 5.6, instantiation of new entities is deferred to the
`doctrine/instantiator <https://github.com/doctrine/instantiator>`_ library, which will avoid calling ``__clone``
or any public API on instantiated objects.
BC BREAK: DefaultRepositoryFactory is now final
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Please implement the ``Doctrine\ORM\Repository\RepositoryFactory`` interface instead of extending
the ``Doctrine\ORM\Repository\DefaultRepositoryFactory``.
BC BREAK: New object expression DQL queries now respects user provided aliasing and not return consumed fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When executing DQL queries with new object expressions, instead of returning
DTOs numerically indexes, it will now respect user provided aliases. Consider
the following query:
::
SELECT new UserDTO(u.id,u.name) as user,new AddressDTO(a.street,a.postalCode) as address, a.id as addressId
FROM User u INNER JOIN u.addresses a WITH a.isPrimary = true
Previously, your result would be similar to this:
::
array(
0=>array(
0=>{UserDTO object},
1=>{AddressDTO object},
2=>{u.id scalar},
3=>{u.name scalar},
4=>{a.street scalar},
5=>{a.postalCode scalar},
'addressId'=>{a.id scalar},
),
...
)
From now on, the resultset will look like this:
::
array(
0=>array(
'user'=>{UserDTO object},
'address'=>{AddressDTO object},
'addressId'=>{a.id scalar}
),
...
)

View File

@@ -1,201 +0,0 @@
# -*- coding: utf-8 -*-
#
# Doctrine 2 ORM documentation build configuration file, created by
# sphinx-quickstart on Fri Dec 3 18:10:24 2010.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os, datetime
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.append(os.path.abspath('_exts'))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['configurationblock']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Doctrine 2 ORM'
copyright = u'2010-%y, Doctrine Project Team'.format(datetime.date.today)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2'
# The full version, including alpha/beta/rc tags.
release = '2'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
language = 'en'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'doctrine'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['_theme']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'Doctrine2ORMdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Doctrine2ORM.tex', u'Doctrine 2 ORM Documentation',
u'Doctrine Project Team', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
primary_domain = "dcorm"
def linkcode_resolve(domain, info):
if domain == 'dcorm':
return 'http://'
return None

View File

@@ -4,18 +4,18 @@ Advanced field value conversion using custom mapping types
.. sectionauthor:: Jan Sorgalla <jsorgalla@googlemail.com>
When creating entities, you sometimes have the need to transform field values
before they are saved to the database. In Doctrine you can use Custom Mapping
before they are saved to the database. In Doctrine you can use Custom Mapping
Types to solve this (see: :ref:`reference-basic-mapping-custom-mapping-types`).
There are several ways to achieve this: converting the value inside the Type
class, converting the value on the database-level or a combination of both.
This article describes the third way by implementing the MySQL specific column
type `Point <http://dev.mysql.com/doc/refman/5.5/en/gis-class-point.html>`_.
type `Point <https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html>`_.
The ``Point`` type is part of the `Spatial extension <http://dev.mysql.com/doc/refman/5.5/en/spatial-extensions.html>`_
The ``Point`` type is part of the `Spatial extension <https://dev.mysql.com/doc/refman/8.0/en/spatial-extensions.html>`_
of MySQL and enables you to store a single location in a coordinate space by
using x and y coordinates. You can use the Point type to store a
using x and y coordinates. You can use the Point type to store a
longitude/latitude pair to represent a geographic location.
The entity
@@ -29,23 +29,25 @@ The entity class:
.. code-block:: php
<?php
namespace Geo\Entity;
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @ORM\Entity
*/
class Location
{
/**
* @Column(type="point")
* @ORM\Column(type="point")
*
* @var \Geo\ValueObject\Point
*/
private $point;
/**
* @Column(type="string")
* @ORM\Column(type="string")
*
* @var string
*/
@@ -84,7 +86,7 @@ The entity class:
}
}
We use the custom type ``point`` in the ``@Column`` docblock annotation of the
We use the custom type ``point`` in the ``@Column`` docblock annotation of the
``$point`` field. We will create this custom mapping type in the next chapter.
The point class:
@@ -92,7 +94,7 @@ The point class:
.. code-block:: php
<?php
namespace Geo\ValueObject;
class Point
@@ -192,11 +194,11 @@ object into a string representation before saving to the database (in the
``convertToDatabaseValue`` method) and back into an object after fetching the
value from the database (in the ``convertToPHPValue`` method).
The format of the string representation format is called `Well-known text (WKT)
<http://en.wikipedia.org/wiki/Well-known_text>`_. The advantage of this format
is, that it is both human readable and parsable by MySQL.
The format of the string representation format is called
`Well-known text (WKT) <https://en.wikipedia.org/wiki/Well-known_text>`_.
The advantage of this format is, that it is both human readable and parsable by MySQL.
Internally, MySQL stores geometry values in a binary format that is not
Internally, MySQL stores geometry values in a binary format that is not
identical to the WKT format. So, we need to let MySQL transform the WKT
representation into its internal format.
@@ -204,19 +206,19 @@ This is where the ``convertToPHPValueSQL`` and ``convertToDatabaseValueSQL``
methods come into play.
This methods wrap a sql expression (the WKT representation of the Point) into
MySQL functions `PointFromText <http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#function_pointfromtext>`_
and `AsText <http://dev.mysql.com/doc/refman/5.5/en/functions-to-convert-geometries-between-formats.html#function_astext>`_
MySQL functions `ST_PointFromText <https://dev.mysql.com/doc/refman/8.0/en/gis-wkt-functions.html#function_st-pointfromtext>`_
and `ST_AsText <https://dev.mysql.com/doc/refman/8.0/en/gis-format-conversion-functions.html#function_st-astext>`_
which convert WKT strings to and from the internal format of MySQL.
.. note::
When using DQL queries, the ``convertToPHPValueSQL`` and
When using DQL queries, the ``convertToPHPValueSQL`` and
``convertToDatabaseValueSQL`` methods only apply to identification variables
and path expressions in SELECT clauses. Expressions in WHERE clauses are
and path expressions in SELECT clauses. Expressions in WHERE clauses are
**not** wrapped!
If you want to use Point values in WHERE clauses, you have to implement a
:doc:`user defined function <dql-user-defined-functions>` for
:doc:`user defined function <dql-user-defined-functions>` for
``PointFromText``.
Example usage
@@ -252,5 +254,5 @@ Example usage
$query = $em->createQuery("SELECT l FROM Geo\Entity\Location WHERE l.address = '1600 Amphitheatre Parkway, Mountain View, CA'");
$location = $query->getSingleResult();
/* @var Geo\ValueObject\Point */
/** @var Geo\ValueObject\Point $point */
$point = $location->getPoint();

View File

@@ -32,29 +32,28 @@ Our entities look like:
.. code-block:: php
<?php
namespace Bank\Entities;
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @ORM\Entity
*/
class Account
{
/** @Id @GeneratedValue @Column(type="integer") */
/** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
private $id;
/** @Column(type="string", unique=true) */
/** @ORM\Column(type="string", unique=true) */
private $no;
/**
* @OneToMany(targetEntity="Entry", mappedBy="account", cascade={"persist"})
*/
/** @ORM\OneToMany(targetEntity="Entry", mappedBy="account", cascade={"persist"}) */
private $entries;
/**
* @Column(type="integer")
*/
/** @ORM\Column(type="integer") */
private $maxCredit = 0;
public function __construct($no, $maxCredit = 0)
{
$this->no = $no;
@@ -62,32 +61,28 @@ Our entities look like:
$this->entries = new \Doctrine\Common\Collections\ArrayCollection();
}
}
/**
* @Entity
* @ORM\Entity
*/
class Entry
{
/** @Id @GeneratedValue @Column(type="integer") */
/** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
private $id;
/**
* @ManyToOne(targetEntity="Account", inversedBy="entries")
*/
/** @ORM\ManyToOne(targetEntity="Account", inversedBy="entries") */
private $account;
/**
* @Column(type="integer")
*/
/** @ORM\Column(type="integer") */
private $amount;
public function __construct($account, $amount)
{
$this->account = $account;
$this->amount = $amount;
// more stuff here, from/to whom, stated reason, execution date and such
}
public function getAmount()
{
return $this->amount;
@@ -178,7 +173,7 @@ relation with this method:
public function addEntry($amount)
{
$this->assertAcceptEntryAllowed($amount);
$e = new Entry($this, $amount);
$this->entries[] = $e;
return $e;
@@ -196,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->setExpectedException("Exception");
$account->addEntry(-1000);
}
@@ -266,19 +261,19 @@ entries collection) we want to add an aggregate field called
class Account
{
/**
* @Column(type="integer")
* @ORM\Column(type="integer")
*/
private $balance = 0;
public function getBalance()
{
return $this->balance;
}
public function addEntry($amount)
{
$this->assertAcceptEntryAllowed($amount);
$e = new Entry($this, $amount);
$this->entries[] = $e;
$this->balance += $amount;
@@ -309,20 +304,20 @@ 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('Bank\Entities\Account', $accId);
// request 2 account
$account2 = $em->find('Bank\Entities\Account', $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
SUM over all entries amounts yields -400. A violation of our max
credit rule.
You can use both optimistic or pessimistic locking to save-guard
You can use both optimistic or pessimistic locking to safe-guard
your aggregate fields against this kind of race-conditions. Reading
Eric Evans DDD carefully he mentions that the "Aggregate Root"
(Account in our example) needs a locking mechanism.
@@ -334,7 +329,7 @@ Optimistic locking is as easy as adding a version column:
<?php
class Account
{
/** @Column(type="integer") @Version */
/** @ORM\Column(type="integer") @ORM\Version */
private $version;
}
@@ -350,7 +345,7 @@ the database using a FOR UPDATE.
<?php
use Doctrine\DBAL\LockMode;
$account = $em->find('Bank\Entities\Account', $accId, LockMode::PESSIMISTIC_READ);
Keeping Updates and Deletes in Sync
@@ -373,4 +368,3 @@ the related objects that make up an aggregate value. Finally I
showed how you can ensure that your aggregate fields do not get out
of sync due to race-conditions and concurrent access.

View File

@@ -95,7 +95,7 @@ class name. Now the new type can be used when mapping columns:
<?php
class MyPersistentClass
{
/** @Column(type="mytype") */
/** @ORM\Column(type="mytype") */
private $field;
}

View File

@@ -3,45 +3,48 @@ Persisting the Decorator Pattern
.. sectionauthor:: Chris Woodford <chris.woodford@gmail.com>
This recipe will show you a simple example of how you can use
This recipe will show you a simple example of how you can use
Doctrine 2 to persist an implementation of the
`Decorator Pattern <http://en.wikipedia.org/wiki/Decorator_pattern>`_
`Decorator Pattern <https://en.wikipedia.org/wiki/Decorator_pattern>`_
Component
---------
The ``Component`` class needs to be persisted, so it's going to
be an ``Entity``. As the top of the inheritance hierarchy, it's going
to have to define the persistent inheritance. For this example, we
will use Single Table Inheritance, but Class Table Inheritance
would work as well. In the discriminator map, we will define two
concrete subclasses, ``ConcreteComponent`` and ``ConcreteDecorator``.
The ``Component`` class needs to be persisted, so it's going to
be an ``Entity``. As the top of the inheritance hierarchy, it's going
to have to define the persistent inheritance. For this example, we
will use Single Table Inheritance, but Class Table Inheritance
would work as well. In the discriminator map, we will define two
concrete subclasses, ``ConcreteComponent`` and ``ConcreteDecorator``.
.. code-block:: php
<?php
namespace Test;
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"cc" = "Test\Component\ConcreteComponent",
"cd" = "Test\Decorator\ConcreteDecorator"})
* @ORM\Entity
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="discr", type="string")
* @ORM\DiscriminatorMap({
* "cc" = "Test\Component\ConcreteComponent",
* "cd" = "Test\Decorator\ConcreteDecorator"
* })
*/
abstract class Component
{
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
* @ORM\Id @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/** @Column(type="string", nullable=true) */
/** @ORM\Column(type="string", nullable=true) */
protected $name;
/**
* Get id
* @return integer $id
@@ -50,7 +53,7 @@ concrete subclasses, ``ConcreteComponent`` and ``ConcreteDecorator``.
{
return $this->id;
}
/**
* Set name
* @param string $name
@@ -59,7 +62,7 @@ concrete subclasses, ``ConcreteComponent`` and ``ConcreteDecorator``.
{
$this->name = $name;
}
/**
* Get name
* @return string $name
@@ -68,33 +71,34 @@ concrete subclasses, ``ConcreteComponent`` and ``ConcreteDecorator``.
{
return $this->name;
}
}
ConcreteComponent
-----------------
The ``ConcreteComponent`` class is pretty simple and doesn't do much
more than extend the abstract ``Component`` class (only for the
The ``ConcreteComponent`` class is pretty simple and doesn't do much
more than extend the abstract ``Component`` class (only for the
purpose of keeping this example simple).
.. code-block:: php
<?php
namespace Test\Component;
use Doctrine\ORM\Annotation as ORM;
use Test\Component;
/** @Entity */
/** @ORM\Entity */
class ConcreteComponent extends Component
{}
Decorator
---------
The ``Decorator`` class doesn't need to be persisted, but it does
need to define an association with a persisted ``Entity``. We can
The ``Decorator`` class doesn't need to be persisted, but it does
need to define an association with a persisted ``Entity``. We can
use a ``MappedSuperclass`` for this.
.. code-block:: php
@@ -102,17 +106,19 @@ use a ``MappedSuperclass`` for this.
<?php
namespace Test;
/** @MappedSuperclass */
use Doctrine\ORM\Annotation as ORM;
/** @ORM\MappedSuperclass */
abstract class Decorator extends Component
{
/**
* @OneToOne(targetEntity="Test\Component", cascade={"all"})
* @JoinColumn(name="decorates", referencedColumnName="id")
* @ORM\OneToOne(targetEntity="Test\Component", cascade={"all"})
* @ORM\JoinColumn(name="decorates", referencedColumnName="id")
*/
protected $decorates;
/**
* initialize the decorator
* @param Component $c
@@ -121,7 +127,7 @@ use a ``MappedSuperclass`` for this.
{
$this->setDecorates($c);
}
/**
* (non-PHPdoc)
* @see Test.Component::getName()
@@ -130,7 +136,7 @@ use a ``MappedSuperclass`` for this.
{
return 'Decorated ' . $this->getDecorates()->getName();
}
/**
* the component being decorated
* @return Component
@@ -139,7 +145,7 @@ use a ``MappedSuperclass`` for this.
{
return $this->decorates;
}
/**
* sets the component being decorated
* @param Component $c
@@ -148,52 +154,53 @@ use a ``MappedSuperclass`` for this.
{
$this->decorates = $c;
}
}
All operations on the ``Decorator`` (i.e. persist, remove, etc) will
cascade from the ``Decorator`` to the ``Component``. This means that
when we persist a ``Decorator``, Doctrine will take care of
persisting the chain of decorated objects for us. A ``Decorator`` can
be treated exactly as a ``Component`` when it comes time to
All operations on the ``Decorator`` (i.e. persist, remove, etc) will
cascade from the ``Decorator`` to the ``Component``. This means that
when we persist a ``Decorator``, Doctrine will take care of
persisting the chain of decorated objects for us. A ``Decorator`` can
be treated exactly as a ``Component`` when it comes time to
persisting it.
The ``Decorator's`` constructor accepts an instance of a
``Component``, as defined by the ``Decorator`` pattern. The
setDecorates/getDecorates methods have been defined as protected to
hide the fact that a ``Decorator`` is decorating a ``Component`` and
keeps the ``Component`` interface and the ``Decorator`` interface
The ``Decorator's`` constructor accepts an instance of a
``Component``, as defined by the ``Decorator`` pattern. The
setDecorates/getDecorates methods have been defined as protected to
hide the fact that a ``Decorator`` is decorating a ``Component`` and
keeps the ``Component`` interface and the ``Decorator`` interface
identical.
To illustrate the intended result of the ``Decorator`` pattern, the
getName() method has been overridden to append a string to the
To illustrate the intended result of the ``Decorator`` pattern, the
getName() method has been overridden to append a string to the
``Component's`` getName() method.
ConcreteDecorator
-----------------
The final class required to complete a simple implementation of the
Decorator pattern is the ``ConcreteDecorator``. In order to further
illustrate how the ``Decorator`` can alter data as it moves through
the chain of decoration, a new field, "special", has been added to
this class. The getName() has been overridden and appends the value
of the getSpecial() method to its return value.
The final class required to complete a simple implementation of the
Decorator pattern is the ``ConcreteDecorator``. In order to further
illustrate how the ``Decorator`` can alter data as it moves through
the chain of decoration, a new field, "special", has been added to
this class. The getName() has been overridden and appends the value
of the getSpecial() method to its return value.
.. code-block:: php
<?php
namespace Test\Decorator;
use Doctrine\ORM\Annotation as ORM;
use Test\Decorator;
/** @Entity */
/** @ORM\Entity */
class ConcreteDecorator extends Decorator
{
/** @Column(type="string", nullable=true) */
/** @ORM\Column(type="string", nullable=true) */
protected $special;
/**
* Set special
* @param string $special
@@ -202,7 +209,7 @@ of the getSpecial() method to its return value.
{
$this->special = $special;
}
/**
* Get special
* @return string $special
@@ -211,7 +218,7 @@ of the getSpecial() method to its return value.
{
return $this->special;
}
/**
* (non-PHPdoc)
* @see Test.Component::getName()
@@ -219,55 +226,55 @@ of the getSpecial() method to its return value.
public function getName()
{
return '[' . $this->getSpecial()
. '] ' . parent::getName();
. '] ' . parent::getName();
}
}
Examples
--------
Here is an example of how to persist and retrieve your decorated
Here is an example of how to persist and retrieve your decorated
objects
.. code-block:: php
<?php
use Test\Component\ConcreteComponent,
Test\Decorator\ConcreteDecorator;
// assumes Doctrine 2 is configured and an instance of
// an EntityManager is available as $em
// create a new concrete component
$c = new ConcreteComponent();
$c->setName('Test Component 1');
$em->persist($c); // assigned unique ID = 1
// create a new concrete decorator
$c = new ConcreteComponent();
$c->setName('Test Component 2');
$d = new ConcreteDecorator($c);
$d->setSpecial('Really');
$em->persist($d);
$em->persist($d);
// assigns c as unique ID = 2, and d as unique ID = 3
$em->flush();
$c = $em->find('Test\Component', 1);
$d = $em->find('Test\Component', 3);
echo get_class($c);
// prints: Test\Component\ConcreteComponent
echo $c->getName();
// prints: Test Component 1
echo get_class($d)
// prints: Test Component 1
echo get_class($d)
// prints: Test\Component\ConcreteDecorator
echo $d->getName();
// prints: [Really] Decorated Test Component 2

View File

@@ -14,7 +14,7 @@ In Doctrine 1 the DQL language was not implemented using a real
parser. This made modifications of the DQL by the user impossible.
Doctrine 2 in contrast has a real parser for the DQL language,
which transforms the DQL statement into an
`Abstract Syntax Tree <http://en.wikipedia.org/wiki/Abstract_syntax_tree>`_
`Abstract Syntax Tree <https://en.wikipedia.org/wiki/Abstract_syntax_tree>`_
and generates the appropriate SQL statement for it. Since this
process is deterministic Doctrine heavily caches the SQL that is
generated from any given DQL query, which reduces the performance
@@ -28,7 +28,6 @@ generating the SQL statement.
There are two types of custom tree walkers that you can hook into
the DQL parser:
- An output walker. This one actually generates the SQL, and there
is only ever one of them. We implemented the default SqlWalker
implementation for it.
@@ -40,7 +39,6 @@ Now this is all awfully technical, so let me come to some use-cases
fast to keep you motivated. Using walker implementation you can for
example:
- Modify the AST to generate a Count Query to be used with a
paginator for any given DQL query.
- Modify the Output Walker to generate vendor-specific SQL
@@ -88,7 +86,7 @@ API would look for this use-case:
$pageNum = 1;
$query = $em->createQuery($dql);
$query->setFirstResult( ($pageNum-1) * 20)->setMaxResults(20);
$totalResults = Paginate::count($query);
$results = $query->getResult();
@@ -101,12 +99,12 @@ The ``Paginate::count(Query $query)`` looks like:
{
static public function count(Query $query)
{
/* @var $countQuery Query */
/** @var Query $countQuery */
$countQuery = clone $query;
$countQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('DoctrineExtensions\Paginate\CountSqlWalker'));
$countQuery->setFirstResult(null)->setMaxResults(null);
return $countQuery->getSingleScalarResult();
}
}
@@ -130,20 +128,20 @@ implementation is:
{
$parent = null;
$parentName = null;
foreach ($this->_getQueryComponents() as $dqlAlias => $qComp) {
foreach ($this->getQueryComponents() as $dqlAlias => $qComp) {
if ($qComp['parent'] === null && $qComp['nestingLevel'] == 0) {
$parent = $qComp;
$parentName = $dqlAlias;
break;
}
}
$pathExpression = new PathExpression(
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $parentName,
$parent['metadata']->getSingleIdentifierFieldName()
);
$pathExpression->type = PathExpression::TYPE_STATE_FIELD;
$AST->selectClause->selectExpressions = array(
new SelectExpression(
new AggregateExpression('count', $pathExpression, true), null
@@ -196,7 +194,7 @@ SQL\_NO\_CACHE on those queries that need it:
public function walkSelectClause($selectClause)
{
$sql = parent::walkSelectClause($selectClause);
if ($this->getQuery()->getHint('mysqlWalker.sqlNoCache') === true) {
if ($selectClause->isDistinct) {
$sql = str_replace('SELECT DISTINCT', 'SELECT DISTINCT SQL_NO_CACHE', $sql);
@@ -204,7 +202,7 @@ SQL\_NO\_CACHE on those queries that need it:
$sql = str_replace('SELECT', 'SELECT SQL_NO_CACHE', $sql);
}
}
return $sql;
}
}
@@ -214,4 +212,3 @@ understanding of the DQL Parser and Walkers, but may offer your
huge benefits with using vendor specific features. This would still
allow you write DQL queries instead of NativeQueries to make use of
vendor specific features.

View File

@@ -17,11 +17,10 @@ and gain access to vendor specific functionalities using the
``EntityManager#createNativeQuery()`` API as described in
the :doc:`Native Query <../reference/native-sql>` chapter.
The DQL Parser has hooks to register functions that can then be
used in your DQL queries and transformed into SQL, allowing to
extend Doctrines Query capabilities to the vendors strength. This
post explains the Used-Defined Functions API (UDF) of the Dql
post explains the User-Defined Functions API (UDF) of the Dql
Parser and shows some examples to give you some hints how you would
extend DQL.
@@ -45,7 +44,7 @@ configuration:
$config->addCustomStringFunction($name, $class);
$config->addCustomNumericFunction($name, $class);
$config->addCustomDatetimeFunction($name, $class);
$em = EntityManager::create($dbParams, $config);
The ``$name`` is the name the function will be referred to in the
@@ -70,7 +69,7 @@ methods, which are quite handy in my opinion:
Date Diff
---------
`Mysql's DateDiff function <http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_datediff>`_
`Mysql's DateDiff function <https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_datediff>`_
takes two dates as argument and calculates the difference in days
with ``date1-date2``.
@@ -96,7 +95,7 @@ discuss it step by step:
// (1)
public $firstDateExpression = null;
public $secondDateExpression = null;
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER); // (2)
@@ -106,7 +105,7 @@ discuss it step by step:
$this->secondDateExpression = $parser->ArithmeticPrimary(); // (6)
$parser->match(Lexer::T_CLOSE_PARENTHESIS); // (3)
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return 'DATEDIFF(' .
@@ -164,7 +163,7 @@ Date Add
Often useful it the ability to do some simple date calculations in
your DQL query using
`MySql's DATE\_ADD function <http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-add>`_.
`MySql's DATE_ADD function <https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-add>`_.
I'll skip the blah and show the code for this function:
@@ -180,28 +179,28 @@ I'll skip the blah and show the code for this function:
public $firstDateExpression = null;
public $intervalExpression = null;
public $unit = null;
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->firstDateExpression = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA);
$parser->match(Lexer::T_IDENTIFIER);
$this->intervalExpression = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_IDENTIFIER);
/* @var $lexer Lexer */
/** @var Lexer $lexer */
$lexer = $parser->getLexer();
$this->unit = $lexer->token['value'];
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return 'DATE_ADD(' .
@@ -246,6 +245,4 @@ vendor sql functions and extend the DQL languages scope.
Code for this Extension to DQL and other Doctrine Extensions can be
found
`in my Github DoctrineExtensions repository <http://github.com/beberlei/DoctrineExtensions>`_.
`in the GitHub DoctrineExtensions repository <https://github.com/beberlei/DoctrineExtensions>`_.

View File

@@ -12,12 +12,14 @@ this working.
Merging entity into an EntityManager
------------------------------------
In Doctrine an entity objects has to be "managed" by an EntityManager to be
updateable. Entities saved into the session are not managed in the next request
In Doctrine, an entity objects has to be "managed" by an EntityManager to be
updated. Entities saved into the session are not managed in the next request
anymore. This means that you have to register these entities with an
EntityManager again if you want to change them or use them as part of
references between other entities. You can achieve this by calling
``EntityManager#merge()``.
references between other entities.
It is a good idea to avoid storing entities in serialized formats such as
``$_SESSION``: instead, store the entity identifiers or raw data.
For a representative User object the code to get turn an instance from
the session into a managed Doctrine object looks like this:
@@ -26,43 +28,28 @@ the session into a managed Doctrine object looks like this:
<?php
require_once 'bootstrap.php';
$em = GetEntityManager(); // creates an EntityManager
$em = GetEntityManager(); // creates an EntityManager
session_start();
if (isset($_SESSION['user']) && $_SESSION['user'] instanceof User) {
$user = $_SESSION['user'];
$user = $em->merge($user);
if (isset($_SESSION['user'])) {
$user = $em->find(User::class, $_SESSION['user']);
if (! $user instanceof User) {
// user not found in the database
$_SESSION['user'] = null;
}
}
.. note::
Serializing entities into the session
-------------------------------------
A frequent mistake is not to get the merged user object from the return
value of ``EntityManager#merge()``. The entity object passed to merge is
not necessarily the same object that is returned from the method.
Serializing entity into the session
-----------------------------------
Entities that are serialized into the session normally contain references to
other entities as well. Think of the user entity has a reference to his
articles, groups, photos or many other different entities. If you serialize
this object into the session then you don't want to serialize the related
entities as well. This is why you should call ``EntityManager#detach()`` on this
object or implement the __sleep() magic method on your entity.
.. code-block:: php
<?php
require_once 'bootstrap.php';
$em = GetEntityManager(); // creates an EntityManager
$user = $em->find("User", 1);
$em->detach($user);
$_SESSION['user'] = $user;
.. note::
When you called detach on your objects they get "unmanaged" with that
entity manager. This means you cannot use them as part of write operations
during ``EntityManager#flush()`` anymore in this request.
Serializing entities in the session means serializing also all associated
entities and collections. While this might look like a quick solution in
simple applications, you will encounter problems due to the fact that the
data in the session is stale.
In order to prevent working with stale data, try saving only minimal
information about your entities in your session, without storing entire
entity objects. Should you need the full information of an object, so it
is suggested to re-query the database, which is usually the most
authoritative source of information in typical PHP applications.

View File

@@ -6,7 +6,7 @@ Implementing ArrayAccess for Domain Objects
This recipe will show you how to implement ArrayAccess for your
domain objects in order to allow more uniform access, for example
in templates. In these examples we will implement ArrayAccess on a
`Layer Supertype <http://martinfowler.com/eaaCatalog/layerSupertype.html>`_
`Layer Supertype <https://martinfowler.com/eaaCatalog/layerSupertype.html>`_
for all our domain objects.
Option 1
@@ -16,7 +16,6 @@ In this implementation we will make use of PHPs highly dynamic
nature to dynamically access properties of a subtype in a supertype
at runtime. Note that this implementation has 2 main caveats:
- It will not work with private fields
- It will not go through any getters/setters
@@ -28,15 +27,15 @@ at runtime. Note that this implementation has 2 main caveats:
public function offsetExists($offset) {
return isset($this->$offset);
}
public function offsetSet($offset, $value) {
$this->$offset = $value;
}
public function offsetGet($offset) {
return $this->$offset;
}
public function offsetUnset($offset) {
$this->$offset = null;
}
@@ -50,7 +49,6 @@ Again we use PHPs dynamic nature to invoke methods on a subtype
from a supertype at runtime. This implementation has the following
caveats:
- It relies on a naming convention
- The semantics of offsetExists can differ
- offsetUnset will not work with typehinted setters
@@ -65,15 +63,15 @@ caveats:
$value = $this->{"get$offset"}();
return $value !== null;
}
public function offsetSet($offset, $value) {
$this->{"set$offset"}($value);
}
public function offsetGet($offset) {
return $this->{"get$offset"}();
}
public function offsetUnset($offset) {
$this->{"set$offset"}(null);
}
@@ -95,18 +93,17 @@ exception (i.e. BadMethodCallException).
public function offsetExists($offset) {
// option 1 or option 2
}
public function offsetSet($offset, $value) {
throw new BadMethodCallException("Array access of class " . get_class($this) . " is read-only!");
}
public function offsetGet($offset) {
// option 1 or option 2
}
public function offsetUnset($offset) {
throw new BadMethodCallException("Array access of class " . get_class($this) . " is read-only!");
}
}

View File

@@ -7,7 +7,7 @@ The NOTIFY change-tracking policy is the most effective
change-tracking policy provided by Doctrine but it requires some
boilerplate code. This recipe will show you how this boilerplate
code should look like. We will implement it on a
`Layer Supertype <http://martinfowler.com/eaaCatalog/layerSupertype.html>`_
`Layer Supertype <https://martinfowler.com/eaaCatalog/layerSupertype.html>`_
for all our domain objects.
Implementing NotifyPropertyChanged
@@ -24,15 +24,15 @@ implement the ``NotifyPropertyChanged`` interface from the
<?php
use Doctrine\Common\NotifyPropertyChanged;
use Doctrine\Common\PropertyChangedListener;
abstract class DomainObject implements NotifyPropertyChanged
{
private $listeners = array();
public function addPropertyChangedListener(PropertyChangedListener $listener) {
$this->listeners[] = $listener;
}
/** Notifies listeners of a change. */
protected function onPropertyChanged($propName, $oldValue, $newValue) {
if ($this->listeners) {
@@ -50,12 +50,12 @@ listeners:
.. code-block:: php
<?php
// Mapping not shown, either in annotations, xml or yaml as usual
// Mapping not shown, either in annotations or xml as usual
class MyEntity extends DomainObject
{
private $data;
// ... other fields as usual
public function setData($data) {
if ($data != $this->data) { // check: is it actually modified?
$this->onPropertyChanged('data', $this->data, $data);
@@ -69,4 +69,3 @@ not mandatory but recommended. That way you can avoid unnecessary
updates and also have full control over when you consider a
property changed.

View File

@@ -1,78 +0,0 @@
Implementing Wakeup or Clone
============================
.. sectionauthor:: Roman Borschel (roman@code-factory.org)
As explained in the
`restrictions for entity classes in the manual <http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/architecture.html#entities>`_,
it is usually not allowed for an entity to implement ``__wakeup``
or ``__clone``, because Doctrine makes special use of them.
However, it is quite easy to make use of these methods in a safe
way by guarding the custom wakeup or clone code with an entity
identity check, as demonstrated in the following sections.
Safely implementing \_\_wakeup
------------------------------
To safely implement ``__wakeup``, simply enclose your
implementation code in an identity check as follows:
.. code-block:: php
<?php
class MyEntity
{
private $id; // This is the identifier of the entity.
//...
public function __wakeup()
{
// If the entity has an identity, proceed as normal.
if ($this->id) {
// ... Your code here as normal ...
}
// otherwise do nothing, do NOT throw an exception!
}
//...
}
Safely implementing \_\_clone
-----------------------------
Safely implementing ``__clone`` is pretty much the same:
.. code-block:: php
<?php
class MyEntity
{
private $id; // This is the identifier of the entity.
//...
public function __clone()
{
// If the entity has an identity, proceed as normal.
if ($this->id) {
// ... Your code here as normal ...
}
// otherwise do nothing, do NOT throw an exception!
}
//...
}
Summary
-------
As you have seen, it is quite easy to safely make use of
``__wakeup`` and ``__clone`` in your entities without adding any
really Doctrine-specific or Doctrine-dependant code.
These implementations are possible and safe because when Doctrine
invokes these methods, the entities never have an identity (yet).
Furthermore, it is possibly a good idea to check for the identity
in your code anyway, since it's rarely the case that you want to
unserialize or clone an entity with no identity.

View File

@@ -1,140 +0,0 @@
Integrating with CodeIgniter
============================
This is recipe for using Doctrine 2 in your
`CodeIgniter <http://www.codeigniter.com>`_ framework.
.. note::
This might not work for all CodeIgniter versions and may require
slight adjustments.
Here is how to set it up:
Make a CodeIgniter library that is both a wrapper and a bootstrap
for Doctrine 2.
Setting up the file structure
-----------------------------
Here are the steps:
- Add a php file to your system/application/libraries folder
called Doctrine.php. This is going to be your wrapper/bootstrap for
the D2 entity manager.
- Put the Doctrine folder (the one that contains Common, DBAL, and
ORM) inside that same libraries folder.
- Your system/application/libraries folder now looks like this:
system/applications/libraries -Doctrine -Doctrine.php -index.html
- If you want, open your config/autoload.php file and autoload
your Doctrine library.
<?php $autoload['libraries'] = array('doctrine');
Creating your Doctrine CodeIgniter library
------------------------------------------
Now, here is what your Doctrine.php file should look like.
Customize it to your needs.
.. code-block:: php
<?php
use Doctrine\Common\ClassLoader,
Doctrine\ORM\Configuration,
Doctrine\ORM\EntityManager,
Doctrine\Common\Cache\ArrayCache,
Doctrine\DBAL\Logging\EchoSQLLogger;
class Doctrine {
public $em = null;
public function __construct()
{
// load database configuration from CodeIgniter
require_once APPPATH.'config/database.php';
// Set up class loading. You could use different autoloaders, provided by your favorite framework,
// if you want to.
require_once APPPATH.'libraries/Doctrine/Common/ClassLoader.php';
$doctrineClassLoader = new ClassLoader('Doctrine', APPPATH.'libraries');
$doctrineClassLoader->register();
$entitiesClassLoader = new ClassLoader('models', rtrim(APPPATH, "/" ));
$entitiesClassLoader->register();
$proxiesClassLoader = new ClassLoader('Proxies', APPPATH.'models/proxies');
$proxiesClassLoader->register();
// Set up caches
$config = new Configuration;
$cache = new ArrayCache;
$config->setMetadataCacheImpl($cache);
$driverImpl = $config->newDefaultAnnotationDriver(array(APPPATH.'models/Entities'));
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCacheImpl($cache);
$config->setQueryCacheImpl($cache);
// Proxy configuration
$config->setProxyDir(APPPATH.'/models/proxies');
$config->setProxyNamespace('Proxies');
// Set up logger
$logger = new EchoSQLLogger;
$config->setSQLLogger($logger);
$config->setAutoGenerateProxyClasses( TRUE );
// Database connection information
$connectionOptions = array(
'driver' => 'pdo_mysql',
'user' => $db['default']['username'],
'password' => $db['default']['password'],
'host' => $db['default']['hostname'],
'dbname' => $db['default']['database']
);
// Create EntityManager
$this->em = EntityManager::create($connectionOptions, $config);
}
}
Please note that this is a development configuration; for a
production system you'll want to use a real caching system like
APC, get rid of EchoSqlLogger, and turn off
autoGenerateProxyClasses.
For more details, consult the
`Doctrine 2 Configuration documentation <http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/configuration.html>`_.
Now to use it
-------------
Whenever you need a reference to the entity manager inside one of
your controllers, views, or models you can do this:
.. code-block:: php
<?php
$em = $this->doctrine->em;
That's all there is to it. Once you get the reference to your
EntityManager do your Doctrine 2.0 voodoo as normal.
Note: If you do not choose to autoload the Doctrine library, you
will need to put this line before you get a reference to it:
.. code-block:: php
<?php
$this->load->library('doctrine');
Good luck!

View File

@@ -43,13 +43,16 @@ entities:
.. code-block:: php
<?php
/** @Entity */
use Doctrine\ORM\Annotation as ORM;
/** @ORM\Entity */
class Article
{
const STATUS_VISIBLE = 'visible';
const STATUS_INVISIBLE = 'invisible';
/** @Column(type="string") */
/** @ORM\Column(type="string") */
private $status;
public function setStatus($status)
@@ -67,10 +70,13 @@ the **columnDefinition** attribute.
.. code-block:: php
<?php
/** @Entity */
use Doctrine\ORM\Annotation as ORM;
/** @ORM\Entity */
class Article
{
/** @Column(type="string", columnDefinition="ENUM('visible', 'invisible')") */
/** @ORM\Column(type="string", columnDefinition="ENUM('visible', 'invisible')") */
private $status;
}
@@ -131,10 +137,13 @@ Then in your entity you can just use this type:
.. code-block:: php
<?php
/** @Entity */
use Doctrine\ORM\Annotation as ORM;
/** @ORM\Entity */
class Article
{
/** @Column(type="enumvisibility") */
/** @ORM\Column(type="enumvisibility") */
private $status;
}

View File

@@ -68,7 +68,7 @@ An Invoice entity
namespace Acme\InvoiceModule\Entity;
use Doctrine\ORM\Mapping AS ORM;
use Doctrine\ORM\Mapping as ORM;
use Acme\InvoiceModule\Model\InvoiceSubjectInterface;
/**
@@ -139,4 +139,3 @@ bundles, keeping them usable by themselves, but still being able to
define relationships between different objects. By using this method,
I've found my bundles end up being easier to maintain independently.

View File

@@ -23,31 +23,32 @@ appropriate autoloaders.
.. code-block:: php
<?php
namespace DoctrineExtensions;
use \Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping;
class TablePrefix
{
protected $prefix = '';
public function __construct($prefix)
{
$this->prefix = (string) $prefix;
}
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
if (!$classMetadata->isInheritanceTypeSingleTable() || $classMetadata->getName() === $classMetadata->rootEntityName) {
$classMetadata->setPrimaryTable([
'name' => $this->prefix . $classMetadata->getTableName()
]);
if ($classMetadata->inheritanceType !== Mapping\InheritanceType::SINGLE_TABLE ||
$classMetadata->getName() === $classMetadata->rootEntityName) {
$classMetadata->setTableName($this->prefix . $classMetadata->getTableName());
}
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY && $mapping['isOwningSide']) {
foreach ($classMetadata->associationMappings as $fieldName => $mapping) {
if ($mapping['type'] == Mapping\ClassMetadata::MANY_TO_MANY && $mapping['isOwningSide']) {
$mappedTableName = $mapping['joinTable']['name'];
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
}
@@ -68,19 +69,17 @@ before the prefix has been set.
If you set this listener up, be aware that you will need
to clear your caches and drop then recreate your database schema.
.. code-block:: php
<?php
// $connectionOptions and $config set earlier
$evm = new \Doctrine\Common\EventManager;
// Table Prefix
$tablePrefix = new \DoctrineExtensions\TablePrefix('prefix_');
$evm->addEventListener(\Doctrine\ORM\Events::loadClassMetadata, $tablePrefix);
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm);

View File

@@ -3,7 +3,7 @@ Strategy-Pattern
This recipe will give you a short introduction on how to design
similar entities without using expensive (i.e. slow) inheritance
but with not more than \* the well-known strategy pattern \* event
but with not more than *the well-known strategy pattern* event
listeners
Scenario / Problem
@@ -12,7 +12,6 @@ Scenario / Problem
Given a Content-Management-System, we probably want to add / edit
some so-called "blocks" and "panels". What are they for?
- A block might be a registration form, some text content, a table
with information. A good example might also be a small calendar.
- A panel is by definition a block that can itself contain blocks.
@@ -23,7 +22,6 @@ So, in this scenario, when building your CMS, you will surely add
lots of blocks and panels to your pages and you will find yourself
highly uncomfortable because of the following:
- Every existing page needs to know about the panels it contains -
therefore, you'll have an association to your panels. But if you've
got several types of panels - what do you do? Add an association to
@@ -58,7 +56,6 @@ the middle of your page, for example).
Such an interface could look like this:
.. code-block:: php
<?php
@@ -87,12 +84,12 @@ Such an interface could look like this:
* @return \Zend_View_Helper_Interface
*/
public function setView(\Zend_View_Interface $view);
/**
* @return \Zend_View_Interface
*/
public function getView();
/**
* Renders this strategy. This method will be called when the user
* displays the site.
@@ -100,7 +97,7 @@ Such an interface could look like this:
* @return string
*/
public function renderFrontend();
/**
* Renders the backend of this block. This method will be called when
* a user tries to reconfigure this block instance.
@@ -118,21 +115,21 @@ Such an interface could look like this:
* @return array
*/
public function getRequiredPanelTypes();
/**
* Determines whether a Block is able to use a given type or not
* @param string $typeName The typename
* @return boolean
*/
public function canUsePanelType($typeName);
public function setBlockEntity(AbstractBlock $block);
public function getBlockEntity();
}
As you can see, we have a method "setBlockEntity" which ties a potential strategy to an object of type AbstractBlock. This type will simply define the basic behaviour of our blocks and could potentially look something like this:
.. code-block:: php
<?php
@@ -155,7 +152,7 @@ As you can see, we have a method "setBlockEntity" which ties a potential strateg
* that is used for this blockitem. (This string (!) value will be persisted by Doctrine 2)
*
* This is a doctrine field, so make sure that you use an @column annotation or setup your
* yaml or xml files correctly
* xml files correctly
* @var string
*/
protected $strategyClassName;
@@ -177,7 +174,7 @@ As you can see, we have a method "setBlockEntity" which ties a potential strateg
public function getStrategyClassName() {
return $this->strategyClassName;
}
/**
* Returns the instantiated strategy
*
@@ -186,7 +183,7 @@ As you can see, we have a method "setBlockEntity" which ties a potential strateg
public function getStrategyInstance() {
return $this->strategyInstance;
}
/**
* Sets the strategy this block / panel should work as. Make sure that you've used
* this method before persisting the block!
@@ -213,28 +210,28 @@ This might look like this:
.. code-block:: php
<?php
use \Doctrine\ORM,
\Doctrine\Common;
use Doctrine\ORM,
Doctrine\Common;
/**
* The BlockStrategyEventListener will initialize a strategy after the
* block itself was loaded.
*/
class BlockStrategyEventListener implements Common\EventSubscriber {
protected $view;
public function __construct(\Zend_View_Interface $view) {
$this->view = $view;
}
public function getSubscribedEvents() {
return array(ORM\Events::postLoad);
}
public function postLoad(ORM\Event\LifecycleEventArgs $args) {
$blockItem = $args->getEntity();
// Both blocks and panels are instances of Block\AbstractBlock
if ($blockItem instanceof Block\AbstractBlock) {
$strategy = $blockItem->getStrategyClassName();
@@ -251,4 +248,3 @@ This might look like this:
In this example, even some variables are set - like a view object
or a specific configuration object.

View File

@@ -15,7 +15,6 @@ What we offer are hooks to execute any kind of validation.
perform validations in value setters or any other method of your
entities that are used in your code.
Entities can register lifecycle event methods with Doctrine that
are called on different occasions. For validation we would need to
hook into the events called before persisting and updating. Even
@@ -36,12 +35,12 @@ is allowed to:
public function assertCustomerAllowedBuying()
{
$orderLimit = $this->customer->getOrderLimit();
$amount = 0;
foreach ($this->orderLines as $line) {
$amount += $line->getAmount();
}
if ($amount > $orderLimit) {
throw new CustomerOrderLimitExceededException();
}
@@ -58,14 +57,17 @@ First Annotations:
.. code-block:: php
<?php
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @HasLifecycleCallbacks
* @ORM\Entity
* @ORM\HasLifecycleCallbacks
*/
class Order
{
/**
* @PrePersist @PreUpdate
* @ORM\PrePersist @ORM\PreUpdate
*/
public function assertCustomerAllowedBuying() {}
}
@@ -77,15 +79,12 @@ In XML Mappings:
<doctrine-mapping>
<entity name="Order">
<lifecycle-callbacks>
<lifecycle-callback type="prePersist" method="assertCustomerallowedBuying" />
<lifecycle-callback type="preUpdate" method="assertCustomerallowedBuying" />
<lifecycle-callback type="prePersist" method="assertCustomerAllowedBuying" />
<lifecycle-callback type="preUpdate" method="assertCustomerAllowedBuying" />
</lifecycle-callbacks>
</entity>
</doctrine-mapping>
YAML needs some little change yet, to allow multiple lifecycle
events for one method, this will happen before Beta 1 though.
Now validation is performed whenever you call
``EntityManager#persist($order)`` or when you call
``EntityManager#flush()`` and an order is about to be updated. Any
@@ -99,21 +98,24 @@ validation callbacks.
.. code-block:: php
<?php
use Doctrine\ORM\Annotation as ORM;
class Order
{
/**
* @PrePersist @PreUpdate
* @ORM\PrePersist @ORM\PreUpdate
*/
public function validate()
{
if (!($this->plannedShipDate instanceof DateTime)) {
throw new ValidateException();
}
if ($this->plannedShipDate->format('U') < time()) {
throw new ValidateException();
}
if ($this->customer == null) {
throw new OrderRequiresCustomerException();
}
@@ -134,4 +136,4 @@ instances. This was already discussed in the previous blog post on
the Versionable extension, which requires another type of event
called "onFlush".
Further readings: :doc:`Lifecycle Events <../reference/events>`
Further readings: :ref:`reference-events-lifecycle-events`

View File

@@ -1,7 +1,7 @@
Working with DateTime Instances
===============================
There are many nitty gritty details when working with PHPs DateTime instances. You have know their inner
There are many nitty gritty details when working with PHPs DateTime instances. You have to know their inner
workings pretty well not to make mistakes with date handling. This cookbook entry holds several
interesting pieces of information on how to work with PHP DateTime instances in Doctrine 2.
@@ -15,10 +15,13 @@ these comparisons are always made **BY REFERENCE**. That means the following cha
.. code-block:: php
<?php
/** @Entity */
use Doctrine\ORM\Annotation as ORM;
/** @ORM\Entity */
class Article
{
/** @Column(type="datetime") */
/** @ORM\Column(type="datetime") */
private $updated;
public function setUpdated()
@@ -61,7 +64,7 @@ to manage this mess,
however let me crush your expectations fast. There is not a single database out there (supported by Doctrine 2)
that supports timezones correctly. Correctly here means that you can cover all the use-cases that
can come up with timezones. If you don't believe me you should read up on `Storing DateTime
in Databases <http://derickrethans.nl/storing-date-time-in-database.html>`_.
in Databases <https://derickrethans.nl/storing-date-time-in-database.html>`_.
The problem is simple. Not a single database vendor saves the timezone, only the differences to UTC.
However with frequent daylight saving and political timezone changes you can have a UTC offset that moves
@@ -110,7 +113,7 @@ the UTC time at the time of the booking and the timezone the event happened in.
$converted = \DateTime::createFromFormat(
$platform->getDateTimeFormatString(),
$value,
self::$utc ? self::$utc : self::$utc = new \DateTimeZone('UTC')
self::getUtc()
);
if (! $converted) {
@@ -123,6 +126,11 @@ the UTC time at the time of the booking and the timezone the event happened in.
return $converted;
}
private static function getUtc()
{
return self::$utc ? self::$utc : self::$utc = new \DateTimeZone('UTC');
}
}
This database type makes sure that every DateTime instance is always saved in UTC, relative
@@ -141,7 +149,6 @@ code before bootstrapping the ORM:
Type::overrideType('datetime', UTCDateTimeType::class);
Type::overrideType('datetimetz', UTCDateTimeType::class);
To be able to transform these values
back into their real timezone you have to save the timezone in a separate field of the entity
requiring timezoned datetimes:
@@ -149,17 +156,20 @@ requiring timezoned datetimes:
.. code-block:: php
<?php
namespace Shipping;
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @ORM\Entity
*/
class Event
{
/** @Column(type="datetime") */
/** @ORM\Column(type="datetime") */
private $created;
/** @Column(type="string") */
/** @ORM\Column(type="string") */
private $timezone;
/**

View File

@@ -1,10 +1,8 @@
Welcome to Doctrine 2 ORM's documentation!
==========================================
ORM Documentation
=================
The Doctrine documentation is comprised of tutorials, a reference section and
cookbook articles that explain different parts of the Object Relational mapper.
Doctrine DBAL and Doctrine Common both have their own documentation.
The Doctrine ORM documentation is comprised of tutorials, a reference section and
cookbook articles that explain different parts of the Object Relational Mapper.
Getting Help
------------
@@ -13,119 +11,14 @@ 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 <http://groups.google.com/group/doctrine-user>`_
- Internet Relay Chat (IRC) in #doctrine on Freenode
- Report a bug on `JIRA <http://www.doctrine-project.org/jira>`_.
- 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 `Twitter <https://twitter.com/search/%23doctrine2>`_ with ``#doctrine2``
- On `StackOverflow <http://stackoverflow.com/questions/tagged/doctrine2>`_
If you need more structure over the different topics you can browse the :doc:`table
of contents <toc>`.
- On `StackOverflow <https://stackoverflow.com/questions/tagged/doctrine-orm>`_
Getting Started
---------------
* **Tutorial**:
:doc:`Getting Started with Doctrine <tutorials/getting-started>`
* **Setup**:
:doc:`Installation & Configuration <reference/configuration>`
Mapping Objects onto a Database
-------------------------------
* **Mapping**:
:doc:`Objects <reference/basic-mapping>` |
:doc:`Associations <reference/association-mapping>` |
:doc:`Inheritance <reference/inheritance-mapping>`
* **Drivers**:
:doc:`Docblock Annotations <reference/annotations-reference>` |
:doc:`XML <reference/xml-mapping>` |
:doc:`YAML <reference/yaml-mapping>` |
:doc:`PHP <reference/php-mapping>`
Working with Objects
--------------------
* **Basic Reference**:
:doc:`Entities <reference/working-with-objects>` |
:doc:`Associations <reference/working-with-associations>` |
:doc:`Events <reference/events>`
* **Query Reference**:
:doc:`DQL <reference/dql-doctrine-query-language>` |
:doc:`QueryBuilder <reference/query-builder>` |
:doc:`Native SQL <reference/native-sql>`
* **Internals**:
:doc:`Internals explained <reference/unitofwork>` |
:doc:`Associations <reference/unitofwork-associations>`
Advanced Topics
---------------
* :doc:`Architecture <reference/architecture>`
* :doc:`Advanced Configuration <reference/advanced-configuration>`
* :doc:`Limitations and known issues <reference/limitations-and-known-issues>`
* :doc:`Commandline Tools <reference/tools>`
* :doc:`Transactions and Concurrency <reference/transactions-and-concurrency>`
* :doc:`Filters <reference/filters>`
* :doc:`NamingStrategy <reference/namingstrategy>`
* :doc:`Improving Performance <reference/improving-performance>`
* :doc:`Caching <reference/caching>`
* :doc:`Partial Objects <reference/partial-objects>`
* :doc:`Change Tracking Policies <reference/change-tracking-policies>`
* :doc:`Best Practices <reference/best-practices>`
* :doc:`Metadata Drivers <reference/metadata-drivers>`
* :doc:`Batch Processing <reference/batch-processing>`
* :doc:`Second Level Cache <reference/second-level-cache>`
Tutorials
---------
* :doc:`Indexed associations <tutorials/working-with-indexed-associations>`
* :doc:`Extra Lazy Associations <tutorials/extra-lazy-associations>`
* :doc:`Composite Primary Keys <tutorials/composite-primary-keys>`
* :doc:`Ordered associations <tutorials/ordered-associations>`
* :doc:`Pagination <tutorials/pagination>`
* :doc:`Override Field/Association Mappings In Subclasses <tutorials/override-field-association-mappings-in-subclasses>`
* :doc:`Embeddables <tutorials/embeddables>`
Changelogs
----------
* :doc:`Migration to 2.5 <changelog/migration_2_5>`
Cookbook
--------
* **Patterns**:
:doc:`Aggregate Fields <cookbook/aggregate-fields>` |
:doc:`Decorator Pattern <cookbook/decorator-pattern>` |
:doc:`Strategy Pattern <cookbook/strategy-cookbook-introduction>`
* **DQL Extension Points**:
:doc:`DQL Custom Walkers <cookbook/dql-custom-walkers>` |
:doc:`DQL User-Defined-Functions <cookbook/dql-user-defined-functions>`
* **Implementation**:
:doc:`Array Access <cookbook/implementing-arrayaccess-for-domain-objects>` |
:doc:`Notify ChangeTracking Example <cookbook/implementing-the-notify-changetracking-policy>` |
:doc:`Using Wakeup Or Clone <cookbook/implementing-wakeup-or-clone>` |
:doc:`Working with DateTime <cookbook/working-with-datetime>` |
:doc:`Validation <cookbook/validation-of-entities>` |
:doc:`Entities in the Session <cookbook/entities-in-session>` |
:doc:`Keeping your Modules independent <cookbook/resolve-target-entity-listener>`
* **Integration into Frameworks/Libraries**
:doc:`CodeIgniter <cookbook/integrating-with-codeigniter>`
* **Hidden Gems**
:doc:`Prefixing Table Name <cookbook/sql-table-prefixes>`
* **Custom Datatypes**
:doc:`MySQL Enums <cookbook/mysql-enums>`
:doc:`Advanced Field Value Conversion <cookbook/advanced-field-value-conversion-using-custom-mapping-types>`
.. include:: toc.rst
The best way to get started is with the :doc:`Getting Started with Doctrine <tutorials/getting-started>` tutorial.
Use the sidebar to browse other tutorials and documentation for the Doctrine PHP ORM.

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

@@ -9,17 +9,18 @@ steps of configuration.
.. code-block:: php
<?php
use Doctrine\ORM\EntityManager,
Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Configuration;
use Doctrine\Common\Proxy\ProxyFactory;
// ...
if ($applicationMode == "development") {
$cache = new \Doctrine\Common\Cache\ArrayCache;
} else {
$cache = new \Doctrine\Common\Cache\ApcCache;
$cache = new \Doctrine\Common\Cache\ApcuCache;
}
$config = new Configuration;
$config->setMetadataCacheImpl($cache);
$driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities');
@@ -27,18 +28,17 @@ steps of configuration.
$config->setQueryCacheImpl($cache);
$config->setProxyDir('/path/to/myproject/lib/MyProject/Proxies');
$config->setProxyNamespace('MyProject\Proxies');
if ($applicationMode == "development") {
$config->setAutoGenerateProxyClasses(true);
} else {
$config->setAutoGenerateProxyClasses(false);
$config->setAutoGenerateProxyClasses($applicationMode === 'development')
if ('development' === $applicationMode) {
$config->setAutoGenerateProxyClasses(ProxyFactory::AUTOGENERATE_EVAL);
}
$connectionOptions = array(
$connectionOptions = [
'driver' => 'pdo_sqlite',
'path' => 'database.sqlite'
);
];
$em = EntityManager::create($connectionOptions, $config);
.. note::
@@ -50,9 +50,8 @@ steps of configuration.
conversions with the query cache. These 2 caches require only an
absolute minimum of memory yet they heavily improve the runtime
performance of Doctrine. The recommended cache driver to use with
Doctrine is `APC <http://www.php.net/apc>`_. APC provides you with
an opcode-cache (which is highly recommended anyway) and a very
fast in-memory cache storage that you can use for the metadata and
Doctrine is `APCu <https://php.net/apcu>`_. APCu provides you with
a very fast in-memory cache storage that you can use for the metadata and
query caches as seen in the previous code snippet.
Configuration Options
@@ -61,30 +60,32 @@ Configuration Options
The following sections describe all the configuration options
available on a ``Doctrine\ORM\Configuration`` instance.
Proxy Directory (***REQUIRED***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proxy Directory
~~~~~~~~~~~~~~~
.. code-block:: php
<?php
$config->setProxyDir($dir);
$config->getProxyDir();
Gets or sets the directory where Doctrine generates any proxy
Sets the directory where Doctrine generates any proxy
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***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Setting the proxy target directory will also implicitly cause a
call to ``Doctrine\ORM\Configuration#setAutoGenerateProxyClasses()``
with a value of ``Doctrine\Common\Proxy\ProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS``.
Proxy Namespace
~~~~~~~~~~~~~~~
.. code-block:: php
<?php
$config->setProxyNamespace($namespace);
$config->getProxyNamespace();
Gets or sets the namespace to use for generated proxy classes. For
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.
@@ -103,16 +104,13 @@ classes.
There are currently 4 available implementations:
- ``Doctrine\ORM\Mapping\Driver\AnnotationDriver``
- ``Doctrine\ORM\Mapping\Driver\XmlDriver``
- ``Doctrine\ORM\Mapping\Driver\YamlDriver``
- ``Doctrine\ORM\Mapping\Driver\DriverChain``
Throughout the most part of this manual the AnnotationDriver is
used in the examples. For information on the usage of the XmlDriver
or YamlDriver please refer to the dedicated chapters
``XML Mapping`` and ``YAML Mapping``.
please refer to the dedicated chapters ``XML Mapping``.
The annotation driver can be configured with a factory method on
the ``Doctrine\ORM\Configuration``:
@@ -141,7 +139,7 @@ Metadata Cache (***RECOMMENDED***)
Gets or sets the cache implementation to use for caching metadata
information, that is, all the information you supply via
annotations, xml or yaml, so that they do not need to be parsed and
annotations or xml, so that they do not need to be parsed and
loaded from scratch on every single request which is a waste of
resources. The cache implementation must implement the
``Doctrine\Common\Cache\Cache`` interface.
@@ -150,8 +148,6 @@ Usage of a metadata cache is highly recommended.
The recommended implementations for production are:
- ``Doctrine\Common\Cache\ApcCache``
- ``Doctrine\Common\Cache\ApcuCache``
- ``Doctrine\Common\Cache\MemcacheCache``
- ``Doctrine\Common\Cache\XcacheCache``
@@ -182,8 +178,6 @@ Usage of a query cache is highly recommended.
The recommended implementations for production are:
- ``Doctrine\Common\Cache\ApcCache``
- ``Doctrine\Common\Cache\ApcuCache``
- ``Doctrine\Common\Cache\MemcacheCache``
- ``Doctrine\Common\Cache\XcacheCache``
@@ -209,8 +203,8 @@ implementation that logs to the standard output using ``echo`` and
``var_dump`` can be found at
``Doctrine\DBAL\Logging\EchoSQLLogger``.
Auto-generating Proxy Classes (***OPTIONAL***)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Auto-generating Proxy Classes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Proxy classes can either be generated manually through the Doctrine
Console or automatically at runtime by Doctrine. The configuration
@@ -223,65 +217,89 @@ option that controls this behavior is:
Possible values for ``$mode`` are:
- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_NEVER``
Never autogenerate a proxy. You will need to generate the proxies
manually, for this use the Doctrine Console like so:
.. code-block:: php
$ ./doctrine orm:generate-proxies
When you do this in a development environment,
be aware that you may get class/file not found errors if certain proxies
are not yet generated. You may also get failing lazy-loads if new
methods were added to the entity class that are not yet in the proxy class.
In such a case, simply use the Doctrine Console to (re)generate the
proxy classes.
- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_ALWAYS``
Always generates a new proxy in every request and writes it to disk.
- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS``
- ``Doctrine\Common\Proxy\ProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS``
Generate the proxy class when the proxy file does not exist.
This strategy causes a file exists call whenever any proxy is
used the first time in a request.
This strategy can potentially cause disk access.
Note that autoloading will be attempted before falling back
to generating a proxy class: if an already existing proxy class
is found, then no file write operations will be performed.
- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_EVAL``
- ``Doctrine\Common\Proxy\ProxyFactory::AUTOGENERATE_EVAL``
Generate the proxy classes and evaluate them on the fly via eval(),
Generate the proxy classes and evaluate them on the fly via ``eval()``,
avoiding writing the proxies to disk.
This strategy is only sane for development.
This strategy is only sane for development and long running
processes.
In a production environment, it is highly recommended to use
AUTOGENERATE_NEVER to allow for optimal performances. The other
options are interesting in development environment.
- ``Doctrine\Common\Proxy\ProxyFactory::AUTOGENERATE_NEVER``
This flag is deprecated, and is an alias
of ``Doctrine\Common\Proxy\ProxyFactory::AUTOGENERATE_EVAL``
- ``Doctrine\Common\Proxy\ProxyFactory::AUTOGENERATE_ALWAYS``
This flag is deprecated, and is an alias
of ``Doctrine\Common\Proxy\ProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS``
Before v2.4, ``setAutoGenerateProxyClasses`` would accept a boolean
value. This is still possible, ``FALSE`` being equivalent to
AUTOGENERATE_NEVER and ``TRUE`` to AUTOGENERATE_ALWAYS.
Manually generating Proxy Classes for performance
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
While the ORM can generate proxy classes when required, it is suggested
to not let this happen for production environments, as it has a major
impact on your application's performance.
In a production environment, it is highly recommended to use
``Doctrine\Common\Proxy\ProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS``
in combination with a well-configured
`composer class autoloader<https://getcomposer.org/doc/01-basic-usage.md#autoloading>`_.
Here is an example of such setup:
.. code-block:: json
{
"autoload": {
"psr-4": {
"MyProject\\": "path/to/project/sources/",
"GeneratedProxies\\": "path/to/generated/proxies/"
}
}
}
You would then configure the ORM to use the ``"GeneratedProxies"``
and the ``"path/to/generated/proxies/"`` for the proxy classes:
.. code-block:: php
<?php
$config->setProxyDir('path/to/generated/proxies/');
$config->setProxyNamespace('GeneratedProxies');
To make sure proxies are never generated by Doctrine, you'd forcefully
generate them during deployment operations:
.. code-block:: sh
$ ./vendor/bin/doctrine orm:generate-proxies
$ composer dump-autoload
Development vs Production Configuration
---------------------------------------
You should code your Doctrine2 bootstrapping with two different
runtime models in mind. There are some serious benefits of using
APC or Memcache in production. In development however this will
APCu or Memcache in production. In development however this will
frequently give you fatal errors, when you change your entities and
the cache still keeps the outdated metadata. That is why we
recommend the ``ArrayCache`` for development.
Furthermore you should have the Auto-generating Proxy Classes
option to true in development and to false in production. If this
option is set to ``TRUE`` it can seriously hurt your script
performance if several proxy classes are re-generated during script
execution. Filesystem calls of that magnitude can even slower than
all the database queries Doctrine issues. Additionally writing a
proxy sets an exclusive file lock which can cause serious
performance bottlenecks in systems with regular concurrent
requests.
Furthermore you should disable the Auto-generating Proxy Classes
option in production.
Connection Options
------------------
@@ -292,7 +310,7 @@ instance of ``Doctrine\DBAL\Connection``. If an array is passed it
is directly passed along to the DBAL Factory
``Doctrine\DBAL\DriverManager::getConnection()``. The DBAL
configuration is explained in the
`DBAL section <./../../../../../projects/doctrine-dbal/en/latest/reference/configuration.html>`_.
`DBAL section <https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/configuration.html>`_.
Proxy Objects
-------------
@@ -330,16 +348,17 @@ identifier. You could simply do this:
<?php
// $em instanceof EntityManager, $cart instanceof MyProject\Model\Cart
// $itemId comes from somewhere, probably a request parameter
$item = $em->getReference('MyProject\Model\Item', $itemId);
$item = $em->getReference(\MyProject\Model\Item::class, $itemId);
$cart->addItem($item);
Here, we added an Item to a Cart without loading the Item from the
database. If you invoke any method on the Item instance, it would
fully initialize its state transparently from the database. Here
$item is actually an instance of the proxy class that was generated
for the Item class but your code does not need to care. In fact it
**should not care**. Proxy objects should be transparent to your
code.
Here, we added an ``Item`` to a ``Cart`` without loading the Item from the
database.
If you access any persistent state that isn't yet available in the ``Item``
instance, the proxying mechanism would fully initialize the object's state
transparently from the database.
Here ``$item`` is actually an instance of the proxy class that was generated
for the ``Item`` class but your code does not need to care. In fact it
**should not care**. Proxy objects should be transparent to your code.
Association proxies
~~~~~~~~~~~~~~~~~~~
@@ -347,7 +366,7 @@ Association proxies
The second most important situation where Doctrine uses proxy
objects is when querying for objects. Whenever you query for an
object that has a single-valued association to another object that
is configured LAZY, without joining that association in the same
is configured ``LAZY``, without joining that association in the same
query, Doctrine puts proxy objects in place where normally the
associated object would be. Just like other proxies it will
transparently initialize itself on first access.
@@ -359,61 +378,12 @@ transparently initialize itself on first access.
This will override the 'fetch' option specified in the mapping for
that association, but only for that query.
Generating Proxy classes
~~~~~~~~~~~~~~~~~~~~~~~~
In a production environment, it is highly recommended to use
``AUTOGENERATE_NEVER`` to allow for optimal performances.
However you will be required to generate the proxies manually
using the Doctrine Console:
.. code-block:: php
$ ./doctrine orm:generate-proxies
The other options are interesting in development environment:
- ``AUTOGENERATE_ALWAYS`` will require you to create and configure
a proxy directory. Proxies will be generated and written to file
on each request, so any modification to your code will be acknowledged.
- ``AUTOGENERATE_FILE_NOT_EXISTS`` will not overwrite an existing
proxy file. If your code changes, you will need to regenerate the
proxies manually.
- ``AUTOGENERATE_EVAL`` will regenerate each proxy on each request,
but without writing them to disk.
Autoloading Proxies
-------------------
When you deserialize proxy objects from the session or any other storage
it is necessary to have an autoloading mechanism in place for these classes.
For implementation reasons Proxy class names are not PSR-0 compliant. This
means that you have to register a special autoloader for these classes:
.. code-block:: php
<?php
use Doctrine\Common\Proxy\Autoloader;
$proxyDir = "/path/to/proxies";
$proxyNamespace = "MyProxies";
Autoloader::register($proxyDir, $proxyNamespace);
If you want to execute additional logic to intercept the proxy file not found
state you can pass a closure as the third argument. It will be called with
the arguments proxydir, namespace and className when the proxy file could not
be found.
Multiple Metadata Sources
-------------------------
When using different components using Doctrine 2 you may end up
with them using two different metadata drivers, for example XML and
YAML. You can use the DriverChain Metadata implementations to
annotationsL. You can use the DriverChain Metadata implementations to
aggregate these drivers based on namespaces:
.. code-block:: php
@@ -423,7 +393,7 @@ aggregate these drivers based on namespaces:
$chain = new DriverChain();
$chain->addDriver($xmlDriver, 'Doctrine\Tests\Models\Company');
$chain->addDriver($yamlDriver, 'Doctrine\Tests\ORM\Mapping');
$chain->addDriver($annotationDriver, 'Doctrine\Tests\ORM\Mapping');
Based on the namespace of the entity the loading of entities is
delegated to the appropriate driver. The chain semantics come from
@@ -433,7 +403,6 @@ the entity class name against the namespace using a
correctly if sub-namespaces use different metadata driver
implementations.
Default Repository (***OPTIONAL***)
-----------------------------------

View File

@@ -24,7 +24,7 @@ annotations for supplying object-relational mapping metadata.
If you're not comfortable with the concept of docblock
annotations, don't worry, as mentioned earlier Doctrine 2 provides
XML and YAML alternatives and you could easily implement your own
the XML alternative and you could easily implement your own
favourite mechanism for defining ORM metadata.
In this chapter a reference of every Doctrine 2 Annotation is given
@@ -181,7 +181,7 @@ Examples:
protected $initials;
/**
* @Column(type="integer", name="login_count" nullable=false, options={"unsigned":true, "default":0})
* @Column(type="integer", name="login_count", nullable=false, options={"unsigned":true, "default":0})
*/
protected $loginCount;
@@ -254,7 +254,7 @@ Example:
<?php
/**
* @Id
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="CUSTOM")
* @CustomIdGenerator(class="My\Namespace\MyIdGenerator")
@@ -276,13 +276,11 @@ to a string column of length 255 called ``dtype``.
Required attributes:
- **name**: The column name of the discriminator. This name is also
used during Array hydration as key to specify the class-name.
Optional attributes:
- **type**: By default this is string.
- **length**: By default this is 255.
@@ -312,7 +310,6 @@ depending on whether the classes are in the namespace or not.
// ...
}
.. _annref_embeddable:
@Embeddable
@@ -339,7 +336,6 @@ annotation to establish the relationship between the two classes.
*/
private $address;
.. _annref_embedded:
@Embedded
@@ -352,7 +348,6 @@ Required attributes:
- **class**: The embeddable class
.. code-block:: php
<?php
@@ -372,7 +367,6 @@ Required attributes:
{
// ...
.. _annref_entity:
@Entity
@@ -383,7 +377,6 @@ the persistence of all classes marked as entities.
Optional attributes:
- **repositoryClass**: Specifies the FQCN of a subclass of the
EntityRepository. Use of repositories for entities is encouraged to keep
specialized DQL and SQL operations separated from the Model/Domain
@@ -398,11 +391,11 @@ Example:
<?php
/**
* @Entity(repositoryClass="MyProject\UserRepository")
* @Entity(repositoryClass="MyProject\UserRepository", readOnly=true)
*/
class User
{
//...
// ...
}
.. _annref_entity_result:
@@ -433,7 +426,6 @@ Required attributes:
- **name**: Name of the persistent field or property of the class.
Optional attributes:
- **column**: Name of the column in the SELECT clause.
@@ -453,9 +445,9 @@ used as default.
Optional attributes:
- **strategy**: Set the name of the identifier generation strategy.
Valid values are AUTO, SEQUENCE, TABLE, IDENTITY, UUID, CUSTOM and NONE.
Valid values are ``AUTO``, ``SEQUENCE``, ``TABLE``, ``IDENTITY``, ``CUSTOM`` and ``NONE``, explained
in the :ref:`Identifier Generation Strategies <identifier-generation-strategies>` section.
If not specified, default value is AUTO.
Example:
@@ -511,7 +503,6 @@ has meaning in the SchemaTool schema generation context.
Required attributes:
- **name**: Name of the Index
- **columns**: Array of columns.
@@ -625,7 +616,6 @@ inferred from the table and primary key names.
Required attributes:
- **name**: Column name that holds the foreign key identifier for
this relation. In the context of @JoinTable it specifies the column
name in the join table.
@@ -634,7 +624,6 @@ Required attributes:
Optional attributes:
- **unique**: Determines whether this relation is exclusive between the
affected entities and should be enforced as such on the database
constraint level. Defaults to false.
@@ -685,7 +674,6 @@ using the affected table and the column names.
Optional attributes:
- **name**: Database name of the join-table
- **joinColumns**: An array of @JoinColumn annotations describing the
join-relation between the owning entities table and the join table.
@@ -717,14 +705,12 @@ describes a many-to-one relationship between two entities.
Required attributes:
- **targetEntity**: FQCN of the referenced target entity. Can be the
unqualified class name if both classes are in the same namespace.
*IMPORTANT:* No leading backslash!
Optional attributes:
- **cascade**: Cascade Option
- **fetch**: One of LAZY or EAGER
- inversedBy - The inversedBy attribute designates the field in
@@ -753,14 +739,12 @@ entities.
Required attributes:
- **targetEntity**: FQCN of the referenced target entity. Can be the
unqualified class name if both classes are in the same namespace.
*IMPORTANT:* No leading backslash!
Optional attributes:
- **mappedBy**: This option specifies the property name on the
targetEntity that is the owning side of this relation. It is a
required attribute for the inverse side of a relationship.
@@ -816,7 +800,6 @@ The @MappedSuperclass annotation cannot be used in conjunction with
Optional attributes:
- **repositoryClass**: (>= 2.2) Specifies the FQCN of a subclass of the EntityRepository.
That will be inherited for all subclasses of that Mapped Superclass.
@@ -853,13 +836,11 @@ Required attributes:
- **name**: The name used to refer to the query with the EntityManager methods that create query objects.
- **query**: The SQL query string.
Optional attributes:
- **resultClass**: The class of the result.
- **resultSetMapping**: The name of a SqlResultSetMapping, as defined in metadata.
Example:
.. code-block:: php
@@ -925,14 +906,12 @@ primary key column names apply here too.
Required attributes:
- **targetEntity**: FQCN of the referenced target entity. Can be the
unqualified class name if both classes are in the same namespace.
*IMPORTANT:* No leading backslash!
Optional attributes:
- **cascade**: Cascade Option
- **fetch**: One of LAZY or EAGER
- **orphanRemoval**: Boolean that specifies if orphans, inverse
@@ -959,14 +938,12 @@ Example:
Required attributes:
- **targetEntity**: FQCN of the referenced target entity. Can be the
unqualified class name if both classes are in the same namespace.
*IMPORTANT:* No leading backslash!
Optional attributes:
- **cascade**: Cascade Option
- **orphanRemoval**: Boolean that specifies if orphans, inverse
OneToOne entities that are not connected to any owning instance,
@@ -983,7 +960,7 @@ Example:
<?php
/**
* @OneToMany(targetEntity="Phonenumber", mappedBy="user", cascade={"persist", "remove", "merge"}, orphanRemoval=true)
* @OneToMany(targetEntity="Phonenumber", mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true)
*/
public $phonenumbers;
@@ -1091,12 +1068,10 @@ the increment size and initial values of the sequence.
Required attributes:
- **sequenceName**: Name of the sequence
Optional attributes:
- **allocationSize**: Increment the sequence by the allocation size
when its fetched. A value larger than 1 allows optimization for
scenarios where you create more than one new entity per request.
@@ -1127,7 +1102,6 @@ Required attributes:
- **name**: The name given to the result set mapping, and used to refer to it in the methods of the Query API.
Optional attributes:
- **entities**: Array of @EntityResult, Specifies the result set mapping to entities.
@@ -1228,12 +1202,10 @@ unqualified classname.
Required attributes:
- **name**: Name of the table
Optional attributes:
- **indexes**: Array of @Index annotations
- **uniqueConstraints**: Array of @UniqueConstraint annotations.
- **schema**: (>= 2.5) Name of the schema the table lies in.
@@ -1266,7 +1238,6 @@ context.
Required attributes:
- **name**: Name of the Index
- **columns**: Array of columns.

View File

@@ -18,7 +18,7 @@ well.
Requirements
------------
Doctrine 2 requires a minimum of PHP 5.4. For greatly improved
Doctrine 2 requires a minimum of PHP 7.1. For greatly improved
performance it is also recommended that you use APC with PHP.
Doctrine 2 Packages
@@ -34,7 +34,6 @@ This manual mainly covers the ORM package, sometimes touching parts
of the underlying DBAL and Common packages. The Doctrine code base
is split in to these packages for a few reasons and they are to...
- ...make things more maintainable and decoupled
- ...allow you to use the code in Doctrine Common without the ORM
or DBAL
@@ -72,27 +71,16 @@ Entities
An entity is a lightweight, persistent domain object. An entity can
be any regular PHP class observing the following restrictions:
- An entity class must not be final or contain final methods.
- All persistent properties/field of any entity class should
always be private or protected, otherwise lazy-loading might not
work as expected. In case you serialize entities (for example Session)
properties should be protected (See Serialize section below).
- An entity class must not implement ``__clone`` or
:doc:`do so safely <../cookbook/implementing-wakeup-or-clone>`.
- An entity class must not implement ``__wakeup`` or
:doc:`do so safely <../cookbook/implementing-wakeup-or-clone>`.
Also consider implementing
`Serializable <http://php.net/manual/en/class.serializable.php>`_
instead.
- Any two entity classes in a class hierarchy that inherit
directly or indirectly from one another must not have a mapped
property with the same name. That is, if B inherits from A then B
must not have a mapped field with the same name as an already
mapped field that is inherited from A.
- An entity cannot make use of func_get_args() to implement variable parameters.
Generated proxies do not support this for performance reasons and your code might
actually fail to work when violating this restriction.
Entities support inheritance, polymorphic associations, and
polymorphic queries. Both abstract and concrete classes can be
@@ -106,14 +94,12 @@ classes, and non-entity classes may extend entity classes.
never calls entity constructors, thus you are free to use them as
you wish and even have it require arguments of any type.
Entity states
~~~~~~~~~~~~~
An entity instance can be characterized as being NEW, MANAGED,
DETACHED or REMOVED.
- A NEW entity instance has no persistent identity, and is not yet
associated with an EntityManager and a UnitOfWork (i.e. those just
created with the "new" operator).
@@ -150,18 +136,18 @@ subsequent access must be through the interface type.
Serializing entities
~~~~~~~~~~~~~~~~~~~~
Serializing entities can be problematic and is not really
recommended, at least not as long as an entity instance still holds
references to proxy objects or is still managed by an
EntityManager. If you intend to serialize (and unserialize) entity
Serializing entities is generally to be avoided.
If you intend to serialize (and unserialize) entity
instances that still hold references to proxy objects you may run
into problems with private properties because of technical
limitations. Proxy objects implement ``__sleep`` and it is not
possible for ``__sleep`` to return names of private properties in
parent classes. On the other hand it is not a solution for proxy
objects to implement ``Serializable`` because Serializable does not
work well with any potential cyclic object references (at least we
did not find a way yet, if you did, please contact us).
into problems, because all proxy properties will be initialized
recursively, leading to large serialized object graphs, especially
for circular associations.
If you really must serialize entities, regardless if proxies are
involved or not, then consider implementing the ``Serializable``
interface and manually checking for cyclic dependencies in your
object graph.
The EntityManager
~~~~~~~~~~~~~~~~~
@@ -189,9 +175,8 @@ The Unit of Work
Internally an ``EntityManager`` uses a ``UnitOfWork``, which is a
typical implementation of the
`Unit of Work pattern <http://martinfowler.com/eaaCatalog/unitOfWork.html>`_,
`Unit of Work pattern <https://martinfowler.com/eaaCatalog/unitOfWork.html>`_,
to keep track of all the things that need to be done the next time
``flush`` is invoked. You usually do not directly interact with a
``UnitOfWork`` but with the ``EntityManager`` instead.

View File

@@ -22,9 +22,9 @@ One tip for working with relations is to read the relation from left to right, w
- ManyToOne - Many instances of the current Entity refer to One instance of the refered Entity.
- OneToOne - One instance of the current Entity refers to One instance of the refered Entity.
See below for all the possible relations.
See below for all the possible relations.
An association is considered to be unidirectional if only one side of the association has
An association is considered to be unidirectional if only one side of the association has
a property referring to the other side.
To gain a full understanding of associations you should also read about :doc:`owning and
@@ -68,18 +68,6 @@ A many-to-one association is the most common association between objects. Exampl
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToOne:
address:
targetEntity: Address
joinColumn:
name: address_id
referencedColumnName: id
.. note::
The above ``@JoinColumn`` is optional as it would default
@@ -145,17 +133,6 @@ references one ``Shipment`` entity.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
joinColumn:
name: shipment_id
referencedColumnName: id
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -182,7 +159,7 @@ Here is a one-to-one relationship between a ``Customer`` and a
``Cart``. The ``Cart`` has a reference back to the ``Customer`` so
it is bidirectional.
Here we see the ``mappedBy`` and ``inversedBy`` annotations for the first time.
Here we see the ``mappedBy`` and ``inversedBy`` attributes for the first time.
They are used to tell Doctrine which property on the other side refers to the
object.
@@ -233,22 +210,6 @@ object.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Customer:
oneToOne:
cart:
targetEntity: Cart
mappedBy: customer
Cart:
oneToOne:
customer:
targetEntity: Customer
inversedBy: cart
joinColumn:
name: customer_id
referencedColumnName: id
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -259,6 +220,7 @@ Generated MySQL Schema:
CREATE TABLE Cart (
id INT AUTO_INCREMENT NOT NULL,
customer_id INT DEFAULT NULL,
UNIQUE INDEX UNIQ_BA388B79395C3F3 (customer_id),
PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE Customer (
@@ -313,8 +275,8 @@ One-To-Many, Bidirectional
--------------------------
A one-to-many association has to be bidirectional, unless you are using a
join table. This is because the many side in a one-to-many association holds
the foreign key, making it the owning side. Doctrine needs the many side
join table. This is because the "many" side in a one-to-many association holds
the foreign key, making it the owning side. Doctrine needs the "many" side
defined in order to understand the association.
This bidirectional mapping requires the ``mappedBy`` attribute on the
@@ -335,7 +297,7 @@ bidirectional many-to-one.
{
// ...
/**
* One Product has Many Features.
* One product has many features. This is the inverse side.
* @OneToMany(targetEntity="Feature", mappedBy="product")
*/
private $features;
@@ -351,7 +313,7 @@ bidirectional many-to-one.
{
// ...
/**
* Many Features have One Product.
* Many features have one product. This is the owning side.
* @ManyToOne(targetEntity="Product", inversedBy="features")
* @JoinColumn(name="product_id", referencedColumnName="id")
*/
@@ -372,24 +334,6 @@ bidirectional many-to-one.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToMany:
features:
targetEntity: Feature
mappedBy: product
Feature:
type: entity
manyToOne:
product:
targetEntity: Product
inversedBy: features
joinColumn:
name: product_id
referencedColumnName: id
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -469,24 +413,6 @@ The following example sets up such a unidirectional one-to-many association:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
phonenumbers:
targetEntity: Phonenumber
joinTable:
name: users_phonenumbers
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
phonenumber_id:
referencedColumnName: id
unique: true
Generates the following MySQL Schema:
.. code-block:: sql
@@ -557,19 +483,6 @@ database perspective is known as an adjacency list approach.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Category:
type: entity
oneToMany:
children:
targetEntity: Category
mappedBy: parent
manyToOne:
parent:
targetEntity: Category
inversedBy: children
Note that the @JoinColumn is not really necessary in this example,
as the defaults would be the same.
@@ -641,22 +554,6 @@ entities:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
targetEntity: Group
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
Generated MySQL Schema:
.. code-block:: sql
@@ -754,30 +651,6 @@ one is bidirectional.
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
targetEntity: Group
inversedBy: users
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
Group:
type: entity
manyToMany:
users:
targetEntity: User
mappedBy: groups
The MySQL schema is exactly the same as for the Many-To-Many
uni-directional case above.
@@ -923,14 +796,6 @@ As an example, consider this mapping:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
This is essentially the same as the following, more verbose,
mapping:
@@ -956,17 +821,6 @@ mapping:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Product:
type: entity
oneToOne:
shipment:
targetEntity: Shipment
joinColumn:
name: shipment_id
referencedColumnName: id
The @JoinTable definition used for many-to-many mappings has
similar defaults. As an example, consider this mapping:
@@ -977,10 +831,10 @@ similar defaults. As an example, consider this mapping:
<?php
class User
{
//...
// ...
/** @ManyToMany(targetEntity="Group") */
private $groups;
//...
// ...
}
.. code-block:: xml
@@ -991,14 +845,6 @@ similar defaults. As an example, consider this mapping:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
targetEntity: Group
This is essentially the same as the following, more verbose, mapping:
.. configuration-block::
@@ -1008,7 +854,7 @@ This is essentially the same as the following, more verbose, mapping:
<?php
class User
{
//...
// ...
/**
* Many Users have Many Groups.
* @ManyToMany(targetEntity="Group")
@@ -1018,7 +864,7 @@ This is essentially the same as the following, more verbose, mapping:
* )
*/
private $groups;
//...
// ...
}
.. code-block:: xml
@@ -1038,22 +884,6 @@ This is essentially the same as the following, more verbose, mapping:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
targetEntity: Group
joinTable:
name: User_Group
joinColumns:
User_id:
referencedColumnName: id
inverseJoinColumns:
Group_id:
referencedColumnName: id
In that case, the name of the join table defaults to a combination
of the simple, unqualified class names of the participating
classes, separated by an underscore character. The names of the

View File

@@ -52,16 +52,15 @@ mapping metadata:
- :doc:`Docblock Annotations <annotations-reference>`
- :doc:`XML <xml-mapping>`
- :doc:`YAML <yaml-mapping>`
- :doc:`PHP code <php-mapping>`
This manual will usually show mapping metadata via docblock annotations, though
many examples also show the equivalent configuration in YAML and XML.
many examples also show the equivalent configuration in XML.
.. note::
All metadata drivers perform equally. Once the metadata of a class has been
read from the source (annotations, xml or yaml) it is stored in an instance
read from the source (annotations or xml) it is stored in an instance
of the ``Doctrine\ORM\Mapping\ClassMetadata`` class and these instances are
stored in the metadata cache. If you're not using a metadata cache (not
recommended!) then the XML driver is the fastest.
@@ -76,7 +75,7 @@ Marking our ``Message`` class as an entity for Doctrine is straightforward:
/** @Entity */
class Message
{
//...
// ...
}
.. code-block:: xml
@@ -87,12 +86,6 @@ Marking our ``Message`` class as an entity for Doctrine is straightforward:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
# ...
With no additional information, Doctrine expects the entity to be saved
into a table with the same name as the class in our case ``Message``.
You can change this by configuring information about the table:
@@ -108,7 +101,7 @@ You can change this by configuring information about the table:
*/
class Message
{
//...
// ...
}
.. code-block:: xml
@@ -119,13 +112,6 @@ You can change this by configuring information about the table:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
table: message
# ...
Now the class ``Message`` will be saved and fetched from the table ``message``.
Property Mapping
@@ -165,19 +151,6 @@ default.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
fields:
id:
type: integer
text:
length: 140
postedAt:
type: datetime
column: posted_at
When we don't explicitly specify a column name via the ``name`` option, Doctrine
assumes the field name is also the column name. This means that:
@@ -227,36 +200,48 @@ 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.
- ``string``: Type that maps an SQL VARCHAR to a PHP string.
- ``integer``: Type that maps an 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
- ``boolean``: Type that maps an SQL boolean or equivalent (TINYINT) to a PHP boolean.
- ``decimal``: Type that maps an SQL DECIMAL to a PHP string.
- ``date``: Type that maps an 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
- ``date_immutable``: Type that maps an SQL DATETIME to a PHP DateTimeImmutable
object.
- ``time``: Type that maps an SQL TIME to a PHP DateTime object.
- ``time_immutable``: Type that maps an SQL TIME to a PHP DateTimeImmutable object.
- ``datetime``: Type that maps an SQL DATETIME/TIMESTAMP to a PHP DateTime
object with the current timezone.
- ``datetimetz``: Type that maps an SQL DATETIME/TIMESTAMP to a PHP DateTime
object with the timezone specified in the value from the database.
- ``datetime_immutable``: Type that maps an SQL DATETIME/TIMESTAMP to a PHP DateTimeImmutable
object with the current timezone.
- ``datetimetz_immutable``: Type that maps an SQL DATETIME/TIMESTAMP to a PHP DateTimeImmutable
object with the timezone specified in the value from the database.
- ``dateinterval``: Type that maps an interval to a PHP DateInterval object
- ``text``: Type that maps an SQL CLOB to a PHP string.
- ``object``: Type that maps an SQL CLOB to a PHP object using
``serialize()`` and ``unserialize()``
- ``array``: Type that maps a SQL CLOB to a PHP array using
- ``array``: Type that maps an SQL CLOB to a PHP array using
``serialize()`` and ``unserialize()``
- ``simple_array``: Type that maps a SQL CLOB to a PHP array using
- ``simple_array``: Type that maps an SQL CLOB to a one-dimensional 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
- ``json_array``: Type that maps an SQL CLOB to a PHP array using
``json_encode()`` and ``json_decode()``. This one has been deprecated in favor
of ``json`` type.
- ``json``: Type that maps an SQL CLOB to a PHP array using
``json_encode()`` and ``json_decode()``. An empty value is correctly represented as ``null``
- ``float``: Type that maps an 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
- ``blob``: Type that maps an SQL BLOB to a PHP resource stream
- ``binary``: Type that maps an SQL binary to a PHP resource stream
A cookbook article shows how to define :doc:`your own custom mapping types
<../cookbook/custom-mapping-types>`.
@@ -270,7 +255,7 @@ A cookbook article shows how to define :doc:`your own custom mapping types
.. warning::
All Date types assume that you are exclusively using the default timezone
set by `date_default_timezone_set() <http://docs.php.net/manual/en/function.date-default-timezone-set.php>`_
set by `date_default_timezone_set() <https://php.net/manual/en/function.date-default-timezone-set.php>`_
or by the php.ini configuration ``date.timezone``. Working with
different timezones will cause troubles and unexpected behavior.
@@ -300,7 +285,7 @@ annotation.
* @GeneratedValue
*/
private $id;
//...
// ...
}
.. code-block:: xml
@@ -314,23 +299,13 @@ annotation.
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
id:
id:
type: integer
generator:
strategy: AUTO
fields:
# fields here
In most cases using the automatic generator strategy (``@GeneratedValue``) is
what you want. It defaults to the identifier generation mechanism your current
database vendor prefers: AUTO_INCREMENT with MySQL, SERIAL with PostgreSQL,
Sequences with Oracle and so on.
.. _identifier-generation-strategies:
Identifier Generation Strategies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -355,8 +330,6 @@ Here is the list of possible generation strategies:
strategy does currently not provide full portability and is
supported by the following platforms: MySQL/SQLite/SQL Anywhere
(AUTO\_INCREMENT), MSSQL (IDENTITY) and PostgreSQL (SERIAL).
- ``UUID``: Tells Doctrine to use the built-in Universally Unique Identifier
generator. This strategy provides full portability.
- ``TABLE``: Tells Doctrine to use a separate table for ID
generation. This strategy provides full portability.
***This strategy is not yet implemented!***
@@ -387,7 +360,7 @@ besides specifying the sequence's name:
* @SequenceGenerator(sequenceName="message_seq", initialValue=1, allocationSize=100)
*/
protected $id = null;
//...
// ...
}
.. code-block:: xml
@@ -401,20 +374,6 @@ besides specifying the sequence's name:
</entity>
</doctrine-mapping>
.. code-block:: yaml
Message:
type: entity
id:
id:
type: integer
generator:
strategy: SEQUENCE
sequenceGenerator:
sequenceName: message_seq
allocationSize: 100
initialValue: 1
The initial value specifies at which value the sequence should
start.
@@ -438,7 +397,6 @@ need to access the sequence once to generate the identifiers for
configuration option is never larger than the actual sequences
INCREMENT BY value, otherwise you may get duplicate keys.
.. note::
It is possible to use strategy="AUTO" and at the same time
@@ -447,7 +405,6 @@ need to access the sequence once to generate the identifiers for
of the underlying platform is SEQUENCE, such as for Oracle and
PostgreSQL.
Composite Keys
~~~~~~~~~~~~~~

View File

@@ -15,7 +15,6 @@ especially what the strategies presented here provide help with.
you use the tools for your particular RDBMS for these bulk
operations.
Bulk Inserts
------------
@@ -42,7 +41,7 @@ internally but also mean more work during ``flush``.
$em->clear(); // Detaches all objects from Doctrine!
}
}
$em->flush(); //Persist objects that did not make up an entire batch
$em->flush(); // Persist objects that did not make up an entire batch
$em->clear();
Bulk Updates
@@ -75,7 +74,7 @@ with the batching strategy that was already used for bulk inserts:
<?php
$batchSize = 20;
$i = 0;
$i = 1;
$q = $em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
foreach ($iterableResult as $row) {
@@ -102,7 +101,6 @@ with the batching strategy that was already used for bulk inserts:
additional memory not visible to the PHP process. For large sets this
may easily kill the process for no apparent reason.
Bulk Deletes
------------
@@ -136,7 +134,7 @@ The following example shows how to do this:
<?php
$batchSize = 20;
$i = 0;
$i = 1;
$q = $em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
while (($row = $iterableResult->next()) !== false) {
@@ -155,7 +153,6 @@ The following example shows how to do this:
fetch-join a collection-valued association. The nature of such SQL
result sets is not suitable for incremental hydration.
Iterating Large Results for Data-Processing
-------------------------------------------
@@ -168,13 +165,13 @@ problems using the following approach:
.. code-block:: php
<?php
$q = $this->_em->createQuery('select u from MyProject\Model\User u');
$q = $this->em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
foreach ($iterableResult as $row) {
// do stuff with the data in the row, $row[0] is always the object
// detach from Doctrine, so that it can be Garbage-Collected immediately
$this->_em->detach($row[0]);
// detach all entities from Doctrine, so that Garbage-Collection can kick in immediately
$this->em->clear();
}
.. note::
@@ -183,5 +180,9 @@ problems using the following approach:
fetch-join a collection-valued association. The nature of such SQL
result sets is not suitable for incremental hydration.
Packages for easing Batch Processing
------------------------------------
You can implement batch processing yourself, or use an existing
package such as `DoctrineBatchUtils <https://github.com/Ocramius/DoctrineBatchUtils>`_,
which already provides the logic described above in an encapsulated format.

View File

@@ -12,14 +12,12 @@ Constrain relationships as much as possible
It is important to constrain relationships as much as possible.
This means:
- Impose a traversal direction (avoid bidirectional associations
if possible)
- Eliminate nonessential associations
This has several benefits:
- Reduced coupling in your domain model
- Simpler code in your domain model (no need to maintain
bidirectionality properly)
@@ -43,7 +41,7 @@ should use events judiciously.
Use cascades judiciously
------------------------
Automatic cascades of the persist/remove/merge/etc. operations are
Automatic cascades of the persist/remove/refresh/etc. operations are
very handy but should be used wisely. Do NOT simply add all
cascades to all associations. Think about which cascades actually
do make sense for you for a particular association, given the
@@ -74,11 +72,11 @@ collections in entities in the constructor. Example:
<?php
namespace MyProject\Model;
use Doctrine\Common\Collections\ArrayCollection;
class User {
private $addresses;
private $articles;
public function __construct() {
$this->addresses = new ArrayCollection;
$this->articles = new ArrayCollection;
@@ -108,4 +106,3 @@ queries generally don't have any noticeable performance impact, it
is still preferable to use fewer, well-defined transactions that
are established through explicit transaction boundaries.

View File

@@ -4,8 +4,8 @@ Caching
Doctrine provides cache drivers in the ``Common`` package for some
of the most popular caching implementations such as APC, Memcache
and Xcache. We also provide an ``ArrayCache`` driver which stores
the data in a PHP array. Obviously, when using ``ArrayCache``, the
cache does not persist between requests, but this is useful for
the data in a PHP array. Obviously, when using ``ArrayCache``, the
cache does not persist between requests, but this is useful for
testing in a development environment.
Cache Drivers
@@ -18,7 +18,6 @@ this interface.
The interface defines the following public methods for you to implement:
- fetch($id) - Fetches an entry from the cache
- contains($id) - Test if an entry exists in the cache
- save($id, $data, $lifeTime = false) - Puts data into the cache for x seconds. 0 = infinite time
@@ -28,11 +27,10 @@ Each driver extends the ``CacheProvider`` class which defines a few
abstract protected methods that each of the drivers must
implement:
- \_doFetch($id)
- \_doContains($id)
- \_doSave($id, $data, $lifeTime = false)
- \_doDelete($id)
- doFetch($id)
- doContains($id)
- doSave($id, $data, $lifeTime = false)
- doDelete($id)
The public methods ``fetch()``, ``contains()`` etc. use the
above protected methods which are implemented by the drivers. The
@@ -43,14 +41,14 @@ these methods.
This documentation does not cover every single cache driver included
with Doctrine. For an up-to-date-list, see the
`cache directory on GitHub <https://github.com/doctrine/cache/tree/master/lib/Doctrine/Common/Cache>`.
`cache directory on GitHub <https://github.com/doctrine/cache/tree/master/lib/Doctrine/Common/Cache>`_.
APC
~~~
In order to use the APC cache driver you must have it compiled and
enabled in your php.ini. You can read about APC
`in the PHP Documentation <http://us2.php.net/apc>`_. It will give
`in the PHP Documentation <https://php.net/apc>`_. It will give
you a little background information about what it is and how you
can use it as well as how to install it.
@@ -68,7 +66,7 @@ APCu
In order to use the APCu cache driver you must have it compiled and
enabled in your php.ini. You can read about APCu
`in the PHP Documentation <http://us2.php.net/apcu>`_. It will give
`in the PHP Documentation <https://php.net/apcu>`_. It will give
you a little background information about what it is and how you
can use it as well as how to install it.
@@ -86,7 +84,7 @@ Memcache
In order to use the Memcache cache driver you must have it compiled
and enabled in your php.ini. You can read about Memcache
`on the PHP website <http://php.net/memcache>`_. It will
`on the PHP website <https://php.net/memcache>`_. It will
give you a little background information about what it is and how
you can use it as well as how to install it.
@@ -98,7 +96,7 @@ driver by itself.
<?php
$memcache = new Memcache();
$memcache->connect('memcache_host', 11211);
$cacheDriver = new \Doctrine\Common\Cache\MemcacheCache();
$cacheDriver->setMemcache($memcache);
$cacheDriver->save('cache_id', 'my_data');
@@ -111,7 +109,7 @@ Memcache.
In order to use the Memcached cache driver you must have it compiled
and enabled in your php.ini. You can read about Memcached
`on the PHP website <http://php.net/memcached>`_. It will
`on the PHP website <https://php.net/memcached>`_. It will
give you a little background information about what it is and how
you can use it as well as how to install it.
@@ -123,7 +121,7 @@ driver by itself.
<?php
$memcached = new Memcached();
$memcached->addServer('memcache_host', 11211);
$cacheDriver = new \Doctrine\Common\Cache\MemcachedCache();
$cacheDriver->setMemcached($memcached);
$cacheDriver->save('cache_id', 'my_data');
@@ -133,7 +131,7 @@ Xcache
In order to use the Xcache cache driver you must have it compiled
and enabled in your php.ini. You can read about Xcache
`here <http://xcache.lighttpd.net/>`_. It will give you a little
`here <https://xcache.lighttpd.net/>`_. It will give you a little
background information about what it is and how you can use it as
well as how to install it.
@@ -151,7 +149,7 @@ Redis
In order to use the Redis cache driver you must have it compiled
and enabled in your php.ini. You can read about what Redis is
`from here <http://redis.io/>`_. Also check
`from here <https://redis.io/>`_. Also check
`A PHP extension for Redis <https://github.com/nicolasff/phpredis/>`_ for how you can use
and install the Redis PHP extension.
@@ -172,7 +170,7 @@ Using Cache Drivers
-------------------
In this section we'll describe how you can fully utilize the API of
the cache drivers to save data to a cache, check if some cached data
the cache drivers to save data to a cache, check if some cached data
exists, fetch the cached data and delete the cached data. We'll use the
``ArrayCache`` implementation as our example here.
@@ -195,7 +193,6 @@ Saving some data to the cache driver is as simple as using the
The ``save()`` method accepts three arguments which are described
below:
- ``$id`` - The cache id
- ``$data`` - The cache entry/data.
- ``$lifeTime`` - The lifetime. If != false, sets a specific
@@ -245,7 +242,7 @@ Deleting
~~~~~~~~
As you might guess, deleting is just as easy as saving, checking
and fetching. You can delete by an individual ID, or you can
and fetching. You can delete by an individual ID, or you can
delete all entries.
By Cache ID
@@ -311,9 +308,8 @@ Result Cache
~~~~~~~~~~~~
The result cache can be used to cache the results of your queries
so that we don't have to query the database or hydrate the data
again after the first time. You just need to configure the result
cache implementation.
so that we don't have to query the database again after the first time.
You just need to configure the result cache implementation.
.. code-block:: php
@@ -348,7 +344,6 @@ result cache driver.
<?php
$query->useResultCache(false);
If you want to set the time the cache has to live you can use the
``setResultCacheLifetime()`` method.
@@ -378,7 +373,7 @@ Metadata Cache
~~~~~~~~~~~~~~
Your class metadata can be parsed from a few different sources like
YAML, XML, Annotations, etc. Instead of parsing this information on
XML, Annotations, etc. Instead of parsing this information on
each request we should cache it using one of the cache drivers.
Just like the query and result cache we need to configure it
@@ -472,4 +467,3 @@ not letting your users' requests populate the cache.
You can read more about cache slams
`in this blog post <http://notmysock.org/blog/php/user-cache-timebomb.html>`_.

View File

@@ -73,7 +73,7 @@ follows:
<?php
use Doctrine\Common\NotifyPropertyChanged,
Doctrine\Common\PropertyChangedListener;
/**
* @Entity
* @ChangeTrackingPolicy("NOTIFY")
@@ -81,12 +81,12 @@ follows:
class MyEntity implements NotifyPropertyChanged
{
// ...
private $_listeners = array();
private $listeners = array();
public function addPropertyChangedListener(PropertyChangedListener $listener)
{
$this->_listeners[] = $listener;
$this->listeners[] = $listener;
}
}
@@ -99,30 +99,30 @@ behaviour:
<?php
// ...
class MyEntity implements NotifyPropertyChanged
{
// ...
protected function _onPropertyChanged($propName, $oldValue, $newValue)
protected function onPropertyChanged($propName, $oldValue, $newValue)
{
if ($this->_listeners) {
foreach ($this->_listeners as $listener) {
if ($this->listeners) {
foreach ($this->listeners as $listener) {
$listener->propertyChanged($this, $propName, $oldValue, $newValue);
}
}
}
public function setData($data)
{
if ($data != $this->data) {
$this->_onPropertyChanged('data', $this->data, $data);
$this->onPropertyChanged('data', $this->data, $data);
$this->data = $data;
}
}
}
You have to invoke ``_onPropertyChanged`` inside every method that
You have to invoke ``onPropertyChanged`` inside every method that
changes the persistent state of ``MyEntity``.
The check whether the new value is different from the old one is
@@ -148,4 +148,3 @@ effectiveness. It has the best performance characteristics of the 3
policies with larger units of work and a flush() operation is very
cheap when nothing has changed.

View File

@@ -1,9 +1,7 @@
Installation and Configuration
==============================
Doctrine can be installed with `Composer <http://www.getcomposer.org>`_. For
older versions we still have `PEAR packages
<http://pear.doctrine-project.org>`_.
Doctrine can be installed with `Composer <https://getcomposer.org>`_.
Define the following requirement in your ``composer.json`` file:
@@ -16,8 +14,7 @@ Define the following requirement in your ``composer.json`` file:
}
Then call ``composer install`` from your command line. If you don't know
how Composer works, check out their `Getting Started
<http://getcomposer.org/doc/00-intro.md>`_ to set up.
how Composer works, check out their `Getting Started <https://getcomposer.org/doc/00-intro.md>`_ to set up.
Class loading
-------------
@@ -70,22 +67,6 @@ Or if you prefer XML:
$config = Setup::createXMLMetadataConfiguration($paths, $isDevMode);
$entityManager = EntityManager::create($dbParams, $config);
Or if you prefer YAML:
.. code-block:: php
<?php
$paths = array("/path/to/yml-mappings");
$config = Setup::createYAMLMetadataConfiguration($paths, $isDevMode);
$entityManager = EntityManager::create($dbParams, $config);
.. note::
If you want to use yml mapping you should add yaml dependency to your `composer.json`:
::
"symfony/yaml": "*"
Inside the ``Setup`` methods several assumptions are made:
- If `$isDevMode` is true caching is done in memory with the ``ArrayCache``. Proxy objects are recreated on every request.
@@ -93,8 +74,7 @@ Inside the ``Setup`` methods several assumptions are made:
- If `$isDevMode` is false, set then proxy classes have to be explicitly created through the command line.
- If third argument `$proxyDir` is not set, use the systems temporary directory.
If you want to configure Doctrine in more detail, take a look at the :doc:`Advanced
Configuration <reference/advanced-configuration>` section.
If you want to configure Doctrine in more detail, take a look at the :doc:`Advanced Configuration <reference/advanced-configuration>` section.
.. note::

View File

@@ -1,5 +1,5 @@
Doctrine Query Language
===========================
=======================
DQL stands for Doctrine Query Language and is an Object
Query Language derivative that is very similar to the Hibernate
@@ -18,7 +18,6 @@ querying that storage to pick a certain subset of your objects.
need to think about DQL as a query language for your object model,
not for your relational schema.
DQL is case in-sensitive, except for namespace, class and field
names, which are case sensitive.
@@ -59,7 +58,6 @@ Here is an example that selects all users with an age > 20:
Lets examine the query:
- ``u`` is a so called identification variable or alias that
refers to the ``MyProject\Model\User`` class. By placing this alias
in the SELECT clause we specify that we want all instances of the
@@ -103,15 +101,15 @@ their inclusion in the SELECT clause.
In this case, the result will be an array of arrays. In the example
above, each element of the result array would be an array of the
scalar name and address values.
scalar name and address values.
You can select scalars from any entity in the query.
You can select scalars from any entity in the query.
**Mixed**
.. code-block:: sql
``SELECT u, p.quantity FROM Users u...``
SELECT u, p.quantity FROM Users u...
Here, the result will again be an array of arrays, with each element
being an array made up of a User object and the scalar value
@@ -131,7 +129,6 @@ multiple FROM clauses.
Doctrine throws an exception if you violate this constraint.
Joins
~~~~~
@@ -180,16 +177,15 @@ not need to lazy load the association with another query.
Doctrine allows you to walk all the associations between
all the objects in your domain model. Objects that were not already
loaded from the database are replaced with lazy load proxy
instances. Non-loaded Collections are also replaced by lazy-load
loaded from the database are replaced with lazy loading proxy
instances. Non-loaded Collections are also replaced by lazy-loading
instances that fetch all the contained objects upon first access.
However relying on the lazy-load mechanism leads to many small
However relying on the lazy-loading mechanism leads to many small
queries executed against the database, which can significantly
affect the performance of your application. **Fetch Joins** are the
solution to hydrate most or all of the entities that you need in a
single SELECT query.
Named and Positional Parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -208,7 +204,8 @@ This section contains a large set of DQL queries and some
explanations of what is happening. The actual result also depends
on the hydration mode.
Hydrate all User entities:
Hydrate all User entities
^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -216,7 +213,8 @@ Hydrate all User entities:
$query = $em->createQuery('SELECT u FROM MyProject\Model\User u');
$users = $query->getResult(); // array of User objects
Retrieve the IDs of all CmsUsers:
Retrieve the IDs of all CmsUsers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -224,7 +222,8 @@ Retrieve the IDs of all CmsUsers:
$query = $em->createQuery('SELECT u.id FROM CmsUser u');
$ids = $query->getResult(); // array of CmsUser ids
Retrieve the IDs of all users that have written an article:
Retrieve the IDs of all users that have written an article
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -232,6 +231,10 @@ Retrieve the IDs of all users that have written an article:
$query = $em->createQuery('SELECT DISTINCT u.id FROM CmsArticle a JOIN a.user u');
$ids = $query->getResult(); // array of CmsUser ids
Retrieve all articles and sort them by username
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Retrieve all articles and sort them by the name of the articles
users instance:
@@ -241,7 +244,8 @@ users instance:
$query = $em->createQuery('SELECT a FROM CmsArticle a JOIN a.user u ORDER BY u.name ASC');
$articles = $query->getResult(); // array of CmsArticle objects
Retrieve the Username and Name of a CmsUser:
Retrieve the Username and Name of a CmsUser
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -250,7 +254,8 @@ Retrieve the Username and Name of a CmsUser:
$users = $query->getResult(); // array of CmsUser username and name values
echo $users[0]['username'];
Retrieve a ForumUser and his single associated entity:
Retrieve a ForumUser and his single associated entity
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -259,7 +264,8 @@ Retrieve a ForumUser and his single associated entity:
$users = $query->getResult(); // array of ForumUser objects with the avatar association loaded
echo get_class($users[0]->getAvatar());
Retrieve a CmsUser and fetch join all the phonenumbers he has:
Retrieve a CmsUser and fetch join all owning phonenumbers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -268,7 +274,8 @@ Retrieve a CmsUser and fetch join all the phonenumbers he has:
$users = $query->getResult(); // array of CmsUser objects with the phonenumbers association loaded
$phonenumbers = $users[0]->getPhonenumbers();
Hydrate a result in Ascending:
Hydrate a result in Ascending
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -276,7 +283,8 @@ Hydrate a result in Ascending:
$query = $em->createQuery('SELECT u FROM ForumUser u ORDER BY u.id ASC');
$users = $query->getResult(); // array of ForumUser objects
Or in Descending Order:
Hydrate a result in Descending Order
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -284,7 +292,8 @@ Or in Descending Order:
$query = $em->createQuery('SELECT u FROM ForumUser u ORDER BY u.id DESC');
$users = $query->getResult(); // array of ForumUser objects
Using Aggregate Functions:
Using Aggregate Functions
^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -295,7 +304,8 @@ Using Aggregate Functions:
$query = $em->createQuery('SELECT u, count(g.id) FROM Entities\User u JOIN u.groups g GROUP BY u.id');
$result = $query->getResult();
With WHERE Clause and Positional Parameter:
Using WHERE Clause and Positional Parameter
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -304,7 +314,8 @@ With WHERE Clause and Positional Parameter:
$query->setParameter(1, 321);
$users = $query->getResult(); // array of ForumUser objects
With WHERE Clause and Named Parameter:
Using WHERE Clause and Named Parameter
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -313,7 +324,8 @@ With WHERE Clause and Named Parameter:
$query->setParameter('name', 'Bob');
$users = $query->getResult(); // array of ForumUser objects
With Nested Conditions in WHERE Clause:
Using Nested Conditions in WHERE Clause
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -326,7 +338,8 @@ With Nested Conditions in WHERE Clause:
));
$users = $query->getResult(); // array of ForumUser objects
With COUNT DISTINCT:
COUNT DISTINCT
^^^^^^^^^^^^^^
.. code-block:: php
@@ -334,7 +347,8 @@ With COUNT DISTINCT:
$query = $em->createQuery('SELECT COUNT(DISTINCT u.name) FROM CmsUser');
$users = $query->getResult(); // array of ForumUser objects
With Arithmetic Expression in WHERE clause:
Using Arithmetic Expression in WHERE clause
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -342,6 +356,9 @@ With Arithmetic Expression in WHERE clause:
$query = $em->createQuery('SELECT u FROM CmsUser u WHERE ((u.id + 5000) * u.id + 3) < 10000000');
$users = $query->getResult(); // array of ForumUser objects
Hide aliased columns from the result
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Retrieve user entities with Arithmetic Expression in ORDER clause, using the ``HIDDEN`` keyword:
.. code-block:: php
@@ -350,6 +367,9 @@ Retrieve user entities with Arithmetic Expression in ORDER clause, using the ``H
$query = $em->createQuery('SELECT u, u.posts_count + u.likes_count AS HIDDEN score FROM CmsUser u ORDER BY score');
$users = $query->getResult(); // array of User objects
Select all user-ids and optionally associated article-ids
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Using a LEFT JOIN to hydrate all user-ids and optionally associated
article-ids:
@@ -359,8 +379,8 @@ article-ids:
$query = $em->createQuery('SELECT u.id, a.id as article_id FROM CmsUser u LEFT JOIN u.articles a');
$results = $query->getResult(); // array of user ids and every article_id for each user
Restricting a JOIN clause by additional conditions specified by
WITH:
Restricting a JOIN clause by additional conditions specified by WITH
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -369,7 +389,8 @@ WITH:
$query->setParameter('foo', '%foo%');
$users = $query->getResult();
Using several Fetch JOINs:
Using several Fetch JOINs
^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -377,7 +398,8 @@ Using several Fetch JOINs:
$query = $em->createQuery('SELECT u, a, p, c FROM CmsUser u JOIN u.articles a JOIN u.phonenumbers p JOIN a.comments c');
$users = $query->getResult();
BETWEEN in WHERE clause:
BETWEEN in WHERE clause
^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -387,7 +409,8 @@ BETWEEN in WHERE clause:
$query->setParameter(2, 321);
$usernames = $query->getResult();
DQL Functions in WHERE clause:
DQL Functions in WHERE clause
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -395,7 +418,8 @@ DQL Functions in WHERE clause:
$query = $em->createQuery("SELECT u.name FROM CmsUser u WHERE TRIM(u.name) = 'someone'");
$usernames = $query->getResult();
IN() Expression:
IN() Expression
^^^^^^^^^^^^^^^
.. code-block:: php
@@ -409,7 +433,8 @@ IN() Expression:
$query = $em->createQuery('SELECT u FROM CmsUser u WHERE u.id NOT IN (1)');
$users = $query->getResult();
CONCAT() DQL Function:
CONCAT() DQL Function
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -423,6 +448,7 @@ CONCAT() DQL Function:
$idUsernames = $query->getResult();
EXISTS in WHERE clause with correlated Subquery
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -430,7 +456,8 @@ EXISTS in WHERE clause with correlated Subquery
$query = $em->createQuery('SELECT u.id FROM CmsUser u WHERE EXISTS (SELECT p.phonenumber FROM CmsPhonenumber p WHERE p.user = u.id)');
$ids = $query->getResult();
Get all users who are members of $group.
Get all users who are members of $group
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -440,6 +467,7 @@ Get all users who are members of $group.
$ids = $query->getResult();
Get all users that have more than 1 phonenumber
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -448,6 +476,7 @@ Get all users that have more than 1 phonenumber
$users = $query->getResult();
Get all users that have no phonenumber
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: php
@@ -455,8 +484,11 @@ Get all users that have no phonenumber
$query = $em->createQuery('SELECT u FROM CmsUser u WHERE u.phonenumbers IS EMPTY');
$users = $query->getResult();
Get all instances of a specific type, for use with inheritance
hierarchies:
Get all instances of a specific type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Get all instances of a specific type, for use with inheritance hierarchies. These queries can be useful for
:doc:`inheritance mapping <inheritance-mapping>`.
.. versionadded:: 2.1
@@ -467,7 +499,10 @@ hierarchies:
$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');
Get all users visible on a given website that have chosen certain gender:
Using IDENTITY() in queries
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Get all users visible on a given website that have chosen certain gender.
.. versionadded:: 2.2
@@ -478,20 +513,43 @@ Get all users visible on a given website that have chosen certain gender:
.. versionadded:: 2.4
Starting with 2.4, the IDENTITY() DQL function also works for composite primary keys:
Starting with 2.4, the IDENTITY() DQL function also works for composite primary keys
.. code-block:: php
<?php
$query = $em->createQuery("SELECT IDENTITY(c.location, 'latitude') AS latitude, IDENTITY(c.location, 'longitude') AS longitude FROM Checkpoint c WHERE c.user = ?1");
Arbitrary Join
^^^^^^^^^^^^^^
Joins between entities without associations were not possible until version
2.4, where you can generate an arbitrary join with the following syntax:
.. code-block:: php
<?php
$query = $em->createQuery('SELECT u FROM User u JOIN Blacklist b WITH u.email = b.email');
$query = $em->createQuery('SELECT u FROM User u JOIN Banlist b WITH u.email = b.email');
With an arbitrary join the result differs from the joins using a mapped property.
The result of an arbitrary join is an one dimensional array with a mix of the entity from the ``SELECT``
and the joined entity fitting to the filtering of the query. In case of the example with ``User``
and ``Banlist``, it can look like this:
- User
- Banlist
- Banlist
- User
- Banlist
- User
- Banlist
- Banlist
- Banlist
In this form of join, the ``Banlist`` entities found by the filtering in the ``WITH`` part are not fetched by an accessor
method on ``User``, but are already part of the result. In case the accessor method for Banlists is invoked on a User instance,
it loads all the related ``Banlist`` objects corresponding to this ``User``. This change of behaviour needs to be considered
when the DQL is switched to an arbitrary join.
.. note::
The differences between WHERE, WITH and HAVING clauses may be
@@ -504,7 +562,6 @@ Joins between entities without associations were not possible until version
- HAVING is applied to the results of a query after
aggregation (GROUP BY)
Partial Object Syntax
^^^^^^^^^^^^^^^^^^^^^
@@ -636,7 +693,6 @@ clause and using sub-selects.
``EntityManager#clear()`` and retrieve new instances of any
affected entity.
DELETE queries
--------------
@@ -657,7 +713,6 @@ The same restrictions apply for the reference of related entities.
of the query. Additionally Deletes of specified entities are *NOT*
cascaded to related entities even if specified in the metadata.
Functions, Operators, Aggregates
--------------------------------
It is possible to wrap both fields and identification values into
@@ -670,13 +725,12 @@ DQL Functions
The following functions are supported in SELECT, WHERE and HAVING
clauses:
- IDENTITY(single\_association\_path\_expression [, fieldMapping]) - Retrieve the foreign key column of association of the owning side
- ABS(arithmetic\_expression)
- IDENTITY(single_association_path_expression [, fieldMapping]) - Retrieve the foreign key column of association of the owning side
- ABS(arithmetic_expression)
- CONCAT(str1, str2)
- CURRENT\_DATE() - Return the current date
- CURRENT\_TIME() - Returns the current time
- CURRENT\_TIMESTAMP() - Returns a timestamp of the current date
- CURRENT_DATE() - Return the current date
- CURRENT_TIME() - Returns the current time
- CURRENT_TIMESTAMP() - Returns a timestamp of the current date
and time.
- LENGTH(str) - Returns the length of the given string
- LOCATE(needle, haystack [, offset]) - Locate the first
@@ -691,8 +745,8 @@ clauses:
- TRIM([LEADING \| TRAILING \| BOTH] ['trchar' FROM] str) - Trim
the string by the given trim char, defaults to whitespaces.
- UPPER(str) - Return the upper-case of the given string.
- DATE_ADD(date, days, unit) - Add the number of days to a given date. (Supported units are DAY, MONTH)
- DATE_SUB(date, days, unit) - Substract the number of days from a given date. (Supported units are DAY, MONTH)
- DATE_ADD(date, days, unit) - Add the number of days to a given date. (Supported units are YEAR, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND)
- DATE_SUB(date, days, unit) - Substract the number of days from a given date. (Supported units are YEAR, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND)
- DATE_DIFF(date1, date2) - Calculate the difference in days between date1-date2.
Arithmetic operators
@@ -716,7 +770,6 @@ Other Expressions
DQL offers a wide-range of additional expressions that are known
from SQL, here is a list of all the supported constructs:
- ``ALL/ANY/SOME`` - Used in a WHERE clause followed by a
sub-select this works like the equivalent constructs in SQL.
- ``BETWEEN a AND b`` and ``NOT BETWEEN a AND b`` can be used to
@@ -803,7 +856,7 @@ what type of results to expect.
Single Table
~~~~~~~~~~~~
`Single Table Inheritance <http://martinfowler.com/eaaCatalog/singleTableInheritance.html>`_
`Single Table Inheritance <https://martinfowler.com/eaaCatalog/singleTableInheritance.html>`_
is an inheritance mapping strategy where all classes of a hierarchy
are mapped to a single database table. In order to distinguish
which row represents which type in the hierarchy a so-called
@@ -896,7 +949,7 @@ entities:
Class Table Inheritance
~~~~~~~~~~~~~~~~~~~~~~~
`Class Table Inheritance <http://martinfowler.com/eaaCatalog/classTableInheritance.html>`_
`Class Table Inheritance <https://martinfowler.com/eaaCatalog/classTableInheritance.html>`_
is an inheritance mapping strategy where each class in a hierarchy
is mapped to several tables: its own table and the tables of all
parent classes. The table of a child class is linked to the table
@@ -941,7 +994,6 @@ you'll notice some differences:
) ENGINE = InnoDB;
ALTER TABLE Employee ADD FOREIGN KEY (id) REFERENCES Person(id) ON DELETE CASCADE
- The data is split between two tables
- A foreign key exists between the two tables
@@ -957,7 +1009,6 @@ automatically for you:
FROM Employee e1_ INNER JOIN Person p0_ ON e1_.id = p0_.id
WHERE p0_.name = ?
The Query class
---------------
@@ -988,7 +1039,6 @@ 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:
- ``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).
@@ -1008,8 +1058,6 @@ the Query class. Here they are:
graph in certain scenarios due to the difference of the identity
semantics between arrays and objects.
- ``Query#getScalarResult()``: Retrieves a flat/rectangular result
set of scalar values that can contain duplicate data. The
pure/mixed distinction does not apply.
@@ -1087,13 +1135,11 @@ clause, we get a mixed result.
Conventions for mixed results are as follows:
- The object fetched in the FROM clause is always positioned with the key '0'.
- Every scalar without a name is numbered in the order given in the query, starting with 1.
- Every aliased scalar is given with its alias-name as the key. The case of the name is kept.
- If several objects are fetched from the FROM clause they alternate every row.
Here is how the result could look like:
.. code-block:: php
@@ -1133,7 +1179,6 @@ will return the rows iterating the different top-level entities.
[2] => Object (User)
[3] => Object (Group)
Hydration Modes
~~~~~~~~~~~~~~~
@@ -1143,11 +1188,10 @@ 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_OBJECT``
- ``Query::HYDRATE_ARRAY``
- ``Query::HYDRATE_SCALAR``
- ``Query::HYDRATE_SINGLE_SCALAR``
Object Hydration
^^^^^^^^^^^^^^^^
@@ -1172,7 +1216,7 @@ why we are listing as many of the assumptions here for reference:
- 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.
previous object is still an unloaded proxy.
This list might be incomplete.
@@ -1211,9 +1255,8 @@ object graph you can use scalar hydration:
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
A query of the kind 'SELECT u.name ..' returns a key 'u_name' in
the result rows.
Single Scalar Hydration
@@ -1247,13 +1290,14 @@ creating a class which extends ``AbstractHydrator``:
<?php
namespace MyProject\Hydrators;
use Doctrine\DBAL\FetchMode;
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
class CustomHydrator extends AbstractHydrator
{
protected function _hydrateAll()
{
return $this->_stmt->fetchAll(PDO::FETCH_ASSOC);
return $this->stmt->fetchAll(FetchMode::Associative);
}
}
@@ -1295,7 +1339,6 @@ Prepared Statements that use numerical or named wildcards require
additional parameters to be executable against the database. To
pass parameters to the query the following methods can be used:
- ``AbstractQuery::setParameter($param, $value)`` - Set the
numerical or named wildcard to the given value.
- ``AbstractQuery::setParameters(array $params)`` - Set an array
@@ -1350,7 +1393,6 @@ Result Cache API:
``Doctrine\ORM\Configuration`` instance so that it is passed to
every ``Query`` and ``NativeQuery`` instance.
Query Hints
^^^^^^^^^^^
@@ -1360,22 +1402,21 @@ exist mostly internal query hints that are not be consumed in
userland. However the following few hints are to be used in
userland:
- Query::HINT\_FORCE\_PARTIAL\_LOAD - Allows to hydrate objects
- ``Query::HINT_FORCE_PARTIAL_LOAD`` - Allows to hydrate objects
although not all their columns are fetched. This query hint can be
used to handle memory consumption problems with large result-sets
that contain char or binary data. Doctrine has no way of implicitly
reloading this data. Partially loaded objects have to be passed to
``EntityManager::refresh()`` if they are to be reloaded fully from
the database.
- Query::HINT\_REFRESH - This query is used internally by
- ``Query::HINT_REFRESH`` - This query is used internally by
``EntityManager::refresh()`` and can be used in userland as well.
If you specify this hint and a query returns the data for an entity
that is already managed by the UnitOfWork, the fields of the
existing entity will be refreshed. In normal operation a result-set
that loads data of an already existing entity is discarded in favor
of the already existing entity.
- Query::HINT\_CUSTOM\_TREE\_WALKERS - An array of additional
- ``Query::HINT_CUSTOM_TREE_WALKERS`` - An array of additional
``Doctrine\ORM\Query\TreeWalker`` instances that are attached to
the DQL query parsing process.
@@ -1396,7 +1437,6 @@ default. This also means you don't regularly need to fiddle with
the parameters of the Query Cache, however if you do there are
several methods to interact with it:
- ``Query::setQueryCacheDriver($driver)`` - Allows to set a Cache
instance
- ``Query::setQueryCacheLifeTime($seconds = 3600)`` - Set lifetime
@@ -1415,7 +1455,6 @@ well as specify the starting offset, Doctrine then uses a strategy
of manipulating the select query to return only the requested
number of results:
- ``Query::setMaxResults($maxResults)``
- ``Query::setFirstResult($offset)``
@@ -1441,7 +1480,7 @@ can mark a many-to-one or one-to-one association as fetched temporarily to batch
<?php
$query = $em->createQuery("SELECT u FROM MyProject\User u");
$query->setFetchMode("MyProject\User", "address", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER);
$query->setFetchMode("MyProject\User", "address", \Doctrine\ORM\Mapping\FetchMode::EAGER);
$query->execute();
Given that there are 10 users and corresponding addresses in the database the executed queries will look something like:
@@ -1452,15 +1491,14 @@ Given that there are 10 users and corresponding addresses in the database the ex
SELECT * FROM address WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
.. note::
Changing the fetch mode during a query mostly makes sense for one-to-one and many-to-one relations. In that case,
Changing the fetch mode during a query mostly makes sense for one-to-one and many-to-one relations. In that case,
all the necessary IDs are available after the root entity (``user`` in the above example) has been loaded. So, one
query per association can be executed to fetch all the referred-to entities (``address``).
For one-to-many relations, changing the fetch mode to eager will cause to execute one query **for every root entity
loaded**. This gives no improvement over the ``lazy`` fetch mode which will also initialize the associations on
a one-by-one basis once they are accessed.
EBNF
----
@@ -1472,7 +1510,6 @@ correct syntax for a particular query should be.
Document syntax:
~~~~~~~~~~~~~~~~
- non-terminals begin with an upper case character
- terminals begin with a lower case character
- parentheses (...) are used for grouping
@@ -1486,10 +1523,8 @@ Document syntax:
Terminals
~~~~~~~~~
- identifier (name, email, ...) must match ``[a-z_][a-z0-9_]*``
- fully_qualified_name (Doctrine\Tests\Models\CMS\CmsUser) matches PHP's fully qualified class names
- aliased_name (CMS:CmsUser) uses two identifiers, one for the namespace alias and one for the class inside it
- string ('foo', 'bar''s house', '%ninja%', ...)
- char ('/', '\\', ' ', ...)
- integer (-1, 0, 1, 34, ...)
@@ -1524,7 +1559,7 @@ Identifiers
AliasIdentificationVariable :: = identifier
/* identifier that must be a class name (the "User" of "FROM User u"), possibly as a fully qualified class name or namespace-aliased */
AbstractSchemaName ::= fully_qualified_name | aliased_name | identifier
AbstractSchemaName ::= fully_qualified_name | identifier
/* Alias ResultVariable declaration (the "total" of "COUNT(*) AS total") */
AliasResultVariable = identifier
@@ -1640,7 +1675,6 @@ Conditional Expressions
EmptyCollectionComparisonExpression | CollectionMemberExpression |
InstanceOfExpression
Collection Expressions
~~~~~~~~~~~~~~~~~~~~~~
@@ -1730,7 +1764,7 @@ QUANTIFIED/BETWEEN/COMPARISON/LIKE/NULL/EXISTS
QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")"
BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression
ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression )
InExpression ::= SingleValuedPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")"
InExpression ::= ArithmeticExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")"
InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")")
InstanceOfParameter ::= AbstractSchemaName | InputParameter
LikeExpression ::= StringExpression ["NOT"] "LIKE" StringPrimary ["ESCAPE" char]
@@ -1771,4 +1805,3 @@ Functions
"UPPER" "(" StringPrimary ")" |
"IDENTITY" "(" SingleValuedAssociationPathExpression {"," string} ")"

View File

@@ -129,7 +129,6 @@ with camelcase and the value of the corresponding constant should
be the name of the constant itself, even with spelling. This has
several reasons:
- It is easy to read.
- Simplicity.
- Each method within an EventSubscriber is named after the
@@ -148,7 +147,6 @@ Lifecycle Events
The EntityManager and UnitOfWork trigger a bunch of events during
the life-time of their registered entities.
- preRemove - The preRemove event occurs for a given entity before
the respective EntityManager remove operation for that entity is
executed. It is not called for a DQL DELETE statement.
@@ -173,7 +171,7 @@ the life-time of their registered entities.
database or after the refresh operation has been applied to it.
- loadClassMetadata - The loadClassMetadata event occurs after the
mapping metadata for a class has been loaded from a mapping source
(annotations/xml/yaml). This event is not a lifecycle callback.
(annotations/xml). This event is not a lifecycle callback.
- onClassMetadataNotFound - Loading class metadata for a particular
requested class name failed. Manipulating the given event args instance
allows providing fallback metadata even when no actual metadata exists
@@ -233,7 +231,6 @@ EntityManager and other relevant data.
:ref:`reference-events-implementing-listeners` section very carefully
to understand which operations are allowed in which lifecycle event.
Lifecycle Callbacks
-------------------
@@ -295,26 +292,8 @@ Note that the methods set as lifecycle callbacks need to be public and,
when using these annotations, you have to apply the
``@HasLifecycleCallbacks`` marker annotation on the entity class.
If you want to register lifecycle callbacks from YAML or XML you
can do it with the following.
.. code-block:: yaml
User:
type: entity
fields:
# ...
name:
type: string(50)
lifecycleCallbacks:
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ]
postPersist: [ doStuffOnPostPersist ]
In YAML the ``key`` of the lifecycleCallbacks entry is the event that you
are triggering on and the value is the method (or methods) to call. The allowed
event types are the ones listed in the previous Lifecycle Events section.
XML would look something like this:
If you want to register lifecycle callbacks from XML it would look
something like this:
.. code-block:: xml
@@ -323,7 +302,7 @@ XML would look something like this:
<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
/Users/robo/dev/php/Doctrine/doctrine-mapping.xsd">
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="User">
@@ -340,7 +319,7 @@ In XML the ``type`` of the lifecycle-callback entry is the event that you
are triggering on and the ``method`` is the method to call. The allowed event
types are the ones listed in the previous Lifecycle Events section.
When using YAML or XML you need to remember to create public methods to match the
When using XML you need to remember to create public methods to match the
callback names you defined. E.g. in these examples ``doStuffOnPrePersist()``,
``doOtherStuffOnPrePersist()`` and ``doStuffOnPostPersist()`` methods need to be
defined on your ``User`` model.
@@ -370,9 +349,8 @@ defined on your ``User`` model.
}
}
Lifecycle Callbacks Event Argument
-----------------------------------
----------------------------------
.. versionadded:: 2.4
@@ -525,7 +503,6 @@ which has access to the entity and the entity manager.
The following restrictions apply to ``prePersist``:
- If you are using a PrePersist Identity Generator such as
sequences the ID value will *NOT* be available within any
PrePersist events.
@@ -573,7 +550,6 @@ OnFlush is a very powerful event. It is called inside
entities and their associations have been computed. This means, the
``onFlush`` event has access to the sets of:
- Entities scheduled for insert
- Entities scheduled for update
- Entities scheduled for removal
@@ -618,7 +594,6 @@ mentioned sets. See this example:
The following restrictions apply to the onFlush event:
- If you create and persist a new entity in ``onFlush``, then
calling ``EntityManager#persist()`` is not enough.
You have to execute an additional call to
@@ -667,7 +642,6 @@ This means you have access to all the fields that have changed for
this entity with their old and new value. The following methods are
available on the ``PreUpdateEventArgs``:
- ``getEntity()`` to get access to the actual entity.
- ``getEntityChangeSet()`` to get a copy of the changeset array.
Changes to this returned array do not affect updating.
@@ -721,7 +695,6 @@ lifecycle callback when there are expensive validations to call:
Restrictions for this event:
- Changes to associations of the passed entities are not
recognized by the flush operation anymore.
- Changes to fields of the passed entities are not recognized by
@@ -780,13 +753,6 @@ An entity listener is a lifecycle listener class used for an entity.
<!-- .... -->
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Entity\User:
type: entity
entityListeners:
UserListener:
# ....
.. _reference-entity-listeners:
@@ -869,32 +835,13 @@ you need to map the listener method using the event type mapping:
<!-- .... -->
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Entity\User:
type: entity
entityListeners:
UserListener:
preFlush: [preFlushHandler]
postLoad: [postLoadHandler]
postPersist: [postPersistHandler]
prePersist: [prePersistHandler]
postUpdate: [postUpdateHandler]
preUpdate: [preUpdateHandler]
postRemove: [postRemoveHandler]
preRemove: [preRemoveHandler]
# ....
.. note::
The order of execution of multiple methods for the same event (e.g. multiple @PrePersist) is not guaranteed.
Entity listeners resolver
~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
Doctrine invokes the listener resolver to get the listener instance.
- A resolver allows you register a specific entity listener instance.
@@ -960,18 +907,17 @@ Load ClassMetadata Event
------------------------
When the mapping information for an entity is read, it is populated
in to a ``ClassMetadataInfo`` instance. You can hook in to this
in to a ``Doctrine\ORM\Mapping\ClassMetadata`` instance. You can hook in to this
process and manipulate the instance.
.. code-block:: php
<?php
$test = new TestEvent();
$metadataFactory = $em->getMetadataFactory();
$test = new TestEventListener();
$evm = $em->getEventManager();
$evm->addEventListener(Events::loadClassMetadata, $test);
$evm->addEventListener(Doctrine\ORM\Events::loadClassMetadata, $test);
class TestEvent
class TestEventListener
{
public function loadClassMetadata(\Doctrine\ORM\Event\LoadClassMetadataEventArgs $eventArgs)
{
@@ -985,4 +931,55 @@ process and manipulate the instance.
}
}
SchemaTool Events
-----------------
It is possible to access the schema metadata during schema changes that are happening in ``Doctrine\ORM\Tools\SchemaTool``.
There are two different events where you can hook in.
postGenerateSchemaTable
~~~~~~~~~~~~~~~~~~~~~~~
This event is fired for each ``Doctrine\DBAL\Schema\Table`` instance, after one was created and built up with the current class metadata
of an entity. It is possible to access to the current state of ``Doctrine\DBAL\Schema\Schema``, the current table schema
instance and class metadata.
.. code-block:: php
<?php
$test = new TestEventListener();
$evm = $em->getEventManager();
$evm->addEventListener(\Doctrine\ORM\Tools\ToolEvents::postGenerateSchemaTable, $test);
class TestEventListener
{
public function postGenerateSchemaTable(\Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
$schema = $eventArgs->getSchema();
$table = $eventArgs->getClassTable();
}
}
postGenerateSchema
~~~~~~~~~~~~~~~~~~
This event is fired after the schema instance was successfully built and before SQL queries are generated from the
schema information of ``Doctrine\DBAL\Schema\Schema``. It allows to access the full object representation of the database schema
and the EntityManager.
.. code-block:: php
<?php
$test = new TestEventListener();
$evm = $em->getEventManager();
$evm->addEventListener(\Doctrine\ORM\Tools\ToolEvents::postGenerateSchema, $test);
class TestEventListener
{
public function postGenerateSchema(\Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs $eventArgs)
{
$schema = $eventArgs->getSchema();
$em = $eventArgs->getEntityManager();
}
}

View File

@@ -13,7 +13,7 @@ Database Schema
How do I set the charset and collation for MySQL tables?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can't set these values inside the annotations, yml or xml mapping files. To make a database
You can't set these values inside the annotations or xml mapping files. To make a database
work with the default charset and collation you should configure MySQL to use it as default charset,
or create the database with charset and collation details. This way they get inherited to all newly
created database tables and columns.
@@ -21,12 +21,6 @@ created database tables and columns.
Entity Classes
--------------
I access a variable and its null, what is wrong?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If this variable is a public variable then you are violating one of the criteria for entities.
All properties have to be protected or private for the proxy object pattern to work.
How can I add default values to a column?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -58,7 +52,7 @@ or adding entities to a collection twice. You have to check for both conditions
in the code before calling ``$em->flush()`` if you know that unique constraint failures
can occur.
In `Symfony2 <http://www.symfony.com>`_ for example there is a Unique Entity Validator
In `Symfony2 <https://www.symfony.com>`_ for example there is a Unique Entity Validator
to achieve this task.
For collections you can check with ``$collection->contains($entity)`` if an entity is already
@@ -108,7 +102,6 @@ foreign keys as primary keys feature of Doctrine introduced in version 2.1.
See :doc:`the tutorial on composite primary keys for more information<../tutorials/composite-primary-keys>`.
How can i paginate fetch-joined collections?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -118,8 +111,8 @@ over this collection using a LIMIT statement (or vendor equivalent).
Doctrine does not offer a solution for this out of the box but there are several extensions
that do:
* `DoctrineExtensions <http://github.com/beberlei/DoctrineExtensions>`_
* `Pagerfanta <http://github.com/whiteoctober/pagerfanta>`_
* `DoctrineExtensions <https://github.com/beberlei/DoctrineExtensions>`_
* `Pagerfanta <https://github.com/whiteoctober/pagerfanta>`_
Why does pagination not work correctly with fetch joins?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -136,7 +129,7 @@ Inheritance
Can I use Inheritance with Doctrine 2?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Yes, you can use Single- or Joined-Table Inheritance in Doctrine 2.
See the documentation chapter on :doc:`inheritance mapping <inheritance-mapping>` for
@@ -149,23 +142,6 @@ If you set a many-to-one or one-to-one association target-entity to any parent c
an inheritance hierarchy Doctrine does not know what PHP class the foreign is actually of.
To find this out it has to execute a SQL query to look this information up in the database.
EntityGenerator
---------------
Why does the EntityGenerator not do X?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The EntityGenerator is not a full fledged code-generator that solves all tasks. Code-Generation
is not a first-class priority in Doctrine 2 anymore (compared to Doctrine 1). The EntityGenerator
is supposed to kick-start you, but not towards 100%.
Why does the EntityGenerator not generate inheritance correctly?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Just from the details of the discriminator map the EntityGenerator cannot guess the inheritance hierarchy.
This is why the generation of inherited entities does not fully work. You have to adjust some additional
code to get this one working correctly.
Performance
-----------

View File

@@ -16,7 +16,6 @@ By adding SQL to the conditional clauses of queries, the filter system filters
out rows belonging to the entities at the level of the SQL result set. This
means that the filtered entities are never hydrated (which can be expensive).
Example filter class
--------------------
Throughout this document the example ``MyLocaleFilter`` class will be used to
@@ -47,7 +46,7 @@ proper quoting of parameters.
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
// Check if the entity implements the LocalAware interface
if (!$targetEntity->reflClass->implementsInterface('LocaleAware')) {
if (!$targetEntity->getReflectionClass()->implementsInterface('LocaleAware')) {
return "";
}
@@ -55,7 +54,6 @@ proper quoting of parameters.
}
}
Configuration
-------------
Filter classes are added to the configuration as following:
@@ -65,11 +63,9 @@ Filter classes are added to the configuration as following:
<?php
$config->addFilter("locale", "\Doctrine\Tests\ORM\Functional\MyLocaleFilter");
The ``Configuration#addFilter()`` method takes a name for the filter and the name of the
class responsible for the actual filtering.
Disabling/Enabling Filters and Setting Parameters
---------------------------------------------------
Filters can be disabled and enabled via the ``FilterCollection`` which is

View File

@@ -11,9 +11,8 @@ request and can greatly improve performance.
"If you care about performance and don't use a bytecode
cache then you don't really care about performance. Please get one
and start using it."
*Stas Malyshev, Core Contributor to PHP and Zend Employee*
*Stas Malyshev, Core Contributor to PHP and Zend Employee*
Metadata and Query caches
-------------------------
@@ -52,7 +51,7 @@ for more information on how this fetch mode works.
Temporarily change fetch mode in DQL
------------------------------------
See :ref:`Doctrine Query Language chapter <dql-temporarily-change-fetch-mode>`
See :ref:`dql-temporarily-change-fetch-mode`
Apply Best Practices
@@ -61,8 +60,7 @@ Apply Best Practices
A lot of the points mentioned in the Best Practices chapter will
also positively affect the performance of Doctrine.
Change Tracking policies
------------------------
See: :doc:`Change Tracking Policies <reference/change-tracking-policies>`
See: :doc:`Change Tracking Policies <change-tracking-policies>`

View File

@@ -25,36 +25,44 @@ appear in the middle of an otherwise mapped inheritance hierarchy
For further support of inheritance, the single or
joined table inheritance features have to be used.
Example:
.. code-block:: php
<?php
/** @MappedSuperclass */
class MappedSuperclassBase
class Person
{
/** @Column(type="integer") */
protected $mapped1;
/** @Column(type="string") */
protected $mapped2;
/**
* @OneToOne(targetEntity="MappedSuperclassRelated1")
* @JoinColumn(name="related1_id", referencedColumnName="id")
* @OneToOne(targetEntity="Toothbrush")
* @JoinColumn(name="toothbrush_id", referencedColumnName="id")
*/
protected $mappedRelated1;
protected $toothbrush;
// ... more fields and methods
}
/** @Entity */
class EntitySubClass extends MappedSuperclassBase
class Employee extends Person
{
/** @Id @Column(type="integer") */
private $id;
/** @Column(type="string") */
private $name;
// ... more fields and methods
}
/** @Entity */
class Toothbrush
{
/** @Id @Column(type="integer") */
private $id;
// ... more fields and methods
}
@@ -73,7 +81,7 @@ defined on that class directly.
Single Table Inheritance
------------------------
`Single Table Inheritance <http://martinfowler.com/eaaCatalog/singleTableInheritance.html>`_
`Single Table Inheritance <https://martinfowler.com/eaaCatalog/singleTableInheritance.html>`_
is an inheritance mapping strategy where all classes of a hierarchy
are mapped to a single database table. In order to distinguish
which row represents which type in the hierarchy a so-called
@@ -84,10 +92,10 @@ Example:
.. configuration-block::
.. code-block:: php
<?php
namespace MyProject\Model;
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
@@ -98,7 +106,7 @@ Example:
{
// ...
}
/**
* @Entity
*/
@@ -107,25 +115,9 @@ Example:
// ...
}
.. code-block:: yaml
MyProject\Model\Person:
type: entity
inheritanceType: SINGLE_TABLE
discriminatorColumn:
name: discr
type: string
discriminatorMap:
person: Person
employee: Employee
MyProject\Model\Employee:
type: entity
Things to note:
- The @InheritanceType and @DiscriminatorColumn must be specified
- The @InheritanceType and @DiscriminatorColumn must be specified
on the topmost class that is part of the mapped entity hierarchy.
- The @DiscriminatorMap specifies which values of the
discriminator column identify a row as being of a certain type. In
@@ -139,9 +131,7 @@ Things to note:
be fully qualified if the classes are contained in the same
namespace as the entity class on which the discriminator map is
applied.
- If no discriminator map is provided, then the map is generated
automatically. The automatically generated discriminator map
contains the lowercase short name of each class as key.
- If no discriminator map is provided, an exception will be thrown.
Design-time considerations
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -162,9 +152,9 @@ relationships involving types that employ this mapping strategy are
very performing.
There is a general performance consideration with Single Table
Inheritance: If the target-entity of a many-to-one or one-to-one
association is an STI entity, it is preferable for performance reasons that it
be a leaf entity in the inheritance hierarchy, (ie. have no subclasses).
Inheritance: If the target-entity of a many-to-one or one-to-one
association is an STI entity, it is preferable for performance reasons that it
be a leaf entity in the inheritance hierarchy, (ie. have no subclasses).
Otherwise Doctrine *CANNOT* create proxy instances
of this entity and will *ALWAYS* load the entity eagerly.
@@ -174,14 +164,14 @@ SQL Schema considerations
For Single-Table-Inheritance to work in scenarios where you are
using either a legacy database schema or a self-written database
schema you have to make sure that all columns that are not in the
root entity but in any of the different sub-entities has to allows
root entity but in any of the different sub-entities has to allow
null values. Columns that have NOT NULL constraints have to be on
the root entity of the single-table inheritance hierarchy.
Class Table Inheritance
-----------------------
`Class Table Inheritance <http://martinfowler.com/eaaCatalog/classTableInheritance.html>`_
`Class Table Inheritance <https://martinfowler.com/eaaCatalog/classTableInheritance.html>`_
is an inheritance mapping strategy where each class in a hierarchy
is mapped to several tables: its own table and the tables of all
parent classes. The table of a child class is linked to the table
@@ -196,7 +186,7 @@ Example:
<?php
namespace MyProject\Model;
/**
* @Entity
* @InheritanceType("JOINED")
@@ -207,7 +197,7 @@ Example:
{
// ...
}
/** @Entity */
class Employee extends Person
{
@@ -216,7 +206,6 @@ Example:
Things to note:
- The @InheritanceType, @DiscriminatorColumn and @DiscriminatorMap
must be specified on the topmost class that is part of the mapped
entity hierarchy.
@@ -229,9 +218,7 @@ Things to note:
be fully qualified if the classes are contained in the same
namespace as the entity class on which the discriminator map is
applied.
- If no discriminator map is provided, then the map is generated
automatically. The automatically generated discriminator map
contains the lowercase short name of each class as key.
- If no discriminator map is provided, an exception will be thrown.
.. note::
@@ -241,7 +228,6 @@ Things to note:
``ON DELETE CASCADE`` in all database implementations. A failure to
implement this yourself will lead to dead rows in the database.
Design-time considerations
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -268,9 +254,9 @@ themselves on access of any subtype fields, so accessing fields of
subtypes after such a query is not safe.
There is a general performance consideration with Class Table
Inheritance: If the target-entity of a many-to-one or one-to-one
association is a CTI entity, it is preferable for performance reasons that it
be a leaf entity in the inheritance hierarchy, (ie. have no subclasses).
Inheritance: If the target-entity of a many-to-one or one-to-one
association is a CTI entity, it is preferable for performance reasons that it
be a leaf entity in the inheritance hierarchy, (ie. have no subclasses).
Otherwise Doctrine *CANNOT* create proxy instances
of this entity and will *ALWAYS* load the entity eagerly.
@@ -293,7 +279,6 @@ Used to override a mapping for an entity field or relationship.
May be applied to an entity that extends a mapped superclass
to override a relationship or field mapping defined by the mapped superclass.
Association Override
~~~~~~~~~~~~~~~~~~~~
Override a mapping for an entity relationship.
@@ -315,7 +300,7 @@ Example:
*/
class User
{
//other fields mapping
// other fields mapping
/**
* @ManyToMany(targetEntity="Group", inversedBy="users")
@@ -365,8 +350,7 @@ Example:
<many-to-many field="groups" target-entity="Group" inversed-by="users">
<cascade>
<cascade-persist/>
<cascade-merge/>
<cascade-detach/>
<cascade-refresh/>
</cascade>
<join-table name="users_groups">
<join-columns>
@@ -402,51 +386,6 @@ Example:
</association-overrides>
</entity>
</doctrine-mapping>
.. code-block:: yaml
# user mapping
MyProject\Model\User:
type: mappedSuperclass
# other fields mapping
manyToOne:
address:
targetEntity: Address
joinColumn:
name: address_id
referencedColumnName: id
cascade: [ persist, merge ]
manyToMany:
groups:
targetEntity: Group
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
cascade: [ persist, merge, detach ]
# admin mapping
MyProject\Model\Admin:
type: entity
associationOverride:
address:
joinColumn:
adminaddress_id:
name: adminaddress_id
referencedColumnName: id
groups:
joinTable:
name: users_admingroups
joinColumns:
adminuser_id:
referencedColumnName: id
inverseJoinColumns:
admingroup_id:
referencedColumnName: id
Things to note:
@@ -454,7 +393,7 @@ Things to note:
- This feature is available for all kind of associations. (OneToOne, OneToMany, ManyToOne, ManyToMany)
- The association type *CANNOT* be changed.
- The override could redefine the joinTables or joinColumns depending on the association type.
- The override could redefine inversedBy to reference more than one extended entity.
- The override could redefine ``inversedBy`` to reference more than one extended entity.
- The override could redefine fetch to modify the fetch strategy of the extended entity.
Attribute Override
@@ -493,7 +432,7 @@ Could be used by an entity that extends a mapped superclass to override a field
* column=@Column(
* name = "guest_id",
* type = "integer",
length = 140
* length = 140
* )
* ),
* @AttributeOverride(name="name",
@@ -501,7 +440,7 @@ Could be used by an entity that extends a mapped superclass to override a field
* name = "guest_name",
* nullable = false,
* unique = true,
length = 240
* length = 240
* )
* )
* })
@@ -522,7 +461,7 @@ Could be used by an entity that extends a mapped superclass to override a field
<many-to-one field="address" target-entity="Address">
<cascade>
<cascade-persist/>
<cascade-merge/>
<cascade-refresh/>
</cascade>
<join-column name="address_id" referenced-column-name="id"/>
</many-to-one>
@@ -543,42 +482,6 @@ Could be used by an entity that extends a mapped superclass to override a field
</attribute-overrides>
</entity>
</doctrine-mapping>
.. code-block:: yaml
# user mapping
MyProject\Model\User:
type: mappedSuperclass
id:
id:
type: integer
column: user_id
length: 150
generator:
strategy: AUTO
fields:
name:
type: string
column: user_name
length: 250
nullable: true
unique: false
#other fields mapping
# guest mapping
MyProject\Model\Guest:
type: entity
attributeOverride:
id:
column: guest_id
type: integer
length: 140
name:
column: guest_name
type: string
length: 240
nullable: false
unique: true
Things to note:

View File

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

View File

@@ -39,7 +39,7 @@ possible either. See the following example:
name VARCHAR,
PRIMARY KEY(id)
);
CREATE TABLE product_attributes (
product_id INTEGER,
attribute_name VARCHAR,
@@ -63,16 +63,7 @@ Where the ``attribute_name`` column contains the key and
``$attributes``.
The feature request for persistence of primitive value arrays
`is described in the DDC-298 ticket <http://www.doctrine-project.org/jira/browse/DDC-298>`_.
Cascade Merge with Bi-directional Associations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are two bugs now that concern the use of cascade merge in combination with bi-directional associations.
Make sure to study the behavior of cascade merge if you are using it:
- `DDC-875 <http://www.doctrine-project.org/jira/browse/DDC-875>`_ Merge can sometimes add the same entity twice into a collection
- `DDC-763 <http://www.doctrine-project.org/jira/browse/DDC-763>`_ Cascade merge on associated entities can insert too many rows through "Persistence by Reachability"
`is described in the DDC-298 ticket <https://github.com/doctrine/orm/issues/3743>`_.
Custom Persisters
~~~~~~~~~~~~~~~~~
@@ -83,8 +74,8 @@ Currently there is no way to overwrite the persister implementation
for a given entity, however there are several use-cases that can
benefit from custom persister implementations:
- `Add Upsert Support <http://www.doctrine-project.org/jira/browse/DDC-668>`_
- `Evaluate possible ways in which stored-procedures can be used <http://www.doctrine-project.org/jira/browse/DDC-445>`_
- `Add Upsert Support <https://github.com/doctrine/orm/issues/5178>`_
- `Evaluate possible ways in which stored-procedures can be used <https://github.com/doctrine/orm/issues/4946>`_
Persist Keys of Collections
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -94,7 +85,7 @@ PHP Arrays are ordered hash-maps and so should be the
evaluate a feature that optionally persists and hydrates the keys
of a Collection instance.
`Ticket DDC-213 <http://www.doctrine-project.org/jira/browse/DDC-213>`_
`Ticket DDC-213 <https://github.com/doctrine/orm/issues/2817>`_
Mapping many tables to one entity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -116,7 +107,6 @@ blog posts we have written on this topics:
- `A re-usable Versionable behavior for Doctrine2 <http://www.doctrine-project.org/2010/02/24/doctrine2-versionable.html>`_
- `Write your own ORM on top of Doctrine2 <http://www.doctrine-project.org/2010/07/19/your-own-orm-doctrine2.html>`_
- `Doctrine 2 Behavioral Extensions <http://www.doctrine-project.org/2010/11/18/doctrine2-behavioral-extensions.html>`_
- `Doctrator <https://github.com/pablodip/doctrator`>_
Doctrine 2 has enough hooks and extension points so that **you** can
add whatever you want on top of it. None of this will ever become
@@ -131,9 +121,8 @@ included in the core of Doctrine 2. However there are already two
extensions out there that offer support for Nested Set with
Doctrine 2:
- `Doctrine2 Hierarchical-Structural Behavior <http://github.com/guilhermeblanco/Doctrine2-Hierarchical-Structural-Behavior>`_
- `Doctrine2 NestedSet <http://github.com/blt04/doctrine2-nestedset>`_
- `Doctrine2 Hierarchical-Structural Behavior <https://github.com/guilhermeblanco/Doctrine2-Hierarchical-Structural-Behavior>`_
- `Doctrine2 NestedSet <https://github.com/blt04/doctrine2-nestedset>`_
Known Issues
------------
@@ -144,9 +133,7 @@ backwards compatibility issues or where no simple fix exists (yet).
We don't plan to add every bug in the tracker there, just those
issues that can potentially cause nightmares or pain of any sort.
See the Open Bugs on Jira for more details on `bugs, improvement and feature
requests
<http://www.doctrine-project.org/jira/secure/IssueNavigator.jspa?reset=true&mode=hide&pid=10032&resolution=-1&sorter/field=updated&sorter/order=DESC>`_.
See bugs, improvement and feature requests on `Github issues <https://github.com/doctrine/orm/issues>`_.
Identifier Quoting and Legacy Databases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -156,7 +143,6 @@ edge case problems Doctrine 2 does **NOT** do automatic identifier
quoting. This can lead to problems when trying to get
legacy-databases to work with Doctrine 2.
- You can quote column-names as described in the
:doc:`Basic-Mapping <basic-mapping>` section.
- You cannot quote join column names.
@@ -180,27 +166,3 @@ MySQL with MyISAM tables
Doctrine cannot provide atomic operations when calling ``EntityManager#flush()`` if one
of the tables involved uses the storage engine MyISAM. You must use InnoDB or
other storage engines that support transactions if you need integrity.
Entities, Proxies and Reflection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Using methods for Reflection on entities can be prone to error, when the entity
is actually a proxy the following methods will not work correctly:
- ``new ReflectionClass``
- ``new ReflectionObject``
- ``get_class()``
- ``get_parent_class()``
This is why ``Doctrine\Common\Util\ClassUtils`` class exists that has similar
methods, which resolve the proxy problem beforehand.
.. code-block:: php
<?php
use Doctrine\Common\Util\ClassUtils;
$bookProxy = $entityManager->getReference('Acme\Book');
$reflection = ClassUtils::newReflectionClass($bookProxy);
$class = ClassUtils::getClass($bookProxy)¸

View File

@@ -11,10 +11,8 @@ Core Metadata Drivers
Doctrine provides a few different ways for you to specify your
metadata:
- **XML files** (XmlDriver)
- **Class DocBlock Annotations** (AnnotationDriver)
- **YAML files** (YamlDriver)
- **PHP Code in files or static functions** (PhpDriver)
Something important to note about the above drivers is they are all
@@ -37,7 +35,6 @@ an entity.
<?php
$em->getConfiguration()->setMetadataCacheImpl(new ApcuCache());
If you want to use one of the included core metadata drivers you
just need to configure it. All the drivers are in the
``Doctrine\ORM\Mapping\Driver`` namespace:
@@ -59,26 +56,26 @@ implements the ``Driver`` interface:
<?php
namespace Doctrine\ORM\Mapping\Driver;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\ClassMetadata;
interface Driver
{
/**
* Loads the metadata for the specified class into the provided container.
*
*
* @param string $className
* @param ClassMetadataInfo $metadata
* @param ClassMetadata $metadata
*/
function loadMetadataForClass($className, ClassMetadataInfo $metadata);
function loadMetadataForClass($className, ClassMetadata $metadata);
/**
* Gets the names of all mapped classes known to this driver.
*
*
* @return array The names of all mapped classes known to this driver.
*/
function getAllClassNames();
function getAllClassNames();
/**
* 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
@@ -102,22 +99,22 @@ the ``AbstractFileDriver`` implementation for you to extend from:
/**
* {@inheritdoc}
*/
protected $_fileExtension = '.dcm.ext';
protected $fileExtension = '.dcm.ext';
/**
* {@inheritdoc}
*/
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
public function loadMetadataForClass($className, ClassMetadata $metadata)
{
$data = $this->_loadMappingFile($file);
// populate ClassMetadataInfo instance from $data
$data = $this->loadMappingFile($file);
// populate ClassMetadata instance from $data
}
/**
* {@inheritdoc}
*/
protected function _loadMappingFile($file)
protected function loadMappingFile($file)
{
// parse contents of $file and return php data structure
}
@@ -133,7 +130,6 @@ the ``AbstractFileDriver`` implementation for you to extend from:
to name the file ``Entities.User.dcm.ext`` for it to be
recognized.
Now you can use your ``MyMetadataDriver`` implementation by setting
it with the ``setMetadataDriverImpl()`` method:
@@ -154,14 +150,11 @@ entity when needed.
You have all the methods you need to manually specify the mapping
information instead of using some mapping file to populate it from.
The base ``ClassMetadataInfo`` class is responsible for only data
storage and is not meant for runtime use. It does not require that
the class actually exists yet so it is useful for describing some
The ``ClassMetadata`` class is responsible for only data storage
and is not meant for runtime use. It does not require that the
class actually exists yet so it is useful for describing some
entity before it exists and using that information to generate for
example the entities themselves. The class ``ClassMetadata``
extends ``ClassMetadataInfo`` and adds some functionality required
for runtime usage and requires that the PHP class is present and
can be autoloaded.
example the entities themselves.
You can read more about the API of the ``ClassMetadata`` classes in
the PHP Mapping chapter.
@@ -191,4 +184,3 @@ iterate over them:
echo $fieldMapping['fieldName'] . "\n";
}

View File

@@ -102,7 +102,6 @@ achieve such standards by implementing a naming strategy.
You need to create a class which implements ``Doctrine\ORM\Mapping\NamingStrategy``.
.. code-block:: php
<?php

View File

@@ -71,7 +71,7 @@ with inheritance hierarchies.
use Doctrine\ORM\Query\ResultSetMappingBuilder;
$sql = "SELECT u.id, u.name, a.id AS address_id, a.street, a.city " .
$sql = "SELECT u.id, u.name, a.id AS address_id, a.street, a.city " .
"FROM users u INNER JOIN address a ON u.address_id = a.id";
$rsm = new ResultSetMappingBuilder($entityManager);
@@ -92,13 +92,12 @@ a mapping from DQL alias (key) to SQL alias (value)
<?php
$selectClause = $builder->generateSelectClause(array(
$selectClause = $rsm->generateSelectClause(array(
'u' => 't1',
'g' => 't2'
));
$sql = "SELECT " . $selectClause . " FROM users t1 JOIN groups t2 ON t1.group_id = t2.id";
The ResultSetMapping
--------------------
@@ -106,7 +105,6 @@ Understanding the ``ResultSetMapping`` is the key to using a
``NativeQuery``. A Doctrine result can contain the following
components:
- Entity results. These represent root result elements.
- Joined entity results. These represent joined entities in
associations of root entity results.
@@ -132,7 +130,6 @@ components:
``ResultSetMapping`` that describes how the results should be
processed by the hydration routines.
We will now look at each of the result types that can appear in a
ResultSetMapping in detail.
@@ -267,7 +264,7 @@ detail:
<?php
/**
* Adds a meta column (foreign key or discriminator column) to the result set.
*
*
* @param string $alias
* @param string $columnAlias
* @param string $columnName
@@ -322,10 +319,10 @@ entity.
$rsm->addEntityResult('User', 'u');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'name', 'name');
$query = $this->_em->createNativeQuery('SELECT id, name FROM users WHERE name = ?', $rsm);
$query = $this->em->createNativeQuery('SELECT id, name FROM users WHERE name = ?', $rsm);
$query->setParameter(1, 'romanb');
$users = $query->getResult();
The result would look like this:
@@ -358,10 +355,10 @@ thus owns the foreign key.
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'name', 'name');
$rsm->addMetaResult('u', 'address_id', 'address_id');
$query = $this->_em->createNativeQuery('SELECT id, name, address_id FROM users WHERE name = ?', $rsm);
$query = $this->em->createNativeQuery('SELECT id, name, address_id FROM users WHERE name = ?', $rsm);
$query->setParameter(1, 'romanb');
$users = $query->getResult();
Foreign keys are used by Doctrine for lazy-loading purposes when
@@ -387,12 +384,12 @@ associations that are lazy.
$rsm->addFieldResult('a', 'address_id', 'id');
$rsm->addFieldResult('a', 'street', 'street');
$rsm->addFieldResult('a', 'city', 'city');
$sql = 'SELECT u.id, u.name, a.id AS address_id, a.street, a.city FROM users u ' .
'INNER JOIN address a ON u.address_id = a.id WHERE u.name = ?';
$query = $this->_em->createNativeQuery($sql, $rsm);
$query = $this->em->createNativeQuery($sql, $rsm);
$query->setParameter(1, 'romanb');
$users = $query->getResult();
In this case the nested entity ``Address`` is registered with the
@@ -422,10 +419,10 @@ to map the hierarchy (both use a discriminator column).
$rsm->addFieldResult('u', 'name', 'name');
$rsm->addMetaResult('u', 'discr', 'discr'); // discriminator column
$rsm->setDiscriminatorColumn('u', 'discr');
$query = $this->_em->createNativeQuery('SELECT id, name, discr FROM users WHERE name = ?', $rsm);
$query = $this->em->createNativeQuery('SELECT id, name, discr FROM users WHERE name = ?', $rsm);
$query->setParameter(1, 'romanb');
$users = $query->getResult();
Note that in the case of Class Table Inheritance, an example as
@@ -442,8 +439,7 @@ You can also map a native query using a named native query mapping.
To achieve that, you must describe the SQL resultset structure
using named native query (and sql resultset mappings if is a several resultset mappings).
Like named query, a named native query can be defined at class level or in a XML or YAML file.
Like named query, a named native query can be defined at class level or in an XML file.
A resultSetMapping parameter is defined in @NamedNativeQuery,
it represents the name of a defined @SqlResultSetMapping.
@@ -538,47 +534,6 @@ it represents the name of a defined @SqlResultSetMapping.
</sql-result-set-mappings>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\User:
type: entity
namedNativeQueries:
fetchMultipleJoinsEntityResults:
name: fetchMultipleJoinsEntityResults
resultSetMapping: mappingMultipleJoinsEntityResults
query: SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username
sqlResultSetMappings:
mappingMultipleJoinsEntityResults:
name: mappingMultipleJoinsEntityResults
columnResult:
0:
name: numphones
entityResult:
0:
entityClass: __CLASS__
fieldResult:
0:
name: id
column: u_id
1:
name: name
column: u_name
2:
name: status
column: u_status
1:
entityClass: Address
fieldResult:
0:
name: id
column: a_id
1:
name: zip
column: a_zip
2:
name: country
column: a_country
Things to note:
- The resultset mapping declares the entities retrieved by this native query.
@@ -589,7 +544,6 @@ Things to note:
column name as the one declared on the class property.
- ``__CLASS__`` is an alias for the mapped class
In the above example,
the ``fetchJoinedAddress`` named query use the joinMapping result set mapping.
This mapping returns 2 entities, User and Address, each property is declared and associated to a column name,
@@ -655,21 +609,6 @@ Let's now see an implicit declaration of the property / column.
</sql-result-set-mappings>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\Address:
type: entity
namedNativeQueries:
findAll:
resultSetMapping: mappingFindAll
query: SELECT * FROM addresses
sqlResultSetMappings:
mappingFindAll:
name: mappingFindAll
entityResult:
address:
entityClass: Address
In this example, we only describe the entity member of the result set mapping.
The property / column mappings is done using the entity mapping values.
@@ -679,7 +618,6 @@ a @FieldResult element should be used for each foreign key column.
The @FieldResult name is composed of the property name for the relationship,
followed by a dot ("."), followed by the name or the field or property of the primary key.
.. configuration-block::
.. code-block:: php
@@ -758,41 +696,6 @@ followed by a dot ("."), followed by the name or the field or property of the pr
</sql-result-set-mappings>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\User:
type: entity
namedNativeQueries:
fetchJoinedAddress:
name: fetchJoinedAddress
resultSetMapping: mappingJoinedAddress
query: SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ?
sqlResultSetMappings:
mappingJoinedAddress:
entityResult:
0:
entityClass: __CLASS__
fieldResult:
0:
name: id
1:
name: name
2:
name: status
3:
name: address.id
column: a_id
4:
name: address.zip
column: a_zip
5:
name: address.city
column: a_city
6:
name: address.country
column: a_country
If you retrieve a single entity and if you use the default mapping,
you can use the resultClass attribute instead of resultSetMapping:
@@ -828,16 +731,6 @@ you can use the resultClass attribute instead of resultSetMapping:
</named-native-queries>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\Address:
type: entity
namedNativeQueries:
findAll:
name: findAll
resultClass: Address
query: SELECT * FROM addresses
In some of your native queries, you'll have to return scalar values,
for example when building report queries.
@@ -888,18 +781,3 @@ You actually can even mix, entities and scalar returns in the same native query
</sql-result-set-mappings>
</entity>
</doctrine-mapping>
.. code-block:: yaml
MyProject\Model\Address:
type: entity
namedNativeQueries:
count:
name: count
resultSetMapping: mappingCount
query: SELECT COUNT(*) AS count FROM addresses
sqlResultSetMappings:
mappingCount:
name: mappingCount
columnResult:
count:
name: count

View File

@@ -23,7 +23,6 @@ of Doctrine2 to this problem is.
to a fully-loaded object by calling ``EntityManager#refresh()``
or a DQL query with the refresh flag.
What is the problem?
--------------------
@@ -87,4 +86,3 @@ Mainly for optimization purposes, but be careful of premature
optimization as partial objects lead to potentially more fragile
code.

View File

@@ -180,18 +180,29 @@ It also has several methods that create builders (which are necessary for advanc
- ``createManyToMany($name, $targetEntity)`` returns an ``ManyToManyAssociationBuilder`` instance
- ``createOneToMany($name, $targetEntity)`` returns an ``OneToManyAssociationBuilder`` instance
ClassMetadataInfo API
ClassMetadata API
---------------------
The ``ClassMetadataInfo`` class is the base data object for storing
The ``ClassMetadata`` class is the base data object for storing
the mapping metadata for a single entity. It contains all the
getters and setters you need populate and retrieve information for
an entity.
Internal
~~~~~~~~
- ``getReflectionClass()``
- ``getReflectionProperties()``
- ``getReflectionProperty($name)``
- ``getSingleIdReflectionProperty()``
- ``getIdentifierValues($entity)``
- ``assignIdentifier($entity, $id)``
- ``setFieldValue($entity, $field, $value)``
- ``getFieldValue($entity, $field)``
General Setters
~~~~~~~~~~~~~~~
- ``setTableName($tableName)``
- ``setPrimaryTable(array $primaryTableDefinition)``
- ``setCustomRepositoryClass($repositoryClassName)``
@@ -204,7 +215,6 @@ General Setters
Inheritance Setters
~~~~~~~~~~~~~~~~~~~
- ``setInheritanceType($type)``
- ``setSubclasses(array $subclasses)``
- ``setParentClasses(array $classNames)``
@@ -214,24 +224,18 @@ Inheritance Setters
Field Mapping Setters
~~~~~~~~~~~~~~~~~~~~~
- ``mapField(array $mapping)``
- ``mapOneToOne(array $mapping)``
- ``mapOneToMany(array $mapping)``
- ``mapManyToOne(array $mapping)``
- ``mapManyToMany(array $mapping)``
- ``addProperty(Property $property)``
- ``addAssociation(AssociationMetadata $property)``
Lifecycle Callback Setters
~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``addLifecycleCallback($callback, $event)``
- ``setLifecycleCallbacks(array $callbacks)``
Versioning Setters
~~~~~~~~~~~~~~~~~~
- ``setVersionMapping(array &$mapping)``
- ``setVersioned($bool)``
- ``setVersionField()``
@@ -239,7 +243,6 @@ Versioning Setters
General Getters
~~~~~~~~~~~~~~~
- ``getTableName()``
- ``getSchemaName()``
- ``getTemporaryIdTableName()``
@@ -247,14 +250,8 @@ General Getters
Identifier Getters
~~~~~~~~~~~~~~~~~~
- ``getIdentifierColumnNames()``
- ``usesIdGenerator()``
- ``isIdentifier($fieldName)``
- ``isIdGeneratorIdentity()``
- ``isIdGeneratorSequence()``
- ``isIdGeneratorTable()``
- ``isIdentifierNatural()``
- ``getIdentifierFieldNames()``
- ``getSingleIdentifierFieldName()``
- ``getSingleIdentifierColumnName()``
@@ -262,35 +259,18 @@ Identifier Getters
Inheritance Getters
~~~~~~~~~~~~~~~~~~~
- ``isInheritanceTypeNone()``
- ``isInheritanceTypeJoined()``
- ``isInheritanceTypeSingleTable()``
- ``isInheritanceTypeTablePerClass()``
- ``isInheritedField($fieldName)``
- ``isInheritedAssociation($fieldName)``
Change Tracking Getters
~~~~~~~~~~~~~~~~~~~~~~~
- ``isChangeTrackingDeferredExplicit()``
- ``isChangeTrackingDeferredImplicit()``
- ``isChangeTrackingNotify()``
Field & Association Getters
~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``isUniqueField($fieldName)``
- ``isNullable($fieldName)``
- ``getColumnName($fieldName)``
- ``getFieldMapping($fieldName)``
- ``getAssociationMapping($fieldName)``
- ``getAssociationMappings()``
- ``getFieldName($columnName)``
- ``hasField($fieldName)``
- ``getColumnNames(array $fieldNames = null)``
- ``getTypeOfField($fieldName)``
- ``getTypeOfColumn($columnName)``
- ``hasAssociation($fieldName)``
@@ -300,26 +280,6 @@ Field & Association Getters
Lifecycle Callback Getters
~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``hasLifecycleCallbacks($lifecycleEvent)``
- ``getLifecycleCallbacks($event)``
ClassMetadata API
-----------------
The ``ClassMetadata`` class extends ``ClassMetadataInfo`` and adds
the runtime functionality required by Doctrine. It adds a few extra
methods related to runtime reflection for working with the entities
themselves.
- ``getReflectionClass()``
- ``getReflectionProperties()``
- ``getReflectionProperty($name)``
- ``getSingleIdReflectionProperty()``
- ``getIdentifierValues($entity)``
- ``setIdentifierValues($entity, $id)``
- ``setFieldValue($entity, $field, $value)``
- ``getFieldValue($entity, $field)``

View File

@@ -38,7 +38,6 @@ good example is to inspect what type of object the
There're currently 3 possible return values for ``getType()``:
- ``QueryBuilder::SELECT``, which returns value 0
- ``QueryBuilder::DELETE``, returning value 1
- ``QueryBuilder::UPDATE``, which returns value 2
@@ -66,7 +65,6 @@ performance. Any changes that may affect the generated DQL actually
modifies the state of ``QueryBuilder`` to a stage we call
STATE\_DIRTY. One ``QueryBuilder`` can be in two different states:
- ``QueryBuilder::STATE_CLEAN``, which means DQL haven't been
altered since last retrieval or nothing were added since its
instantiation
@@ -76,7 +74,6 @@ STATE\_DIRTY. One ``QueryBuilder`` can be in two different states:
Working with QueryBuilder
~~~~~~~~~~~~~~~~~~~~~~~~~
High level API methods
^^^^^^^^^^^^^^^^^^^^^^
@@ -247,8 +244,8 @@ while the named placeholders start with a : followed by a string.
Calling ``setParameter()`` automatically infers which type you are setting as
value. This works for integers, arrays of strings/integers, DateTime instances
and for managed entities. If you want to set a type explicitly you can call
the third argument to ``setParameter()`` explicitly. It accepts either a PDO
type or a DBAL Type name for conversion.
the third argument to ``setParameter()`` explicitly. It accepts either a DBAL
Doctrine\DBAL\ParameterType::* or a DBAL Type name for conversion.
If you've got several parameters to bind to your query, you can
also use setParameters() instead of setParameter() with the
@@ -379,7 +376,6 @@ complete list of supported helper methods available:
// Example - $qb->expr()->orX($cond1 [, $condN])->add(...)->...
public function orX($x = null); // Returns Expr\OrX instance
/** Comparison objects **/
// Example - $qb->expr()->eq('u.id', '?1') => u.id = ?1
@@ -406,7 +402,6 @@ complete list of supported helper methods available:
// Example - $qb->expr()->isNotNull('u.id') => u.id IS NOT NULL
public function isNotNull($x); // Returns string
/** Arithmetic objects **/
// Example - $qb->expr()->prod('u.id', '2') => u.id * 2
@@ -421,7 +416,6 @@ complete list of supported helper methods available:
// Example - $qb->expr()->quot('u.id', '2') => u.id / 2
public function quot($x, $y); // Returns Expr\Math instance
/** Pseudo-function objects **/
// Example - $qb->expr()->exists($qb2->getDql())
@@ -456,7 +450,6 @@ complete list of supported helper methods available:
// Example - $qb->expr()->between('u.id', '1', '10')
public function between($val, $x, $y); // Returns Expr\Func
/** Function objects **/
// Example - $qb->expr()->trim('u.firstname')
@@ -502,7 +495,7 @@ complete list of supported helper methods available:
Adding a Criteria to a Query
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can also add a :ref:`Criteria <filtering-collections>` to a QueryBuilder by
You can also add a :ref:`filtering-collections` to a QueryBuilder by
using ``addCriteria``:
.. code-block:: php
@@ -512,7 +505,7 @@ using ``addCriteria``:
// ...
$criteria = Criteria::create()
->orderBy(['firstName', 'ASC']);
->orderBy(['firstName' => Criteria::ASC]);
// $qb instanceof QueryBuilder
$qb->addCriteria($criteria);
@@ -531,7 +524,6 @@ one: ``add()``. This method is responsible of building every piece
of DQL. It takes 3 parameters: ``$dqlPartName``, ``$dqlPart`` and
``$append`` (default=false)
- ``$dqlPartName``: Where the ``$dqlPart`` should be placed.
Possible values: select, from, where, groupBy, having, orderBy
- ``$dqlPart``: What should be placed in ``$dqlPartName``. Accepts

View File

@@ -18,7 +18,6 @@ There are some flavors of caching available, but is better to cache read-only da
Be aware that caches are not aware of changes made to the persistent store by another application.
They can, however, be configured to regularly expire cached data.
Caching Regions
---------------
@@ -42,7 +41,6 @@ Something like below for an entity region :
'region_name:entity_3_hash' => ['id'=> 3, 'name' => 'Bar', 'associationName'=>['id'=>22]]
];
If the entity holds a collection that also needs to be cached.
An collection region could look something like :
@@ -66,12 +64,10 @@ A query region might be something like :
'region_name:query_3_hash' => ['list' => [2, 4]]
];
.. note::
The following data structures represents now the cache will looks like, this is not actual cached data.
.. _reference-second-level-cache-regions:
Cache Regions
@@ -87,7 +83,6 @@ It allows you to provide your own cache implementation that might take advantage
If you want to support locking for ``READ_WRITE`` strategies you should implement ``ConcurrentRegion``; ``CacheRegion`` otherwise.
Cache region
~~~~~~~~~~~~
@@ -97,7 +92,7 @@ Defines a contract for accessing a particular region.
Defines a contract for accessing a particular cache region.
`See API Doc <http://www.doctrine-project.org/api/orm/2.5/class-Doctrine.ORM.Cache.Region.html>`_.
`See API Doc <https://www.doctrine-project.org/api/orm/latest/Doctrine/ORM/Cache/Region.html>`_.
Concurrent cache region
~~~~~~~~~~~~~~~~~~~~~~~
@@ -111,7 +106,7 @@ If you want to use an ``READ_WRITE`` cache, you should consider providing your o
Defines contract for concurrently managed data region.
`See API Doc <http://www.doctrine-project.org/api/orm/2.5/class-Doctrine.ORM.Cache.ConcurrentRegion.html>`_.
`See API Doc <https://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/ConcurrentRegion.html>`_.
Timestamp region
~~~~~~~~~~~~~~~~
@@ -120,7 +115,7 @@ Timestamp region
Tracks the timestamps of the most recent updates to particular entity.
`See API Doc <http://www.doctrine-project.org/api/orm/2.5/class-Doctrine.ORM.Cache.TimestampRegion.html>`_.
`See API Doc <http://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/TimestampRegion.html>`_.
.. _reference-second-level-cache-mode:
@@ -138,7 +133,6 @@ Caching mode
* Read Write Cache doesnt employ any locks but can do reads, inserts, updates and deletes.
* Good if the application needs to update data rarely.
* ``READ_WRITE``
@@ -147,7 +141,6 @@ Caching mode
* Slowest strategy.
* To use it a the cache region implementation must support locking.
Built-in cached persisters
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -173,20 +166,20 @@ Configuration
-------------
Doctrine allows you to specify configurations and some points of extension for the second-level-cache
Enable Second Level Cache
~~~~~~~~~~~~~~~~~~~~~~~~~
To enable the second-level-cache, you should provide a cache factory
To enable the second-level-cache, you should provide a cache factory.
``\Doctrine\ORM\Cache\DefaultCacheFactory`` is the default implementation.
.. code-block:: php
<?php
/* @var $config \Doctrine\ORM\Cache\RegionsConfiguration */
/* @var $cache \Doctrine\Common\Cache\Cache */
/** @var \Doctrine\ORM\Cache\RegionsConfiguration $cacheConfig */
/** @var \Doctrine\Common\Cache\Cache $cache */
/** @var \Doctrine\ORM\Configuration $config */
$factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($config, $cache);
$factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($cacheConfig, $cache);
// Enable second-level-cache
$config->setSecondLevelCacheEnabled();
@@ -195,7 +188,6 @@ To enable the second-level-cache, you should provide a cache factory
$config->getSecondLevelCacheConfiguration()
->setCacheFactory($factory);
Cache Factory
~~~~~~~~~~~~~
@@ -209,7 +201,7 @@ It allows you to provide a specific implementation of the following components :
* ``EntityHydrator`` Transform an entity into a cache entry and cache entry into entities
* ``CollectionHydrator`` Transform a collection into a cache entry and cache entry into collection
`See API Doc <http://www.doctrine-project.org/api/orm/2.5/class-Doctrine.ORM.Cache.DefaultCacheFactory.html>`_.
`See API Doc <http://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/DefaultCacheFactory.html>`_.
Region Lifetime
~~~~~~~~~~~~~~~
@@ -219,8 +211,9 @@ To specify a default lifetime for all regions or specify a different lifetime fo
.. code-block:: php
<?php
/* @var $config \Doctrine\ORM\Configuration */
/* @var $cacheConfig \Doctrine\ORM\Cache\CacheConfiguration */
/** @var \Doctrine\ORM\Configuration $config */
/** @var \Doctrine\ORM\Cache\CacheConfiguration $cacheConfig */
/** @var \Doctrine\ORM\Cache\RegionsConfiguration $regionConfig */
$cacheConfig = $config->getSecondLevelCacheConfiguration();
$regionConfig = $cacheConfig->getRegionsConfiguration();
@@ -228,7 +221,6 @@ To specify a default lifetime for all regions or specify a different lifetime fo
$regionConfig->setLifetime('my_entity_region', 3600); // Time to live for a specific region; In seconds
$regionConfig->setDefaultLifetime(7200); // Default time to live; In seconds
Cache Log
~~~~~~~~~
By providing a cache logger you should be able to get information about all cache operations such as hits, misses and puts.
@@ -238,7 +230,7 @@ By providing a cache logger you should be able to get information about all cach
.. code-block:: php
<?php
/* @var $config \Doctrine\ORM\Configuration */
/** @var \Doctrine\ORM\Configuration $config */
$logger = new \Doctrine\ORM\Cache\Logging\StatisticsCacheLogger();
// Cache logger
@@ -246,7 +238,6 @@ By providing a cache logger you should be able to get information about all cach
$config->getSecondLevelCacheConfiguration()
->setCacheLogger($logger);
// Collect cache statistics
// Get the number of entries successfully retrieved from a specific region.
@@ -270,7 +261,7 @@ By providing a cache logger you should be able to get information about all cach
If you want to get more information you should implement ``\Doctrine\ORM\Cache\Logging\CacheLogger``.
and collect all information you want.
`See API Doc <http://www.doctrine-project.org/api/orm/2.5/class-Doctrine.ORM.Cache.CacheLogger.html>`_.
`See API Doc <http://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/Logging/CacheLogger.html>`_.
Entity cache definition
@@ -280,7 +271,6 @@ Entity cache definition
* ``usage`` Specifies the caching strategy: ``READ_ONLY``, ``NONSTRICT_READ_WRITE``, ``READ_WRITE``. see :ref:`reference-second-level-cache-mode`
* ``region`` Optional value that specifies the name of the second level cache region.
.. configuration-block::
.. code-block:: php
@@ -310,7 +300,7 @@ Entity cache definition
.. code-block:: xml
<?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 http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<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="Country">
<cache usage="READ_ONLY" region="my_entity_region" />
<id name="id" type="integer" column="id">
@@ -320,30 +310,11 @@ Entity cache definition
</entity>
</doctrine-mapping>
.. code-block:: yaml
Country:
type: entity
cache:
usage : READ_ONLY
region : my_entity_region
id:
id:
type: integer
id: true
generator:
strategy: IDENTITY
fields:
name:
type: string
Association cache definition
----------------------------
The most common use case is to cache entities. But we can also cache relationships.
It caches the primary keys of association and cache each element will be cached into its region.
.. configuration-block::
.. code-block:: php
@@ -386,7 +357,7 @@ It caches the primary keys of association and cache each element will be cached
.. code-block:: xml
<?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 http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<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="State">
<cache usage="NONSTRICT_READ_WRITE" />
@@ -396,7 +367,7 @@ It caches the primary keys of association and cache each element will be cached
</id>
<field name="name" type="string" column="name"/>
<many-to-one field="country" target-entity="Country">
<cache usage="NONSTRICT_READ_WRITE" />
@@ -411,39 +382,6 @@ It caches the primary keys of association and cache each element will be cached
</entity>
</doctrine-mapping>
.. code-block:: yaml
State:
type: entity
cache:
usage : NONSTRICT_READ_WRITE
id:
id:
type: integer
id: true
generator:
strategy: IDENTITY
fields:
name:
type: string
manyToOne:
state:
targetEntity: Country
joinColumns:
country_id:
referencedColumnName: id
cache:
usage : NONSTRICT_READ_WRITE
oneToMany:
cities:
targetEntity:City
mappedBy: state
cache:
usage : NONSTRICT_READ_WRITE
> Note: for this to work, the target entity must also be marked as cacheable.
Cache usage
@@ -461,8 +399,8 @@ Basic entity cache
$country1 = $em->find('Country', 1); // Retrieve item from cache
$country->setName("New Name");
$em->persist($country);
$country1->setName("New Name");
$em->flush(); // Hit database to update the row and update cache
$em->clear(); // Clear entity manager
@@ -470,7 +408,6 @@ Basic entity cache
$country2 = $em->find('Country', 1); // Retrieve item from cache
// Notice that $country1 and $country2 are not the same instance.
Association cache
.. code-block:: php
@@ -538,7 +475,7 @@ The query cache stores the results of the query but as identifiers, entity value
.. code-block:: php
<?php
/* @var $em \Doctrine\ORM\EntityManager */
/** @var \Doctrine\ORM\EntityManager $em */
// Execute database query, store query cache and entity cache
$result1 = $em->createQuery('SELECT c FROM Country c ORDER BY c.name')
@@ -565,7 +502,7 @@ The Cache Mode controls how a particular query interacts with the second-level c
.. code-block:: php
<?php
/* @var $em \Doctrine\ORM\EntityManager */
/** @var \Doctrine\ORM\EntityManager $em */
// Will refresh the query cache and all entities the cache as it reads from the database.
$result1 = $em->createQuery('SELECT c FROM Country c ORDER BY c.name')
->setCacheMode(Cache::MODE_GET)
@@ -583,37 +520,34 @@ DQL UPDATE / DELETE statements are ported directly into a database and bypass th
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.
Execute the ``UPDATE`` and invalidate ``all cache entries`` using ``Query::HINT_CACHE_EVICT``
.. code-block:: php
<?php
// Execute and invalidate
$this->_em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1")
$this->em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1")
->setHint(Query::HINT_CACHE_EVICT, true)
->execute();
Execute the ``UPDATE`` and invalidate ``all cache entries`` using the cache API
.. code-block:: php
<?php
// Execute
$this->_em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1")
$this->em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1")
->execute();
// Invoke Cache API
$em->getCache()->evictEntityRegion('Entity\Country');
Execute the ``UPDATE`` and invalidate ``a specific cache entry`` using the cache API
.. code-block:: php
<?php
// Execute
$this->_em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1")
$this->em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1")
->execute();
// Invoke Cache API
$em->getCache()->evictEntity('Entity\Country', 1);
@@ -653,7 +587,7 @@ However, you can use the cache API to check / invalidate cache entries.
.. code-block:: php
<?php
/* @var $cache \Doctrine\ORM\Cache */
/** @var \Doctrine\ORM\Cache $cache */
$cache = $em->getCache();
$cache->containsEntity('Entity\State', 1) // Check if the cache exists
@@ -698,11 +632,11 @@ For performance reasons the cache API does not extract from composite primary ke
}
// Supported
/* @var $article Article */
/** @var Article $article */
$article = $em->find('Article', 1);
// Supported
/* @var $article Article */
/** @var Article $article */
$article = $em->find('Article', $article);
// Supported
@@ -723,7 +657,6 @@ should be used in conjunction with distributed caching system such as memcached,
Caches should be used with care when using a load-balancer if you don't share the cache.
While using APC or any file based cache update occurred in a specific machine would not reflect to the cache in other machines.
Paginator
~~~~~~~~~

View File

@@ -10,7 +10,7 @@ we cannot protect you from SQL injection.
Please also read the documentation chapter on Security in Doctrine DBAL. This
page only handles Security issues in the ORM.
- [DBAL Security Page](https://github.com/doctrine/dbal/blob/master/docs/en/reference/security.rst)
- `DBAL Security Page <http://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
@@ -81,7 +81,6 @@ this is technically impossible. The correct way is:
$query = $entityManager->createQuery($dql);
$query->setParameter(1, $_GET['status']);
Preventing Mass Assignment Vulnerabilities
------------------------------------------
@@ -118,8 +117,8 @@ entity might look like this:
}
}
Now the possiblity of mass-asignment exists on this entity and can
be exploitet by attackers to set the "isAdmin" flag to true on any
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:
.. code-block:: php

View File

@@ -22,7 +22,6 @@ about the use of generate entities for example, you can call:
$> php vendor/bin/doctrine orm:generate-entities --help
Configuration
~~~~~~~~~~~~~
@@ -73,7 +72,7 @@ sample ``cli-config.php`` file looks as follows:
// Any way to access the EntityManager from your application
$em = GetMyEntityManager();
$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
@@ -84,7 +83,7 @@ script will ultimately use. The Doctrine Binary will automatically
find the first instance of HelperSet in the global variable
namespace and use this.
.. note::
.. note::
You have to adjust this snippet for your specific application or framework
and use their facilities to access the Doctrine EntityManager and
@@ -95,7 +94,6 @@ Command Overview
The following Commands are currently available:
- ``help`` Displays help for a command (?)
- ``list`` Lists commands
- ``dbal:import`` Import SQL file(s) directly to Database.
@@ -109,16 +107,10 @@ The following Commands are currently available:
cache drivers.
- ``orm:convert-d1-schema`` Converts Doctrine 1.X schema into a
Doctrine 2.X schema.
- ``orm:convert-mapping`` Convert mapping information between
supported formats.
- ``orm:ensure-production-settings`` Verify that Doctrine is
properly configured for a production environment.
- ``orm:generate-entities`` Generate entity classes and method
stubs from your mapping information.
- ``orm:generate-proxies`` Generates proxy classes for entity
classes.
- ``orm:generate-repositories`` Generate repository classes from
your mapping information.
- ``orm:run-dql`` Executes arbitrary DQL directly from the command
line.
- ``orm:schema-tool:create`` Processes the schema and either
@@ -133,12 +125,8 @@ The following Commands are currently available:
For these commands are also available aliases:
- ``orm:convert:d1-schema`` is alias for ``orm:convert-d1-schema``.
- ``orm:convert:mapping`` is alias for ``orm:convert-mapping``.
- ``orm:generate:entities`` is alias for ``orm:generate-entities``.
- ``orm:generate:proxies`` is alias for ``orm:generate-proxies``.
- ``orm:generate:repositories`` is alias for ``orm:generate-repositories``.
.. note::
@@ -164,7 +152,6 @@ Database Schema Generation
they are not related to the current project that is using Doctrine.
Please be careful!
To generate your database schema from your Doctrine mapping files
you can use the ``SchemaTool`` class or the ``schema-tool`` Console
Command.
@@ -173,7 +160,7 @@ When using the SchemaTool class directly, create your schema using
the ``createSchema()`` method. First create an instance of the
``SchemaTool`` and pass it an instance of the ``EntityManager``
that you want to use to create the schema. This method receives an
array of ``ClassMetadataInfo`` instances.
array of ``ClassMetadata`` instances.
.. code-block:: php
@@ -204,8 +191,8 @@ tables of the current model to clean up with orphaned tables.
You can also use database introspection to update your schema
easily with the ``updateSchema()`` method. It will compare your
existing database schema to the passed array of
``ClassMetadataInfo`` instances.
existing database schema to the passed array of ``ClassMetadata``
instances.
.. code-block:: php
@@ -261,163 +248,6 @@ your cli-config.php properly.
(or mapping files), i.e.
``new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em, $mappingPaths);``
Entity Generation
-----------------
Generate entity classes and method stubs from your mapping information.
.. code-block:: php
$ php doctrine orm:generate-entities
$ php doctrine orm:generate-entities --update-entities
$ php doctrine orm:generate-entities --regenerate-entities
This command is not suited for constant usage. It is a little helper and does
not support all the mapping edge cases very well. You still have to put work
in your entities after using this command.
It is possible to use the EntityGenerator on code that you have already written. It will
not be lost. The EntityGenerator will only append new code to your
file and will not delete the old code. However this approach may still be prone
to error and we suggest you use code repositories such as GIT or SVN to make
backups of your code.
It makes sense to generate the entity code if you are using entities as Data
Access Objects only and don't put much additional logic on them. If you are
however putting much more logic on the entities you should refrain from using
the entity-generator and code your entities manually.
.. note::
Even if you specified Inheritance options in your
XML or YAML Mapping files the generator cannot generate the base and
child classes for you correctly, because it doesn't know which
class is supposed to extend which. You have to adjust the entity
code manually for inheritance to work!
Convert Mapping Information
---------------------------
Convert mapping information between supported formats.
This is an **execute one-time** command. It should not be necessary for
you to call this method multiple times, especially when using the ``--from-database``
flag.
Converting an existing database schema into mapping files only solves about 70-80%
of the necessary mapping information. Additionally the detection from an existing
database cannot detect inverse associations, inheritance types,
entities with foreign keys as primary keys and many of the
semantical operations on associations such as cascade.
.. note::
There is no need to convert YAML or XML mapping files to annotations
every time you make changes. All mapping drivers are first class citizens
in Doctrine 2 and can be used as runtime mapping for the ORM. See the
docs on XML and YAML Mapping for an example how to register this metadata
drivers as primary mapping source.
To convert some mapping information between the various supported
formats you can use the ``ClassMetadataExporter`` to get exporter
instances for the different formats:
.. code-block:: php
<?php
$cme = new \Doctrine\ORM\Tools\Export\ClassMetadataExporter();
Once you have a instance you can use it to get an exporter. For
example, the yml exporter:
.. code-block:: php
<?php
$exporter = $cme->getExporter('yml', '/path/to/export/yml');
Now you can export some ``ClassMetadata`` instances:
.. code-block:: php
<?php
$classes = array(
$em->getClassMetadata('Entities\User'),
$em->getClassMetadata('Entities\Profile')
);
$exporter->setMetadata($classes);
$exporter->export();
This functionality is also available from the command line to
convert your loaded mapping information to another format. The
``orm:convert-mapping`` command accepts two arguments, the type to
convert to and the path to generate it:
.. code-block:: php
$ php doctrine orm:convert-mapping xml /path/to/mapping-path-converted-to-xml
Reverse Engineering
-------------------
You can use the ``DatabaseDriver`` to reverse engineer a database
to an array of ``ClassMetadataInfo`` instances and generate YAML,
XML, etc. from them.
.. note::
Reverse Engineering is a **one-time** process that can get you started with a project.
Converting an existing database schema into mapping files only detects about 70-80%
of the necessary mapping information. Additionally the detection from an existing
database cannot detect inverse associations, inheritance types,
entities with foreign keys as primary keys and many of the
semantical operations on associations such as cascade.
First you need to retrieve the metadata instances with the
``DatabaseDriver``:
.. code-block:: php
<?php
$em->getConfiguration()->setMetadataDriverImpl(
new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
$em->getConnection()->getSchemaManager()
)
);
$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);
$metadata = $cmf->getAllMetadata();
Now you can get an exporter instance and export the loaded metadata
to yml:
.. code-block:: php
<?php
$cme = new \Doctrine\ORM\Tools\Export\ClassMetadataExporter();
$exporter = $cme->getExporter('yml', '/path/to/export/yml');
$exporter->setMetadata($metadata);
$exporter->export();
You can also reverse engineer a database using the
``orm:convert-mapping`` command:
.. code-block:: php
$ php doctrine orm:convert-mapping --from-database yml /path/to/mapping-path-converted-to-yml
.. note::
Reverse Engineering is not always working perfectly
depending on special cases. It will only detect Many-To-One
relations (even if they are One-To-One) and will try to create
entities from Many-To-Many tables. It also has problems with naming
of foreign keys that have multiple column names. Any Reverse
Engineered Database-Schema needs considerable manual work to become
a useful domain model.
Runtime vs Development Mapping Validation
-----------------------------------------
@@ -463,7 +293,6 @@ number of elements with error messages.
prefix backslash. PHP does this with ``get_class()`` or Reflection
methods for backwards compatibility reasons.
Adding own commands
-------------------
@@ -509,7 +338,6 @@ defined ones) is possible through the command:
new \MyProject\Tools\Console\Commands\OneMoreCommand(),
));
Re-use console application
--------------------------

View File

@@ -68,7 +68,7 @@ looks like this:
// $em instanceof EntityManager
$em->getConnection()->beginTransaction(); // suspend auto-commit
try {
//... do some work
// ... do some work
$user = new User;
$user->setName('George');
$em->persist($user);
@@ -98,24 +98,16 @@ functionally equivalent to the previously shown code looks as follows:
<?php
// $em instanceof EntityManager
$em->transactional(function($em) {
//... do some work
// ... 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
commit and rolls back the transaction when an
exception occurs.
commit.
.. _transactions-and-concurrency_exception-handling:
@@ -208,15 +200,6 @@ example we'll use an integer.
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
fields:
version:
type: integer
version: true
Alternatively a datetime type can be used (which maps to a SQL
timestamp or datetime):
@@ -241,15 +224,6 @@ timestamp or datetime):
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
fields:
version:
type: datetime
version: true
Version numbers (not timestamps) should however be preferred as
they can not potentially conflict in a highly concurrent
environment, unlike timestamps where this is a possibility,
@@ -279,15 +253,15 @@ either when calling ``EntityManager#find()``:
<?php
use Doctrine\DBAL\LockMode;
use Doctrine\ORM\OptimisticLockException;
$theEntityId = 1;
$expectedVersion = 184;
try {
$entity = $em->find('User', $theEntityId, LockMode::OPTIMISTIC, $expectedVersion);
// do the work
$em->flush();
} catch(OptimisticLockException $e) {
echo "Sorry, but someone else has already changed this entity. Please apply the changes again!";
@@ -300,16 +274,16 @@ Or you can use ``EntityManager#lock()`` to find out:
<?php
use Doctrine\DBAL\LockMode;
use Doctrine\ORM\OptimisticLockException;
$theEntityId = 1;
$expectedVersion = 184;
$entity = $em->find('User', $theEntityId);
try {
// assert version
$em->lock($entity, LockMode::OPTIMISTIC, $expectedVersion);
} catch(OptimisticLockException $e) {
echo "Sorry, but someone else has already changed this entity. Please apply the changes again!";
}
@@ -348,7 +322,7 @@ See the example code, The form (GET Request):
<?php
$post = $em->find('BlogPost', 123456);
echo '<input type="hidden" name="id" value="' . $post->getId() . '" />';
echo '<input type="hidden" name="version" value="' . $post->getCurrentVersion() . '" />';
@@ -359,7 +333,7 @@ And the change headline action (POST Request):
<?php
$postId = (int)$_GET['id'];
$postVersion = (int)$_GET['version'];
$post = $em->find('BlogPost', $postId, \Doctrine\DBAL\LockMode::OPTIMISTIC, $postVersion);
.. _transactions-and-concurrency_pessimistic-locking:
@@ -382,7 +356,6 @@ transaction is running.
Doctrine 2 currently supports two pessimistic lock modes:
- Pessimistic Write
(``Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE``), locks the
underlying database rows for concurrent Read and Write Operations.
@@ -392,7 +365,6 @@ Doctrine 2 currently supports two pessimistic lock modes:
You can use pessimistic locks in three different scenarios:
1. Using
``EntityManager#find($className, $id, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)``
or
@@ -406,4 +378,3 @@ You can use pessimistic locks in three different scenarios:
or
``Query#setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_READ)``

View File

@@ -16,11 +16,11 @@ Bidirectional Associations
The following rules apply to **bidirectional** associations:
- The inverse side has to have the ``mappedBy`` attribute of the OneToOne,
OneToMany, or ManyToMany mapping declaration. The mappedBy
OneToMany, or ManyToMany mapping declaration. The ``mappedBy``
attribute contains the name of the association-field on the owning side.
- The owning side has to have the ``inversedBy`` attribute of the
OneToOne, ManyToOne, or ManyToMany mapping declaration.
The inversedBy attribute contains the name of the association-field
OneToOne, ManyToOne, or ManyToMany mapping declaration.
The ``inversedBy`` attribute contains the name of the association-field
on the inverse-side.
- ManyToOne is always the owning side of a bidirectional association.
- OneToMany is always the inverse side of a bidirectional association.

View File

@@ -36,13 +36,15 @@ will still end up with the same reference:
public function testIdentityMapReference()
{
$objectA = $this->entityManager->getReference('EntityName', 1);
// check for proxyinterface
$this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $objectA);
/** @var EntityName|\ProxyManager\Proxy\GhostObjectInterface $objectA */
$objectA = $this->entityManager->getReference(EntityName::class, 1);
$objectB = $this->entityManager->find('EntityName', 1);
self::assertInstanceOf(\ProxyManager\Proxy\GhostObjectInterface::class, $objectA);
self::assertFalse($objectA->isProxyInitialized());
$this->assertSame($objectA, $objectB)
$objectB = $this->entityManager->find(EntityName::class, 1);
self::assertSame($objectA, $objectB)
}
The identity map being indexed by primary keys only allows shortcuts when you
@@ -104,7 +106,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
necessarily know about the database at all. A natural question would now be,
"how does Doctrine even detect objects have changed?".
"how does Doctrine even detect objects have changed?".
For this Doctrine keeps a second map inside the UnitOfWork. Whenever you fetch
an object from the database Doctrine will keep a copy of all the properties and
@@ -129,12 +131,10 @@ optimize the performance of the Flush Operation:
- Temporarily mark entities as read only. If you have a very large UnitOfWork
but know that a large set of entities has not changed, just mark them as read
only with ``$entityManager->getUnitOfWork()->markReadOnly($entity)``.
- Flush only a single entity with ``$entityManager->flush($entity)``.
- Use :doc:`Change Tracking Policies <change-tracking-policies>` to use more
explicit strategies of notifying the UnitOfWork what objects/properties
changed.
Query Internals
---------------
@@ -198,4 +198,3 @@ ClassMetadataFactory
~~~~~~~~~~~~~~~~~~~~
tbr

View File

@@ -15,7 +15,7 @@ with associations in Doctrine:
removed, not the entity itself. A collection of entities always
only represents the association to the containing entities, not the
entity itself.
- When a bidirectional assocation is updated, Doctrine only checks
- When a bidirectional association is updated, Doctrine only checks
on one of both sides for these changes. This is called the :doc:`owning side <unitofwork-associations>`
of the association.
- A property with a reference to many entities has to be instances of the
@@ -37,7 +37,7 @@ information about its type and if it's the owning or inverse side.
{
/** @Id @GeneratedValue @Column(type="string") */
private $id;
/**
* Bidirectional - Many users have Many favorite comments (OWNING SIDE)
*
@@ -45,7 +45,7 @@ information about its type and if it's the owning or inverse side.
* @JoinTable(name="user_favorite_comments")
*/
private $favorites;
/**
* Unidirectional - Many users have marked many comments as read
*
@@ -53,14 +53,14 @@ information about its type and if it's the owning or inverse side.
* @JoinTable(name="user_read_comments")
*/
private $commentsRead;
/**
* Bidirectional - One-To-Many (INVERSE SIDE)
*
* @OneToMany(targetEntity="Comment", mappedBy="author")
*/
private $commentsAuthored;
/**
* Unidirectional - Many-To-One
*
@@ -68,20 +68,20 @@ information about its type and if it's the owning or inverse side.
*/
private $firstComment;
}
/** @Entity */
class Comment
{
/** @Id @GeneratedValue @Column(type="string") */
private $id;
/**
* Bidirectional - Many comments are favorited by many users (INVERSE SIDE)
*
* @ManyToMany(targetEntity="User", mappedBy="favorites")
*/
private $userFavorites;
/**
* Bidirectional - Many Comments are authored by one user (OWNING SIDE)
*
@@ -100,19 +100,19 @@ definitions omitted):
firstComment_id VARCHAR(255) DEFAULT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE Comment (
id VARCHAR(255) NOT NULL,
author_id VARCHAR(255) DEFAULT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE user_favorite_comments (
user_id VARCHAR(255) NOT NULL,
favorite_comment_id VARCHAR(255) NOT NULL,
PRIMARY KEY(user_id, favorite_comment_id)
) ENGINE = InnoDB;
CREATE TABLE user_read_comments (
user_id VARCHAR(255) NOT NULL,
comment_id VARCHAR(255) NOT NULL,
@@ -135,7 +135,7 @@ relations of the ``User``:
public function getReadComments() {
return $this->commentsRead;
}
public function setFirstComment(Comment $c) {
$this->firstComment = $c;
}
@@ -148,17 +148,17 @@ The interaction code would then look like in the following snippet
<?php
$user = $em->find('User', $userId);
// unidirectional many to many
$comment = $em->find('Comment', $readCommentId);
$user->getReadComments()->add($comment);
$em->flush();
// unidirectional many to one
$myFirstComment = new Comment();
$user->setFirstComment($myFirstComment);
$em->persist($myFirstComment);
$em->flush();
@@ -171,40 +171,40 @@ fields on both sides:
class User
{
// ..
public function getAuthoredComments() {
return $this->commentsAuthored;
}
public function getFavoriteComments() {
return $this->favorites;
}
}
class Comment
{
// ...
public function getUserFavorites() {
return $this->userFavorites;
}
public function setAuthor(User $author = null) {
$this->author = $author;
}
}
// Many-to-Many
$user->getFavorites()->add($favoriteComment);
$favoriteComment->getUserFavorites()->add($user);
$em->flush();
// Many-To-One / One-To-Many Bidirectional
$newComment = new Comment();
$user->getAuthoredComments()->add($newComment);
$newComment->setAuthor($user);
$em->persist($newComment);
$em->flush();
@@ -225,10 +225,10 @@ element. Here are some examples:
// Remove by Elements
$user->getComments()->removeElement($comment);
$comment->setAuthor(null);
$user->getFavorites()->removeElement($comment);
$comment->getUserFavorites()->removeElement($user);
// Remove by Key
$user->getComments()->remove($ithComment);
$comment->setAuthor(null);
@@ -240,7 +240,7 @@ Notice how both sides of the bidirectional association are always
updated. Unidirectional associations are consequently simpler to
handle.
Also note that if you use type-hinting in your methods, you will
Also note that if you use type-hinting in your methods, you will
have to specify a nullable type, i.e. ``setAddress(?Address $address)``,
otherwise ``setAddress(null)`` will fail to remove the association.
Another way to deal with this is to provide a special method, like
@@ -262,7 +262,6 @@ where n is the size of the map.
can often be used to improve performance by avoiding the loading of
the inverse collection.
You can also clear the contents of a whole collection using the
``Collections::clear()`` method. You should be aware that using
this method can lead to a straight and optimized database delete or
@@ -271,8 +270,8 @@ entities that have been re-added to the collection.
Say you clear a collection of tags by calling
``$post->getTags()->clear();`` and then call
``$post->getTags()->add($tag)``. This will not recognize the tag having
already been added previously and will consequently issue two separate database
``$post->getTags()->add($tag)``. This will not recognize the tag having
already been added previously and will consequently issue two separate database
calls.
Association Management Methods
@@ -291,12 +290,12 @@ example that encapsulate much of the association management code:
<?php
class User
{
//...
// ...
public function markCommentRead(Comment $comment) {
// Collections implement ArrayAccess
$this->commentsRead[] = $comment;
}
public function addComment(Comment $comment) {
if (count($this->commentsAuthored) == 0) {
$this->setFirstComment($comment);
@@ -304,30 +303,30 @@ example that encapsulate much of the association management code:
$this->comments[] = $comment;
$comment->setAuthor($this);
}
private function setFirstComment(Comment $c) {
$this->firstComment = $c;
}
public function addFavorite(Comment $comment) {
$this->favorites->add($comment);
$comment->addUserFavorite($this);
}
public function removeFavorite(Comment $comment) {
$this->favorites->removeElement($comment);
$comment->removeUserFavorite($this);
}
}
class Comment
{
// ..
public function addUserFavorite(User $user) {
$this->userFavorites[] = $user;
}
public function removeUserFavorite(User $user) {
$this->userFavorites->removeElement($user);
}
@@ -351,7 +350,6 @@ the details inside the classes can be challenging.
entity cannot circumvent the logic you implement on your entity for
association management. For example:
.. code-block:: php
<?php
@@ -373,7 +371,7 @@ as your preferences.
Synchronizing Bidirectional Collections
---------------------------------------
In the case of Many-To-Many associations you as the developer have the
In the case of Many-To-Many associations you as the developer have the
responsibility of keeping the collections on the owning and inverse side
in sync when you apply changes to them. Doctrine can only
guarantee a consistent state for the hydration, not for your client
@@ -387,13 +385,12 @@ can show the possible caveats you can encounter:
<?php
$user->getFavorites()->add($favoriteComment);
// not calling $favoriteComment->getUserFavorites()->add($user);
$user->getFavorites()->contains($favoriteComment); // TRUE
$favoriteComment->getUserFavorites()->contains($user); // FALSE
There are two approaches to handle this problem in your code:
1. Ignore updating the inverse side of bidirectional collections,
BUT never read from them in requests that changed their state. In
the next request Doctrine hydrates the consistent collection state
@@ -410,7 +407,7 @@ Transitive persistence / Cascade Operations
Doctrine 2 provides a mechanism for transitive persistence through cascading of certain operations.
Each association to another entity or a collection of
entities can be configured to automatically cascade the following operations to the associated entities:
``persist``, ``remove``, ``merge``, ``detach``, ``refresh`` or ``all``.
``persist``, ``remove``, ``refresh`` or ``all``.
The main use case for ``cascade: persist`` is to avoid "exposing" associated entities to your PHP application.
Continuing with the User-Comment example of this chapter, this is how the creation of a new user and a new
@@ -422,7 +419,7 @@ comment might look like in your controller (without ``cascade: persist``):
$user = new User();
$myFirstComment = new Comment();
$user->addComment($myFirstComment);
$em->persist($user);
$em->persist($myFirstComment); // required, if `cascade: persist` is not set
$em->flush();
@@ -463,14 +460,14 @@ If you then set up the cascading to the ``User#commentsAuthored`` property...
<?php
class User
{
//...
// ...
/**
* Bidirectional - One-To-Many (INVERSE SIDE)
*
* @OneToMany(targetEntity="Comment", mappedBy="author", cascade={"persist", "remove"})
*/
private $commentsAuthored;
//...
// ...
}
...you can now create a user and an associated comment like this:
@@ -480,7 +477,7 @@ If you then set up the cascading to the ``User#commentsAuthored`` property...
<?php
$user = new User();
$user->comment('Lorem ipsum', new DateTime());
$em->persist($user);
$em->flush();
@@ -529,7 +526,6 @@ operation. During each ``flush()`` operation Doctrine detects if there
are new entities in any collection and three possible cases can
happen:
1. New entities in a collection marked as ``cascade: persist`` will be
directly persisted by Doctrine.
2. New entities in a collection not marked as ``cascade: persist`` will
@@ -610,10 +606,10 @@ Now two examples of what happens when you remove the references:
$em->flush();
In this case you have not only changed the ``Contact`` entity itself but
you have also removed the references for standing data and as well as one
address reference. When flush is called not only are the references removed
but both the old standing data and the one address entity are also deleted
In this case you have not only changed the ``Contact`` entity itself but
you have also removed the references for standing data and as well as one
address reference. When flush is called not only are the references removed
but both the old standing data and the one address entity are also deleted
from the database.
.. _filtering-collections:
@@ -719,7 +715,6 @@ methods:
* ``startsWith($field, $value)``
* ``endsWith($field, $value)``
.. note::
There is a limitation on the compatibility of Criteria comparisons.

View File

@@ -25,6 +25,13 @@ Work that have not yet been persisted are lost.
Not calling ``EntityManager#flush()`` will lead to all changes
during that request being lost.
.. note::
Doctrine does NEVER touch the public API of methods in your entity
classes (like getters and setters) nor the constructor method.
Instead, it uses reflection to get/set data from/to your entity objects.
When Doctrine fetches data from DB and saves it back,
any code put in your get/set methods won't be implicitly taken into account.
Entities and the Identity Map
-----------------------------
@@ -41,7 +48,7 @@ headline "Hello World" with the ID 1234:
<?php
$article = $entityManager->find('CMS\Article', 1234);
$article->setHeadline('Hello World dude!');
$article2 = $entityManager->find('CMS\Article', 1234);
echo $article2->getHeadline();
@@ -93,25 +100,25 @@ from newly opened EntityManager.
{
/** @Id @Column(type="integer") @GeneratedValue */
private $id;
/** @Column(type="string") */
private $headline;
/** @ManyToOne(targetEntity="User") */
private $author;
/** @OneToMany(targetEntity="Comment", mappedBy="article") */
private $comments;
public function __construct()
{
$this->comments = new ArrayCollection();
}
public function getAuthor() { return $this->author; }
public function getComments() { return $this->comments; }
}
$article = $em->find('Article', 1);
This code only retrieves the ``Article`` instance with id 1 executing
@@ -132,22 +139,22 @@ your code. See the following code:
<?php
$article = $em->find('Article', 1);
// accessing a method of the user instance triggers the lazy-load
echo "Author: " . $article->getAuthor()->getName() . "\n";
// Lazy Loading Proxies pass instanceof tests:
if ($article->getAuthor() instanceof User) {
// a User Proxy is a generated "UserProxy" class
}
// accessing the comments as an iterator triggers the lazy-load
// retrieving ALL the comments of this article from the database
// using a single SELECT statement
foreach ($article->getComments() as $comment) {
echo $comment->getText() . "\n\n";
}
// Article::$comments passes instanceof tests for the Collection interface
// But it will NOT pass for the ArrayCollection interface
if ($article->getComments() instanceof \Doctrine\Common\Collections\Collection) {
@@ -155,25 +162,28 @@ your code. See the following code:
}
A slice of the generated proxy classes code looks like the
following piece of code. A real proxy class override ALL public
methods along the lines of the ``getName()`` method shown below:
following piece of code. A real proxy class override all non-identity
non-transient object state at instantiation time in order to
enable lazy-loading mechanisms:
.. code-block:: php
<?php
class UserProxy extends User implements Proxy
class UserProxyHASH extends User implements GhostObjectInterface
{
private function _load()
// ... generated code
public static function staticProxyConstructor($initializer)
{
// lazy loading code
// ... generated code
}
public function getName()
private function callInitializerHASH($methodName, array $parameters)
{
$this->_load();
return parent::getName();
// ... generated code
}
// .. other public methods of User
// ... generated code
}
.. warning::
@@ -183,7 +193,6 @@ methods along the lines of the ``getName()`` method shown below:
to heavily. Make sure to use DQL to fetch-join all the parts of the
object-graph that you need as efficiently as possible.
Persisting entities
-------------------
@@ -206,7 +215,6 @@ be properly synchronized with the database when
database in the most efficient way and a single, short transaction,
taking care of maintaining referential integrity.
Example:
.. code-block:: php
@@ -227,18 +235,16 @@ Example:
generated identifier being not available after a failed flush
operation.
The semantics of the persist operation, applied on an entity X, are
as follows:
- If X is a new entity, it becomes managed. The entity X will be
entered into the database as a result of the flush operation.
- If X is a preexisting managed entity, it is ignored by the
persist operation. However, the persist operation is cascaded to
entities referenced by X, if the relationships from X to these
other entities are mapped with cascade=PERSIST or cascade=ALL (see
":ref:`Transitive Persistence <transitive-persistence>`").
":ref:`transitive-persistence`").
- If X is a removed entity, it becomes managed.
- If X is a detached entity, an exception will be thrown on
flush.
@@ -262,7 +268,6 @@ which means that its persistent state will be deleted once
for and appear in query and collection results. See
the section on :ref:`Database and UnitOfWork Out-Of-Sync <workingobjects_database_uow_outofsync>`
for more information.
Example:
@@ -275,16 +280,15 @@ Example:
The semantics of the remove operation, applied to an entity X are
as follows:
- If X is a new entity, it is ignored by the remove operation.
However, the remove operation is cascaded to entities referenced by
X, if the relationship from X to these other entities is mapped
with cascade=REMOVE or cascade=ALL (see ":ref:`Transitive Persistence <transitive-persistence>`").
with cascade=REMOVE or cascade=ALL (see ":ref:`transitive-persistence`").
- If X is a managed entity, the remove operation causes it to
become removed. The remove operation is cascaded to entities
referenced by X, if the relationships from X to these other
entities is mapped with cascade=REMOVE or cascade=ALL (see
":ref:`Transitive Persistence <transitive-persistence>`").
":ref:`transitive-persistence`").
- If X is a detached entity, an InvalidArgumentException will be
thrown.
- If X is a removed entity, it is ignored by the remove operation.
@@ -304,11 +308,10 @@ foreign key semantics of onDelete="CASCADE".
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 2
will fetch this association. If its a Single association it will
will fetch this association. If it is 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()\`.
´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
@@ -326,133 +329,39 @@ in multiple ways with very different performance impacts.
Detaching entities
------------------
An entity is detached from an EntityManager and thus no longer
managed by invoking the ``EntityManager#detach($entity)`` method on
it or by cascading the detach operation to it. Changes made to the
detached entity, if any (including removal of the entity), will not
be synchronized to the database after the entity has been
All entities are detached from an EntityManager and thus no longer
managed by it after invoking the ``EntityManager#clear()`` method.
Changes made to the detached entities, if any (including their removal),
will not be synchronized to the database after they have been
detached.
Doctrine will not hold on to any references to a detached entity.
Doctrine will not hold on to any references to detached entities.
Example:
.. code-block:: php
<?php
$em->detach($entity);
$em->clear();
The semantics of the detach operation, applied to an entity X are
as follows:
- If X is a managed entity, the detach operation causes it to
become detached. The detach operation is cascaded to entities
referenced by X, if the relationships from X to these other
entities is mapped with cascade=DETACH or cascade=ALL (see
":ref:`Transitive Persistence <transitive-persistence>`"). Entities which previously referenced X
- If X is a managed entity, the ``clear`` operation causes it to
become detached. Entities which previously referenced X
will continue to reference X.
- If X is a new or detached entity, it is ignored by the detach
operation.
- If X is a removed entity, the detach operation is cascaded to
entities referenced by X, if the relationships from X to these
other entities is mapped with cascade=DETACH or cascade=ALL (see
":ref:`Transitive Persistence <transitive-persistence>`"). Entities which previously referenced X
will continue to reference X.
- If X is a removed entity, it will become detached, and therefore
no longer scheduled to be removed. Entities which previously
referenced X will continue to reference X.
There are several situations in which an entity is detached
automatically without invoking the ``detach`` method:
automatically:
- When ``EntityManager#clear()`` is invoked, all entities that are
currently managed by the EntityManager instance become detached.
- When serializing an entity. The entity retrieved upon subsequent
unserialization will be detached (This is the case for all entities
that are serialized and stored in some cache, i.e. when using the
Query Result Cache).
The ``detach`` operation is usually not as frequently needed and
used as ``persist`` and ``remove``.
Merging entities
----------------
Merging entities refers to the merging of (usually detached)
entities into the context of an EntityManager so that they become
managed again. To merge the state of an entity into an
EntityManager use the ``EntityManager#merge($entity)`` method. The
state of the passed entity will be merged into a managed copy of
this entity and this copy will subsequently be returned.
Example:
.. code-block:: php
<?php
$detachedEntity = unserialize($serializedEntity); // some detached entity
$entity = $em->merge($detachedEntity);
// $entity now refers to the fully managed copy returned by the merge operation.
// The EntityManager $em now manages the persistence of $entity as usual.
.. note::
When you want to serialize/unserialize entities you
have to make all entity properties protected, never private. The
reason for this is, if you serialize a class that was a proxy
instance before, the private variables won't be serialized and a
PHP Notice is thrown.
The semantics of the merge operation, applied to an entity X, are
as follows:
- If X is a detached entity, the state of X is copied onto a
pre-existing managed entity instance X' of the same identity.
- If X is a new entity instance, a new managed copy X' will be
created and the state of X is copied onto this managed instance.
- If X is a removed entity instance, an InvalidArgumentException
will be thrown.
- If X is a managed entity, it is ignored by the merge operation,
however, the merge operation is cascaded to entities referenced by
relationships from X if these relationships have been mapped with
the cascade element value MERGE or ALL (see ":ref:`Transitive Persistence <transitive-persistence>`").
- For all entities Y referenced by relationships from X having the
cascade element value MERGE or ALL, Y is merged recursively as Y'.
For all such Y referenced by X, X' is set to reference Y'. (Note
that if X is managed then X is the same object as X'.)
- If X is an entity merged to X', with a reference to another
entity Y, where cascade=MERGE or cascade=ALL is not specified, then
navigation of the same association from X' yields a reference to a
managed object Y' with the same persistent identity as Y.
The ``merge`` operation will throw an ``OptimisticLockException``
if the entity being merged uses optimistic locking through a
version field and the versions of the entity being merged and the
managed copy don't match. This usually means that the entity has
been modified while being detached.
The ``merge`` operation is usually not as frequently needed and
used as ``persist`` and ``remove``. The most common scenario for
the ``merge`` operation is to reattach entities to an EntityManager
that come from some cache (and are therefore detached) and you want
to modify and persist such an entity.
.. warning::
If you need to perform multiple merges of entities that share certain subparts
of their object-graphs and cascade merge, then you have to call ``EntityManager#clear()`` between the
successive calls to ``EntityManager#merge()``. Otherwise you might end up with
multiple copies of the "same" object in the database, however with different ids.
.. note::
If you load some detached entities from a cache and you do
not need to persist or delete them or otherwise make use of them
without the need for persistence services there is no need to use
``merge``. I.e. you can simply pass detached objects from a cache
directly to the view.
unserialization will be detached (this is the case for all entities
that are serialized and stored in some cache).
Synchronization with the Database
---------------------------------
@@ -495,7 +404,6 @@ Synchronizing New and Managed Entities
The flush operation applies to a managed entity with the following
semantics:
- The entity itself is synchronized to the database using a SQL
UPDATE statement, only if at least one persistent field has
changed.
@@ -504,14 +412,12 @@ semantics:
The flush operation applies to a new entity with the following
semantics:
- The entity itself is synchronized to the database using a SQL
INSERT statement.
For all (initialized) relationships of the new or managed entity
the following semantics apply to each associated entity X:
- If X is new and persist operations are configured to cascade on
the relationship, X will be persisted.
- If X is new and no persist operations are configured to cascade
@@ -543,7 +449,6 @@ The cost of flushing
How costly a flush operation is, mainly depends on two factors:
- The size of the EntityManager's current UnitOfWork.
- The configured change tracking policies
@@ -563,14 +468,13 @@ during development.
.. note::
Do not invoke ``flush`` after every change to an entity
or every single invocation of persist/remove/merge/... This is an
or every single invocation of persist/remove/refresh/... This is an
anti-pattern and unnecessarily reduces the performance of your
application. Instead, form units of work that operate on your
objects and call ``flush`` when you are done. While serving a
single HTTP request there should be usually no need for invoking
``flush`` more than 0-2 times.
Direct access to a Unit of Work
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -590,7 +494,6 @@ instance the EntityManager is currently using.
marked as INTERNAL by not using them and carefully read the API
documentation.
Entity State
~~~~~~~~~~~~
@@ -626,7 +529,7 @@ An entity is in DETACHED state if it has persistent state and
identity but is currently not associated with an
``EntityManager``.
An entity is in NEW state if has no persistent state and identity
An entity is in NEW state if it has no persistent state and identity
and is not associated with an ``EntityManager`` (for example those
just created via the "new" operator).
@@ -680,13 +583,13 @@ methods on a repository as follows:
<?php
// $em instanceof EntityManager
// All users that are 20 years old
$users = $em->getRepository('MyProject\Domain\User')->findBy(array('age' => 20));
// All users that are 20 years old and have a surname of 'Miller'
$users = $em->getRepository('MyProject\Domain\User')->findBy(array('age' => 20, 'surname' => 'Miller'));
// A single user by its nickname
$user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('nickname' => 'romanb'));
@@ -722,7 +625,7 @@ examples are equivalent:
<?php
// A single user by its nickname
$user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('nickname' => 'romanb'));
// A single user by its nickname (__call magic)
$user = $em->getRepository('MyProject\Domain\User')->findOneByNickname('romanb');
@@ -739,8 +642,8 @@ By Criteria
.. versionadded:: 2.3
The Repository implement the ``Doctrine\Common\Collections\Selectable``
interface. That means you can build ``Doctrine\Common\Collections\Criteria``
The Repository implements the ``Doctrine\Common\Collections\Selectable``
interface. It means you can build ``Doctrine\Common\Collections\Criteria``
and pass them to the ``matching($criteria)`` method.
See section `Filtering collections` of chapter :doc:`Working with Associations <working-with-associations>`
@@ -750,7 +653,7 @@ By Eager Loading
Whenever you query for an entity that has persistent associations
and these associations are mapped as EAGER, they will automatically
be loaded together with the entity being queried and is thus
be loaded together with the entity being queried and are thus
immediately available to your application.
By Lazy Loading
@@ -780,7 +683,7 @@ A DQL query is represented by an instance of the
<?php
// $em instanceof EntityManager
// All users with an age between 20 and 30 (inclusive).
$q = $em->createQuery("select u from MyDomain\Model\User u where u.age >= 20 and u.age <= 30");
$users = $q->getResult();
@@ -814,7 +717,7 @@ By default the EntityManager returns a default implementation of
``Doctrine\ORM\EntityRepository`` when you call
``EntityManager#getRepository($entityClass)``. You can overwrite
this behaviour by specifying the class name of your own Entity
Repository in the Annotation, XML or YAML metadata. In large
Repository in the Annotation or XML metadata. In large
applications that require lots of specialized DQL queries using a
custom repository is one recommended way of grouping these queries
in a central location.
@@ -823,23 +726,23 @@ in a central location.
<?php
namespace MyDomain\Model;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="MyDomain\Model\UserRepository")
*/
class User
{
}
class UserRepository extends EntityRepository
{
public function getAllAdminUsers()
{
return $this->_em->createQuery('SELECT u FROM MyDomain\Model\User u WHERE u.status = "admin"')
return $this->em->createQuery('SELECT u FROM MyDomain\Model\User u WHERE u.status = "admin"')
->getResult();
}
}
@@ -850,7 +753,6 @@ You can access your repository now by calling:
<?php
// $em instanceof EntityManager
$admins = $em->getRepository('MyDomain\Model\User')->getAllAdminUsers();

View File

@@ -7,7 +7,7 @@ form of XML documents.
The XML driver is backed by an XML Schema document that describes
the structure of a mapping document. The most recent version of the
XML Schema document is available online at
`http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd <http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd>`_.
`https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd <https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd>`_.
In order to point to the latest version of the document of a
particular stable release branch, just append the release number,
i.e.: doctrine-mapping-2.0.xsd The most convenient way to work with
@@ -21,7 +21,7 @@ setup for the latest code in trunk.
<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://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd">
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
...
@@ -31,7 +31,6 @@ The XML mapping document of a class is loaded on-demand the first
time it is requested and subsequently stored in the metadata cache.
In order to work, this requires certain conventions:
- Each entity/mapped superclass must get its own dedicated XML
mapping document.
- The name of the mapping document must consist of the fully
@@ -107,7 +106,7 @@ of several common elements:
<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
http://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd">
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
@@ -194,12 +193,10 @@ specified as the ``<entity />`` element as a direct child of the
Required attributes:
- name - The fully qualified class-name of the entity.
Optional attributes:
- **table** - The Table-Name to be used for this entity. Otherwise the
Unqualified Class-Name is used by default.
- **repository-class** - The fully qualified class-name of an
@@ -241,13 +238,11 @@ entity. For the ID mapping you have to use the ``<id />`` element.
Required attributes:
- name - The name of the Property/Field on the given Entity PHP
class.
Optional attributes:
- type - The ``Doctrine\DBAL\Types\Type`` name, defaults to
"string"
- column - Name of the column in the database, defaults to the
@@ -305,7 +300,6 @@ subset of the ``<field />`` element attributes:
Required attributes:
- name - The name of the Property/Field on the given Entity PHP
class.
- type - The ``Doctrine\DBAL\Types\Type`` name, preferably
@@ -313,7 +307,6 @@ Required attributes:
Optional attributes:
- column - Name of the column in the database, defaults to the
field name.
@@ -339,7 +332,6 @@ have to use the ``NONE`` strategy.
The following values are allowed for the ``<generator />`` strategy
attribute:
- AUTO - Automatic detection of the identifier strategy based on
the preferred solution of the database vendor.
- IDENTITY - Use of a IDENTIFY strategy such as Auto-Increment IDs
@@ -362,12 +354,10 @@ element to describe the sequence:
Required attributes for ``<sequence-generator />``:
- sequence-name - The name of the sequence
Optional attributes for ``<sequence-generator />``:
- allocation-size - By how much steps should the sequence be
incremented when a value is retrieved. Defaults to 1
- initial-value - What should the initial value of the sequence
@@ -380,7 +370,6 @@ Optional attributes for ``<sequence-generator />``:
element, if Doctrine chooses the sequence strategy for a
platform.
Defining a Mapped Superclass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -400,7 +389,6 @@ can define it in XML using the ``<mapped-superclass />`` tag.
Required attributes:
- name - Class name of the mapped superclass.
You can nest any number of ``<field />`` and unidirectional
@@ -440,7 +428,6 @@ The allowed values for inheritance-type attribute are ``JOINED`` or
All inheritance related definitions have to be defined on the root
entity of the hierarchy.
Defining Lifecycle Callbacks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -473,7 +460,6 @@ For the inverse side the mapping is as simple as:
Required attributes for inverse One-To-One:
- field - Name of the property/field on the entity's PHP class.
- target-entity - Name of the entity associated entity class. If
this is not qualified the namespace of the current class is
@@ -491,7 +477,6 @@ For the owning side this mapping would look like:
Required attributes for owning One-to-One:
- field - Name of the property/field on the entity's PHP class.
- target-entity - Name of the entity associated entity class. If
this is not qualified the namespace of the current class is
@@ -499,7 +484,6 @@ Required attributes for owning One-to-One:
Optional attributes for owning One-to-One:
- inversed-by - If the association is bidirectional the
inversed-by attribute has to be specified with the name of the
field on the inverse entity that contains the back-reference.
@@ -542,7 +526,6 @@ like:
Required attributes:
- field - Name of the property/field on the entity's PHP class.
- target-entity - Name of the entity associated entity class. If
this is not qualified the namespace of the current class is
@@ -550,7 +533,6 @@ Required attributes:
Optional attributes:
- inversed-by - If the association is bidirectional the
inversed-by attribute has to be specified with the name of the
field on the inverse entity that contains the back-reference.
@@ -593,7 +575,6 @@ exists for bi-directional associations.
Required attributes:
- field - Name of the property/field on the entity's PHP class.
- target-entity - Name of the entity associated entity class. If
this is not qualified the namespace of the current class is
@@ -603,7 +584,6 @@ Required attributes:
Optional attributes:
- fetch - Either LAZY, EXTRA_LAZY or EAGER, defaults to LAZY.
- index-by: Index the collection by a field on the target entity.
@@ -622,7 +602,6 @@ definitions and rely on their implicit values.
Required attributes:
- field - Name of the property/field on the entity's PHP class.
- target-entity - Name of the entity associated entity class. If
this is not qualified the namespace of the current class is
@@ -630,7 +609,6 @@ Required attributes:
Optional attributes:
- mapped-by - Name of the field on the owning side that contains
the owning side association if the defined many-to-many association
is on the inverse side.
@@ -686,9 +664,7 @@ tags.
Besides ``<cascade-all />`` the following operations can be
specified by their respective tags:
- ``<cascade-persist />``
- ``<cascade-merge />``
- ``<cascade-remove />``
- ``<cascade-refresh />``
@@ -701,14 +677,12 @@ key names are called that are used for joining two entities.
Required attributes:
- name - The column name of the foreign key.
- referenced-column-name - The column name of the associated
entities primary key
Optional attributes:
- unique - If the join column should contain a UNIQUE constraint.
This makes sense for Many-To-Many join-columns only to simulate a
one-to-many unidirectional using a join-table.
@@ -768,7 +742,7 @@ entity relationship. You can define this in XML with the "association-key" attri
<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
http://raw.github.com/doctrine/doctrine2/master/doctrine-mapping.xsd">
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Application\Model\ArticleAttribute">
<id name="article" association-key="true" />

View File

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

82
docs/en/sidebar.rst Normal file
View File

@@ -0,0 +1,82 @@
.. toc::
.. tocheader:: Tutorials
.. 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
.. toc::
.. tocheader:: Reference
.. 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/xml-mapping
reference/annotations-reference
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/implementing-wakeup-or-clone
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

@@ -1,87 +0,0 @@
Welcome to Doctrine 2 ORM's documentation!
==========================================
Tutorials
---------
.. toctree::
:maxdepth: 1
tutorials/getting-started
tutorials/getting-started-database
tutorials/getting-started-models
tutorials/working-with-indexed-associations
tutorials/extra-lazy-associations
tutorials/composite-primary-keys
tutorials/ordered-associations
tutorials/override-field-association-mappings-in-subclasses
tutorials/pagination.rst
tutorials/embeddables.rst
Reference Guide
---------------
.. toctree::
:maxdepth: 1
:numbered:
reference/architecture
reference/configuration.rst
reference/faq
reference/basic-mapping
reference/association-mapping
reference/inheritance-mapping
reference/working-with-objects
reference/working-with-associations
reference/events
reference/unitofwork
reference/unitofwork-associations
reference/transactions-and-concurrency
reference/batch-processing
reference/dql-doctrine-query-language
reference/query-builder
reference/native-sql
reference/change-tracking-policies
reference/partial-objects
reference/xml-mapping
reference/yaml-mapping
reference/annotations-reference
reference/php-mapping
reference/caching
reference/improving-performance
reference/tools
reference/metadata-drivers
reference/best-practices
reference/limitations-and-known-issues
tutorials/pagination
reference/filters
reference/namingstrategy
reference/advanced-configuration
reference/second-level-cache
reference/security
Cookbook
--------
.. toctree::
:maxdepth: 1
cookbook/aggregate-fields
cookbook/custom-mapping-types
cookbook/decorator-pattern
cookbook/dql-custom-walkers
cookbook/dql-user-defined-functions
cookbook/implementing-arrayaccess-for-domain-objects
cookbook/implementing-the-notify-changetracking-policy
cookbook/implementing-wakeup-or-clone
cookbook/integrating-with-codeigniter
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

@@ -28,16 +28,19 @@ and year of production as primary keys:
.. code-block:: php
<?php
namespace VehicleCatalogue\Model;
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @ORM\Entity
*/
class Car
{
/** @Id @Column(type="string") */
/** @ORM\Id @ORM\Column(type="string") */
private $name;
/** @Id @Column(type="integer") */
/** @ORM\Id @ORM\Column(type="integer") */
private $year;
public function __construct($name, $year)
@@ -63,7 +66,7 @@ and year of production as primary keys:
<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
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="VehicleCatalogue\Model\Car">
<id field="name" type="string" />
@@ -71,16 +74,6 @@ and year of production as primary keys:
</entity>
</doctrine-mapping>
.. code-block:: yaml
VehicleCatalogue\Model\Car:
type: entity
id:
name:
type: string
year:
type: integer
Now you can use this entity:
.. code-block:: php
@@ -137,9 +130,8 @@ of one or many parent entities.
The semantics of mapping identity through foreign entities are easy:
- Only allowed on Many-To-One or One-To-One associations.
- Plug an ``@Id`` annotation onto every association.
- Plug an ``@ORM\Id`` annotation onto every association.
- Set an attribute ``association-key`` with the field name of the association in XML.
- Set a key ``associationKey:`` with the field name of the association in YAML.
Use-Case 1: Dynamic Attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -154,19 +146,21 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
namespace Application\Model;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @ORM\Entity
*/
class Article
{
/** @Id @Column(type="integer") @GeneratedValue */
/** @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue */
private $id;
/** @Column(type="string") */
/** @ORM\Column(type="string") */
private $title;
/**
* @OneToMany(targetEntity="ArticleAttribute", mappedBy="article", cascade={"ALL"}, indexBy="attribute")
* @ORM\OneToMany(targetEntity="ArticleAttribute", mappedBy="article", cascade={"ALL"}, indexBy="attribute")
*/
private $attributes;
@@ -177,17 +171,17 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
}
/**
* @Entity
* @ORM\Entity
*/
class ArticleAttribute
{
/** @Id @ManyToOne(targetEntity="Article", inversedBy="attributes") */
/** @ORM\Id @ORM\ManyToOne(targetEntity="Article", inversedBy="attributes") */
private $article;
/** @Id @Column(type="string") */
/** @ORM\Id @ORM\Column(type="string") */
private $attribute;
/** @Column(type="string") */
/** @ORM\Column(type="string") */
private $value;
public function __construct($name, $value, $article)
@@ -203,12 +197,12 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
<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
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Application\Model\ArticleAttribute">
<id name="article" association-key="true" />
<id name="attribute" type="string" />
<field name="value" type="string" />
<many-to-one field="article" target-entity="Article" inversed-by="attributes" />
@@ -216,24 +210,6 @@ We keep up the example of an Article with arbitrary attributes, the mapping look
</doctrine-mapping>
.. code-block:: yaml
Application\Model\ArticleAttribute:
type: entity
id:
article:
associationKey: true
attribute:
type: string
fields:
value:
type: string
manyToOne:
article:
targetEntity: Article
inversedBy: attributes
Use-Case 2: Simple Derived Identity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -246,44 +222,27 @@ One good example for this is a user-address relationship:
.. code-block:: php
<?php
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @ORM\Entity
*/
class User
{
/** @Id @Column(type="integer") @GeneratedValue */
/** @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue */
private $id;
}
/**
* @Entity
* @ORM\Entity
*/
class Address
{
/** @Id @OneToOne(targetEntity="User") */
/** @ORM\Id @ORM\OneToOne(targetEntity="User") */
private $user;
}
.. code-block:: yaml
User:
type: entity
id:
id:
type: integer
generator:
strategy: AUTO
Address:
type: entity
id:
user:
associationKey: true
oneToOne:
user:
targetEntity: User
Use-Case 3: Join-Table with Metadata
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -295,23 +254,27 @@ of products purchased and maybe even the current price.
<?php
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Annotation as ORM;
/** @Entity */
/** @ORM\Entity */
class Order
{
/** @Id @Column(type="integer") @GeneratedValue */
/** @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue */
private $id;
/** @ManyToOne(targetEntity="Customer") */
/** @ORM\ManyToOne(targetEntity="Customer") */
private $customer;
/** @OneToMany(targetEntity="OrderItem", mappedBy="order") */
/** @ORM\OneToMany(targetEntity="OrderItem", mappedBy="order") */
private $items;
/** @Column(type="boolean") */
private $payed = false;
/** @Column(type="boolean") */
/** @ORM\Column(type="boolean") */
private $paid = false;
/** @ORM\Column(type="boolean") */
private $shipped = false;
/** @Column(type="datetime") */
/** @ORM\Column(type="datetime") */
private $created;
public function __construct(Customer $customer)
@@ -322,16 +285,16 @@ of products purchased and maybe even the current price.
}
}
/** @Entity */
/** @ORM\Entity */
class Product
{
/** @Id @Column(type="integer") @GeneratedValue */
/** @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue */
private $id;
/** @Column(type="string") */
/** @ORM\Column(type="string") */
private $name;
/** @Column(type="decimal") */
/** @ORM\Column(type="decimal") */
private $currentPrice;
public function getCurrentPrice()
@@ -340,19 +303,19 @@ of products purchased and maybe even the current price.
}
}
/** @Entity */
/** @ORM\Entity */
class OrderItem
{
/** @Id @ManyToOne(targetEntity="Order") */
/** @ORM\Id @ORM\ManyToOne(targetEntity="Order") */
private $order;
/** @Id @ManyToOne(targetEntity="Product") */
/** @ORM\Id @ORM\ManyToOne(targetEntity="Product") */
private $product;
/** @Column(type="integer") */
/** @ORM\Column(type="integer") */
private $amount = 1;
/** @Column(type="decimal") */
/** @ORM\Column(type="decimal") */
private $offeredPrice;
public function __construct(Order $order, Product $product, $amount = 1)
@@ -363,7 +326,6 @@ of products purchased and maybe even the current price.
}
}
Performance Considerations
~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -4,7 +4,7 @@ Separating Concerns using Embeddables
Embeddables are classes which are not entities themselves, but are embedded
in entities and can also be queried in DQL. You'll mostly want to use them
to reduce duplication or separating concerns. Value objects such as date range
or address are the primary use case for this feature.
or address are the primary use case for this feature.
.. note::
@@ -21,26 +21,28 @@ instead of simply adding the respective columns to the ``User`` class.
<?php
/** @Entity */
use Doctrine\ORM\Annotation as ORM;
/** @ORM\Entity */
class User
{
/** @Embedded(class = "Address") */
/** @ORM\Embedded(class = "Address") */
private $address;
}
/** @Embeddable */
/** @ORM\Embeddable */
class Address
{
/** @Column(type = "string") */
/** @ORM\Column(type = "string") */
private $street;
/** @Column(type = "string") */
/** @ORM\Column(type = "string") */
private $postalCode;
/** @Column(type = "string") */
/** @ORM\Column(type = "string") */
private $city;
/** @Column(type = "string") */
/** @ORM\Column(type = "string") */
private $country;
}
@@ -59,22 +61,6 @@ instead of simply adding the respective columns to the ``User`` class.
</embeddable>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
embedded:
address:
class: Address
Address:
type: embeddable
fields:
street: { type: string }
postalCode: { type: string }
city: { type: string }
country: { type: string }
In terms of your database schema, Doctrine will automatically inline all
columns from the ``Address`` class into the table of the ``User`` class,
just as if you had declared them directly there.
@@ -113,10 +99,12 @@ The following example shows you how to set your prefix to ``myPrefix_``:
<?php
/** @Entity */
use Doctrine\ORM\Annotation as ORM;
/** @ORM\Entity */
class User
{
/** @Embedded(class = "Address", columnPrefix = "myPrefix_") */
/** @ORM\Embedded(class = "Address", columnPrefix = "myPrefix_") */
private $address;
}
@@ -126,15 +114,6 @@ The following example shows you how to set your prefix to ``myPrefix_``:
<embedded name="address" class="Address" column-prefix="myPrefix_" />
</entity>
.. code-block:: yaml
User:
type: entity
embedded:
address:
class: Address
columnPrefix: myPrefix_
To have Doctrine drop the prefix and use the value object's property name
directly, set ``columnPrefix=false`` (``use-column-prefix="false"`` for XML):
@@ -144,29 +123,21 @@ directly, set ``columnPrefix=false`` (``use-column-prefix="false"`` for XML):
<?php
/** @Entity */
use Doctrine\ORM\Annotation as ORM;
/** @ORM\Entity */
class User
{
/** @Embedded(class = "Address", columnPrefix = false) */
/** @ORM\Embedded(class = "Address", columnPrefix = false) */
private $address;
}
.. code-block:: yaml
User:
type: entity
embedded:
address:
class: Address
columnPrefix: false
.. code-block:: xml
<entity name="User">
<embedded name="address" class="Address" use-column-prefix="false" />
</entity>
DQL
---

View File

@@ -34,7 +34,6 @@ Additionally even with Doctrine 2.0 the following methods do not trigger the col
With extra lazy collections you can now not only add entities to large collections but also paginate them
easily using a combination of ``count`` and ``slice``.
Enabling Extra-Lazy Associations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -46,15 +45,18 @@ switch to extra lazy as shown in these examples:
.. code-block:: php
<?php
namespace Doctrine\Tests\Models\CMS;
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @ORM\Entity
*/
class CmsGroup
{
/**
* @ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
* @ORM\ManyToMany(targetEntity="CmsUser", mappedBy="groups", fetch="EXTRA_LAZY")
*/
public $users;
}
@@ -65,22 +67,10 @@ switch to extra lazy as shown in these examples:
<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
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\Models\CMS\CmsGroup">
<!-- ... -->
<many-to-many field="users" target-entity="CmsUser" mapped-by="groups" fetch="EXTRA_LAZY" />
</entity>
</doctrine-mapping>
.. code-block:: yaml
Doctrine\Tests\Models\CMS\CmsGroup:
type: entity
# ...
manyToMany:
users:
targetEntity: CmsUser
mappedBy: groups
fetch: EXTRA_LAZY

View File

@@ -7,7 +7,7 @@ Getting Started: Database First
start with developing Objects and then map them onto your database. When
you :doc:`Model First <getting-started-models>`, you are modelling your application using tools (for
example UML) and generate database schema and PHP code from this model.
When you have a :doc:`Database First <getting-started-database>`, you already have a database schema
When you have a Database First, you already have a database schema
and generate the corresponding PHP code from it.
.. note::

View File

@@ -5,7 +5,7 @@ Getting Started: Model First
When you :doc:`Code First <getting-started>`, you
start with developing Objects and then map them onto your database. When
you :doc:`Model First <getting-started-models>`, you are modelling your application using tools (for
you Model First, you are modelling your application using tools (for
example UML) and generate database schema and PHP code from this model.
When you have a :doc:`Database First <getting-started-database>`, then you already have a database schema
and generate the corresponding PHP code from it.

File diff suppressed because it is too large Load Diff

View File

@@ -5,26 +5,29 @@ There are use-cases when you'll want to sort collections when they are
retrieved from the database. In userland you do this as long as you
haven't initially saved an entity with its associations into the
database. To retrieve a sorted collection from the database you can
use the ``@OrderBy`` annotation with an collection that specifies
use the ``@ORM\OrderBy`` annotation with an collection that specifies
an DQL snippet that is appended to all queries with this
collection.
Additional to any ``@OneToMany`` or ``@ManyToMany`` annotation you
can specify the ``@OrderBy`` in the following way:
Additional to any ``@ORM\OneToMany`` or ``@ORM\ManyToMany`` annotation
you can specify the ``@ORM\OrderBy`` in the following way:
.. configuration-block::
.. code-block:: php
<?php
/** @Entity **/
use Doctrine\ORM\Annotation as ORM;
/** @ORM\Entity **/
class User
{
// ...
/**
* @ManyToMany(targetEntity="Group")
* @OrderBy({"name" = "ASC"})
* @ORM\ManyToMany(targetEntity="Group")
* @ORM\OrderBy({"name" = "ASC"})
**/
private $groups;
}
@@ -41,39 +44,21 @@ can specify the ``@OrderBy`` in the following way:
</entity>
</doctrine-mapping>
.. code-block:: yaml
User:
type: entity
manyToMany:
groups:
orderBy: { 'name': 'ASC' }
targetEntity: Group
joinTable:
name: users_groups
joinColumns:
user_id:
referencedColumnName: id
inverseJoinColumns:
group_id:
referencedColumnName: id
The DQL Snippet in OrderBy is only allowed to consist of
unqualified, unquoted field names and of an optional ASC/DESC
positional statement. Multiple Fields are separated by a comma (,).
The referenced field names have to exist on the ``targetEntity``
class of the ``@ManyToMany`` or ``@OneToMany`` annotation.
class of the ``@ORM\ManyToMany`` or ``@ORM\OneToMany`` annotation.
The semantics of this feature can be described as follows.
The semantics of this feature can be described as follows:
- ``@OrderBy`` acts as an implicit ORDER BY clause for the given
- ``@ORM\OrderBy`` acts as an implicit ORDER BY clause for the given
fields, that is appended to all the explicitly given ORDER BY
items.
- All collections of the ordered type are always retrieved in an
ordered fashion.
- To keep the database impact low, these implicit ORDER BY items
are only added to an DQL Query if the collection is fetch joined in
are only added to a DQL Query if the collection is fetch joined in
the DQL query.
Given our previously defined example, the following would not add
@@ -107,4 +92,3 @@ You can reverse the order with an explicit DQL ORDER BY:
SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC, g.name ASC

View File

@@ -14,12 +14,15 @@ Suppose we have a class ExampleEntityWithOverride. This class uses trait Example
.. code-block:: php
<?php
use Doctrine\ORM\Annotation as ORM;
/**
* @Entity
* @ORM\Entity
*
* @AttributeOverrides({
* @AttributeOverride(name="foo",
* column=@Column(
* @ORM\AttributeOverrides({
* @ORM\AttributeOverride(name="foo",
* column=@ORM\Column(
* name = "foo_overridden",
* type = "integer",
* length = 140,
@@ -29,9 +32,9 @@ Suppose we have a class ExampleEntityWithOverride. This class uses trait Example
* )
* })
*
* @AssociationOverrides({
* @AssociationOverride(name="bar",
* joinColumns=@JoinColumn(
* @ORM\AssociationOverrides({
* @ORM\AssociationOverride(name="bar",
* joinColumns=@ORM\JoinColumn(
* name="example_entity_overridden_bar_id", referencedColumnName="id"
* )
* )
@@ -43,11 +46,11 @@ Suppose we have a class ExampleEntityWithOverride. This class uses trait Example
}
/**
* @Entity
* @ORM\Entity
*/
class Bar
{
/** @Id @Column(type="string") */
/** @ORM\Id @ORM\Column(type="string") */
private $id;
}
@@ -59,22 +62,25 @@ which has mapping metadata that is overridden by the annotation above:
.. code-block:: php
<?php
use Doctrine\ORM\Annotation as ORM;
/**
* Trait class
*/
trait ExampleTrait
{
/** @Id @Column(type="string") */
/** @ORM\Id @ORM\Column(type="string") */
private $id;
/**
* @Column(name="trait_foo", type="integer", length=100, nullable=true, unique=true)
* @ORM\Column(name="trait_foo", type="integer", length=100, nullable=true, unique=true)
*/
protected $foo;
/**
* @OneToOne(targetEntity="Bar", cascade={"persist", "merge"})
* @JoinColumn(name="example_trait_bar_id", referencedColumnName="id")
* @ORM\OneToOne(targetEntity="Bar", cascade={"persist", "refresh"})
* @ORM\JoinColumn(name="example_trait_bar_id", referencedColumnName="id")
*/
protected $bar;
}
@@ -89,4 +95,4 @@ The case for just extending a class would be just the same but:
// ...
}
Overriding is also supported via XML and YAML (:ref:`examples <inheritence_mapping_overrides>`).
Overriding is also supported via XML (:ref:`examples <inheritence_mapping_overrides>`).

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