Compare commits

..

15 Commits

Author SHA1 Message Date
Andrii Dembitskyi cccb2e2fdf Docs: use canonical order for phpdoc tags, add missed semicolon (#9190) 2021-12-20 22:23:47 +01:00
Benjamin Eberlei 18138d895e Make PrimaryReadReplicaConnection enforcement explicit (#9239)
* Move primary replica connection logic into ORM explicitly.

* Housekeeping: Use full named variables

* Housekeeping: phpcs
2021-12-20 13:50:25 +01:00
Benjamin Eberlei fa2b52c974 [docs] Fix wording for attributes=>parameters. (#9265) 2021-12-18 11:16:35 +01:00
olsavmic 5bf814032f Revert "Fix SchemaValidator with abstract child class in discriminator map (#9096)" (#9262)
This reverts commit bbb68d0072.
2021-12-18 11:01:30 +01:00
Andrii Dembitskyi 02a4e4099d Docs: consistency for FQCN, spacing, etc (#9232)
* Docs: consistent spacing, consistent array-style, consistent FQCN, avoid double escaped slashes, avoid double quotes if not necessary

* Docs: use special note block instead of markdown-based style

* Docs: Quote FQCN in table with backticks to be compatible with all render engines

* Drop all mentions API doc - it is not available anymore

* Add missed FQCN for code snippets
2021-12-13 23:10:01 +01:00
Alexander M. Turek 12a70bbefb PHPCS 3.6.2, Psalm 4.15.0 (#9247) 2021-12-13 21:28:56 +01:00
Grégoire Paris 5a4ddb2870 Merge pull request #9184 from ThomasLandauer/patch-1
[Documentation] Events Overview Table: Adding "Passed Argument" column
2021-12-12 16:21:13 +01:00
Alexander M. Turek 68fa55f310 Remove fallbacks for old doctrine/annotations version (#9235) 2021-12-11 17:11:34 +01:00
Thomas Landauer 0b0c3e7e58 Update docs/en/reference/events.rst
Co-authored-by: Grégoire Paris <postmaster@greg0ire.fr>
2021-12-09 12:00:30 +01:00
Kevin van Sonsbeek 92434f91c7 Added psalm param to abstract addFilterConstraint (#9229) 2021-12-08 22:31:52 +00:00
Alexander Schranz 6414ad4cbb Merge pull request #9210 from alexander-schranz/patch-2
Fix making columns  optional in indexes xml schema as they can be defined via fields now
2021-12-06 00:55:01 +01:00
Thomas Landauer 8b6fe52f74 Update events.rst 2021-12-01 01:01:04 +01:00
Thomas Landauer 32cd2106d0 Completing links to EventArgs classes in overview table
Questions:
1. Is https://github.com/doctrine/persistence/blob/master/lib/Doctrine/Persistence/Event/LifecycleEventArgs.php correct at all? Shouldn't this be https://github.com/doctrine/orm/blob/2.10.x/lib/Doctrine/ORM/Event/LifecycleEventArgs.php, like all the others?

2. Which one is correct for `preUpdate`? https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/events.html#entity-listeners-class says `PreUpdateEventArgs`, but https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/events.html#listening-and-subscribing-to-lifecycle-events says `LifecycleEventArgs`

For the two links to `doctrine/persistence`, I'm linking to `/master/` now, which is being forwarded to `/2.2.x/`.
2021-11-30 15:51:20 +01:00
Thomas Landauer 77b7107d05 Using const for type 2021-11-23 01:41:01 +01:00
Thomas Landauer 2dde65c4ba [Documentation] Events Overview Table: Adding "Passed Argument" column
As announced in https://github.com/doctrine/orm/pull/9160#issuecomment-954304588 I'm adding the passed "EventArgs" class to the overview table. Once this is complete, my further plan is to remove the entire paragraph https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/events.html#lifecycle-callbacks-event-argument, and probably also the second code block at https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/events.html#entity-listeners-class

Is there a better way to link to the source code of `LifecycleEventArgs` than https://github.com/doctrine/persistence/blob/2.2.x/lib/Doctrine/Persistence/Event/LifecycleEventArgs.php ?

Also, I changed `postLoad` to `preUpdate` in the code block, to have an example that does not receive `LifecycleEventArgs` ;-)
2021-11-11 00:22:25 +01:00
20 changed files with 219 additions and 233 deletions
+2 -2
View File
@@ -41,10 +41,10 @@
"phpbench/phpbench": "^0.16.10 || ^1.0",
"phpstan/phpstan": "1.2.0",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.4",
"squizlabs/php_codesniffer": "3.6.1",
"squizlabs/php_codesniffer": "3.6.2",
"symfony/cache": "^4.4 || ^5.2",
"symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0",
"vimeo/psalm": "4.13.1"
"vimeo/psalm": "4.15.0"
},
"conflict": {
"doctrine/annotations": "<1.13 || >= 2.0"
@@ -4,7 +4,7 @@ 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
@@ -15,7 +15,7 @@ type `Point <https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.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,9 +29,9 @@ The entity class:
.. code-block:: php
<?php
namespace Geo\Entity;
/**
* @Entity
*/
@@ -84,7 +84,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 +92,7 @@ The point class:
.. code-block:: php
<?php
namespace Geo\ValueObject;
class Point
@@ -196,7 +196,7 @@ 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.
@@ -210,13 +210,13 @@ 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 +252,5 @@ Example usage
$query = $em->createQuery("SELECT l FROM Geo\Entity\Location l WHERE l.address = '1600 Amphitheatre Parkway, Mountain View, CA'");
$location = $query->getSingleResult();
/* @var Geo\ValueObject\Point */
/** @var Geo\ValueObject\Point */
$point = $location->getPoint();
+8 -8
View File
@@ -88,7 +88,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 +101,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();
}
}
@@ -137,13 +137,13 @@ implementation is:
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 +196,7 @@ modify the generation of the SELECT clause, adding the
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 +204,7 @@ modify the generation of the SELECT clause, adding the
$sql = str_replace('SELECT', 'SELECT SQL_NO_CACHE', $sql);
}
}
return $sql;
}
}
+12 -12
View File
@@ -45,7 +45,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
@@ -96,7 +96,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 +106,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(' .
@@ -180,28 +180,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(' .
+27 -27
View File
@@ -59,12 +59,12 @@ inside the instance variables PHP DocBlock comment. Any value hold
inside this variable will be saved to and loaded from the database
as part of the lifecycle of the instance variables entity-class.
Required attributes:
Required parameters:
- **type**: Name of the DBAL Type which does the conversion between PHP
and Database representation.
Optional attributes:
Optional parameters:
- **name**: By default the property name is used for the database
column name also, however the ``name`` attribute allows you to
@@ -165,7 +165,7 @@ Examples:
~~~~~~~~
Add caching strategy to a root entity or a collection.
Optional attributes:
Optional parameters:
- **usage**: One of ``READ_ONLY``, ``READ_WRITE`` or ``NONSTRICT_READ_WRITE``, By default this is ``READ_ONLY``.
- **region**: An specific region name
@@ -210,7 +210,7 @@ Example:
This attribute allows you to specify a user-provided class to generate identifiers. This attribute only works when both :ref:`#[Id] <attrref_id>` and :ref:`#[GeneratedValue(strategy: "CUSTOM")] <attrref_generatedvalue>` are specified.
Required attributes:
Required parameters:
- **class**: name of the class which should extend Doctrine\ORM\Id\AbstractIdGenerator
@@ -244,13 +244,13 @@ actually instantiated as.
If this attribute is not specified, the discriminator column defaults
to a string column of length 255 called ``dtype``.
Required attributes:
Required parameters:
- **name**: The column name of the discriminator. This name is also
used during Array hydration as key to specify the class-name.
Optional attributes:
Optional parameters:
- **type**: By default this is string.
@@ -319,7 +319,7 @@ attribute to establish the relationship between the two classes.
The embedded attribute is required on an entity's member variable,
in order to specify that it is an embedded class.
Required attributes:
Required parameters:
- **class**: The embeddable class
@@ -331,7 +331,7 @@ Required attributes:
Required attribute to mark a PHP class as an entity. Doctrine manages
the persistence of all classes marked as entities.
Optional attributes:
Optional parameters:
- **repositoryClass**: Specifies the FQCN of a subclass of the
``EntityRepository``. Use of repositories for entities is encouraged to keep
@@ -368,7 +368,7 @@ conjunction with #[Id].
If this attribute is not specified with ``#[Id]`` the ``NONE`` strategy is
used as default.
Optional attributes:
Optional parameters:
- **strategy**: Set the name of the identifier generation strategy.
Valid values are ``AUTO``, ``SEQUENCE``, ``IDENTITY``, ``UUID``
@@ -424,14 +424,14 @@ Attribute is used on the entity-class level. It provides a hint to the SchemaToo
generate a database index on the specified table columns. It only
has meaning in the ``SchemaTool`` schema generation context.
Required attributes:
Required parameters:
- **name**: Name of the Index
- **fields**: Array of fields. Exactly one of **fields, columns** is required.
- **columns**: Array of columns. Exactly one of **fields, columns** is required.
Optional attributes:
Optional parameters:
- **options**: Array of platform specific options:
@@ -548,7 +548,7 @@ The ``#[InverseJoinColumn]`` is the same as ``#[JoinColumn]`` and is used in the
of a ``#[ManyToMany]`` attribute declaration to specifiy the details of the join table's
column information used for the join to the inverse entity.
Optional attributes:
Optional parameters:
- **name**: Column name that holds the foreign key identifier for
this relation. In the context of ``#[JoinTable]`` it specifies the column
@@ -623,14 +623,14 @@ Example:
Defines that the annotated instance variable holds a reference that
describes a many-to-one relationship between two entities.
Required attributes:
Required parameters:
- **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:
Optional parameters:
- **cascade**: Cascade Option
@@ -659,14 +659,14 @@ additional, optional attribute that has reasonable default
configuration values using the table and names of the two related
entities.
Required attributes:
Required parameters:
- **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:
Optional parameters:
- **mappedBy**: This option specifies the property name on the
@@ -720,7 +720,7 @@ The ``#[MappedSuperclass]`` attribute cannot be used in conjunction with
``#[Entity]``. See the Inheritance Mapping section for
:doc:`more details on the restrictions of mapped superclasses <inheritance-mapping>`.
Optional attributes:
Optional parameters:
- **repositoryClass**: Specifies the FQCN of a subclass of the EntityRepository.
That will be inherited for all subclasses of that Mapped Superclass.
@@ -756,13 +756,13 @@ be specified. When no
:ref:`#[JoinColumn] <attrref_joincolumn>` is specified it defaults to using the target entity table and
primary key column names and the current naming strategy to determine a name for the join column.
Required attributes:
Required parameters:
- **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:
Optional parameters:
- **cascade**: Cascade Option
- **fetch**: One of LAZY or EAGER
@@ -786,13 +786,13 @@ Example:
#[OneToMany]
~~~~~~~~~~~~
Required attributes:
Required parameters:
- **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:
Optional parameters:
- **cascade**: Cascade Option
- **orphanRemoval**: Boolean that specifies if orphans, inverse
@@ -916,11 +916,11 @@ For use with ``#[GeneratedValue(strategy: "SEQUENCE")]`` this
attribute allows to specify details about the sequence, such as
the increment size and initial values of the sequence.
Required attributes:
Required parameters:
- **sequenceName**: Name of the sequence
Optional attributes:
Optional parameters:
- **allocationSize**: Increment the sequence by the allocation size
when its fetched. A value larger than 1 allows optimization for
@@ -954,11 +954,11 @@ placed on the entity-class level and is optional. If it is
not specified the table name will default to the entity's
unqualified classname.
Required attributes:
Required parameters:
- **name**: Name of the table
Optional attributes:
Optional parameters:
- **schema**: Name of the schema the table lies in.
@@ -985,12 +985,12 @@ generate a database unique constraint on the specified table
columns. It only has meaning in the SchemaTool schema generation
context.
Required attributes:
Required parameters:
- **name**: Name of the Index
- **columns**: Array of columns.
Optional attributes:
Optional parameters:
- **options**: Array of platform specific options:
+57 -43
View File
@@ -135,38 +135,38 @@ see :ref:`Lifecycle Callbacks<lifecycle-callbacks>`
Events Overview
---------------
+-----------------------------------------------------------------+-----------------------+-----------+
| Event | Dispatched by | Lifecycle |
| | | Callback |
+=================================================================+=======================+===========+
| :ref:`preRemove<reference-events-pre-remove>` | ``$em->remove()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postRemove<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`prePersist<reference-events-pre-persist>` | ``$em->persist()`` | Yes |
| | on *initial* persist | |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postPersist<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`preUpdate<reference-events-pre-update>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postUpdate<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postLoad<reference-events-post-load>` | Loading from database | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`loadClassMetadata<reference-events-load-class-metadata>` | Loading of mapping | No |
| | metadata | |
+-----------------------------------------------------------------+-----------------------+-----------+
| ``onClassMetadataNotFound`` | ``MappingException`` | No |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`preFlush<reference-events-pre-flush>` | ``$em->flush()`` | Yes |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`onFlush<reference-events-on-flush>` | ``$em->flush()`` | No |
+-----------------------------------------------------------------+-----------------------+-----------+
| :ref:`postFlush<reference-events-post-flush>` | ``$em->flush()`` | No |
+-----------------------------------------------------------------+-----------------------+-----------+
| ``onClear`` | ``$em->clear()`` | No |
+-----------------------------------------------------------------+-----------------------+-----------+
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| Event | Dispatched by | Lifecycle | Passed |
| | | Callback | Argument |
+=================================================================+=======================+===========+=====================================+
| :ref:`preRemove<reference-events-pre-remove>` | ``$em->remove()`` | Yes | `_LifecycleEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postRemove<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `_LifecycleEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`prePersist<reference-events-pre-persist>` | ``$em->persist()`` | Yes | `_LifecycleEventArgs`_ |
| | on *initial* persist | | |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postPersist<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `_LifecycleEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`preUpdate<reference-events-pre-update>` | ``$em->flush()`` | Yes | `_PreUpdateEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postUpdate<reference-events-post-update-remove-persist>` | ``$em->flush()`` | Yes | `_LifecycleEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postLoad<reference-events-post-load>` | Loading from database | Yes | `_LifecycleEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`loadClassMetadata<reference-events-load-class-metadata>` | Loading of mapping | No | `_LoadClassMetadataEventArgs` |
| | metadata | | |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| ``onClassMetadataNotFound`` | ``MappingException`` | No | `_OnClassMetadataNotFoundEventArgs` |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`preFlush<reference-events-pre-flush>` | ``$em->flush()`` | Yes | `_PreFlushEventArgs`_ |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`onFlush<reference-events-on-flush>` | ``$em->flush()`` | No | `_OnFlushEventArgs` |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| :ref:`postFlush<reference-events-post-flush>` | ``$em->flush()`` | No | `_PostFlushEventArgs` |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
| ``onClear`` | ``$em->clear()`` | No | `_OnClearEventArgs` |
+-----------------------------------------------------------------+-----------------------+-----------+-------------------------------------+
Naming convention
~~~~~~~~~~~~~~~~~
@@ -296,6 +296,9 @@ specific to a particular entity class's lifecycle.
.. code-block:: attribute
<?php
use Doctrine\DBAL\Types\Types;
use Doctrine\Persistence\Event\LifecycleEventArgs;
/**
* #[Entity]
@@ -305,11 +308,11 @@ specific to a particular entity class's lifecycle.
{
// ...
#[Column(type: 'string', length: 255)]
#[Column(type: Types::STRING, length: 255)]
public $value;
#[PrePersist]
public function doStuffOnPrePersist()
public function doStuffOnPrePersist(LifecycleEventArgs $eventArgs)
{
$this->createdAt = date('Y-m-d H:i:s');
}
@@ -320,15 +323,17 @@ specific to a particular entity class's lifecycle.
$this->value = 'changed from prePersist callback!';
}
#[PostLoad]
public function doStuffOnPostLoad()
#[PreUpdate]
public function doStuffOnPreUpdate(PreUpdateEventArgs $eventArgs)
{
$this->value = 'changed from postLoad callback!';
$this->value = 'changed from preUpdate callback!';
}
}
.. code-block:: annotation
<?php
use Doctrine\Persistence\Event\LifecycleEventArgs;
/**
* @Entity
@@ -342,7 +347,7 @@ specific to a particular entity class's lifecycle.
public $value;
/** @PrePersist */
public function doStuffOnPrePersist()
public function doStuffOnPrePersist(LifecycleEventArgs $eventArgs)
{
$this->createdAt = date('Y-m-d H:i:s');
}
@@ -353,10 +358,10 @@ specific to a particular entity class's lifecycle.
$this->value = 'changed from prePersist callback!';
}
/** @PostLoad */
public function doStuffOnPostLoad()
/** @PreUpdate */
public function doStuffOnPreUpdate(PreUpdateEventArgs $eventArgs)
{
$this->value = 'changed from postLoad callback!';
$this->value = 'changed from preUpdate callback!';
}
}
.. code-block:: xml
@@ -372,7 +377,7 @@ specific to a particular entity class's lifecycle.
<lifecycle-callbacks>
<lifecycle-callback type="prePersist" method="doStuffOnPrePersist"/>
<lifecycle-callback type="prePersist" method="doOtherStuffOnPrePersist"/>
<lifecycle-callback type="postLoad" method="doStuffOnPostLoad"/>
<lifecycle-callback type="preUpdate" method="doStuffOnPreUpdate"/>
</lifecycle-callbacks>
</entity>
</doctrine-mapping>
@@ -386,7 +391,7 @@ specific to a particular entity class's lifecycle.
type: string(255)
lifecycleCallbacks:
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ]
postLoad: [ doStuffOnPostLoad ]
preUpdate: [ doStuffOnPreUpdate ]
Lifecycle Callbacks Event Argument
----------------------------------
@@ -1085,3 +1090,12 @@ and the EntityManager.
$em = $eventArgs->getEntityManager();
}
}
.. _LifecycleEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/LifecycleEventArgs.php
.. _PreUpdateEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php
.. _PreFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PreFlushEventArgs.php
.. _PostFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/PostFlushEventArgs.php
.. _OnFlushEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/OnFlushEventArgs.php
.. _OnClearEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/OnClearEventArgs.php
.. _LoadClassMetadataEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php
.. _OnClassMetadataNotFoundEventArgs: https://github.com/doctrine/orm/blob/HEAD/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php
+51 -61
View File
@@ -31,31 +31,31 @@ Each cache region resides in a specific cache namespace and has its own lifetime
Notice that when caching collection and queries only identifiers are stored.
The entity values will be stored in its own region
Something like below for an entity region :
Something like below for an entity region:
.. code-block:: php
<?php
[
'region_name:entity_1_hash' => ['id'=> 1, 'name' => 'FooBar', 'associationName'=>null],
'region_name:entity_2_hash' => ['id'=> 2, 'name' => 'Foo', 'associationName'=>['id'=>11]],
'region_name:entity_3_hash' => ['id'=> 3, 'name' => 'Bar', 'associationName'=>['id'=>22]]
'region_name:entity_1_hash' => ['id' => 1, 'name' => 'FooBar', 'associationName' => null],
'region_name:entity_2_hash' => ['id' => 2, 'name' => 'Foo', 'associationName' => ['id' => 11]],
'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 :
An collection region could look something like:
.. code-block:: php
<?php
[
'region_name:entity_1_coll_assoc_name_hash' => ['ownerId'=> 1, 'list' => [1, 2, 3]],
'region_name:entity_2_coll_assoc_name_hash' => ['ownerId'=> 2, 'list' => [2, 3]],
'region_name:entity_3_coll_assoc_name_hash' => ['ownerId'=> 3, 'list' => [2, 4]]
'region_name:entity_1_coll_assoc_name_hash' => ['ownerId' => 1, 'list' => [1, 2, 3]],
'region_name:entity_2_coll_assoc_name_hash' => ['ownerId' => 2, 'list' => [2, 3]],
'region_name:entity_3_coll_assoc_name_hash' => ['ownerId' => 3, 'list' => [2, 4]]
];
A query region might be something like :
A query region might be something like:
.. code-block:: php
@@ -93,8 +93,6 @@ Cache region
``Doctrine\ORM\Cache\Region`` defines a contract for accessing a particular
cache region.
`See API Doc <https://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/Region.html>`_.
Concurrent cache region
~~~~~~~~~~~~~~~~~~~~~~~
@@ -105,8 +103,6 @@ If you want to use an ``READ_WRITE`` cache, you should consider providing your o
``Doctrine\ORM\Cache\ConcurrentRegion`` defines a contract for concurrently managed data region.
`See API Doc <https://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/ConcurrentRegion.html>`_.
Timestamp region
~~~~~~~~~~~~~~~~
@@ -114,8 +110,6 @@ Timestamp region
Tracks the timestamps of the most recent updates to particular entity.
`See API Doc <https://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/TimestampRegion.html>`_.
.. _reference-second-level-cache-mode:
Caching mode
@@ -132,7 +126,7 @@ 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,21 +141,21 @@ Built-in cached persisters
Cached persisters are responsible to access cache regions.
+-----------------------+-------------------------------------------------------------------------------------------+
| Cache Usage | Persister |
+=======================+===========================================================================================+
| READ_ONLY | Doctrine\\ORM\\Cache\\Persister\\Entity\\ReadOnlyCachedEntityPersister |
+-----------------------+-------------------------------------------------------------------------------------------+
| READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Entity\\ReadWriteCachedEntityPersister |
+-----------------------+-------------------------------------------------------------------------------------------+
| NONSTRICT_READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Entity\\NonStrictReadWriteCachedEntityPersister |
+-----------------------+-------------------------------------------------------------------------------------------+
| READ_ONLY | Doctrine\\ORM\\Cache\\Persister\\Collection\\ReadOnlyCachedCollectionPersister |
+-----------------------+-------------------------------------------------------------------------------------------+
| READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Collection\\ReadWriteCachedCollectionPersister |
+-----------------------+-------------------------------------------------------------------------------------------+
| NONSTRICT_READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Collection\\NonStrictReadWriteCachedCollectionPersister |
+-----------------------+-------------------------------------------------------------------------------------------+
+-----------------------+------------------------------------------------------------------------------------------+
| Cache Usage | Persister |
+=======================+==========================================================================================+
| READ_ONLY | ``Doctrine\ORM\Cache\Persister\Entity\ReadOnlyCachedEntityPersister`` |
+-----------------------+------------------------------------------------------------------------------------------+
| READ_WRITE | ``Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister`` |
+-----------------------+------------------------------------------------------------------------------------------+
| NONSTRICT_READ_WRITE | ``Doctrine\ORM\Cache\Persister\Entity\NonStrictReadWriteCachedEntityPersister`` |
+-----------------------+------------------------------------------------------------------------------------------+
| READ_ONLY | ``Doctrine\ORM\Cache\Persister\Collection\ReadOnlyCachedCollectionPersister`` |
+-----------------------+------------------------------------------------------------------------------------------+
| READ_WRITE | ``Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister`` |
+-----------------------+------------------------------------------------------------------------------------------+
| NONSTRICT_READ_WRITE | ``Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister`` |
+-----------------------+------------------------------------------------------------------------------------------+
Configuration
-------------
@@ -172,7 +166,7 @@ Enable Second Level Cache
~~~~~~~~~~~~~~~~~~~~~~~~~
To enable the second-level-cache, you should provide a cache factory.
``\Doctrine\ORM\Cache\DefaultCacheFactory`` is the default implementation.
``Doctrine\ORM\Cache\DefaultCacheFactory`` is the default implementation.
.. code-block:: php
@@ -196,7 +190,7 @@ Cache Factory
Cache Factory is the main point of extension.
It allows you to provide a specific implementation of the following components :
It allows you to provide a specific implementation of the following components:
``QueryCache``
stores and retrieves query cache results.
@@ -209,8 +203,6 @@ It allows you to provide a specific implementation of the following components :
``CollectionHydrator``
transforms collections into cache entries and cache entries into collections
`See API Doc <https://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/DefaultCacheFactory.html>`_.
Region Lifetime
~~~~~~~~~~~~~~~
@@ -234,12 +226,12 @@ Cache Log
~~~~~~~~~
By providing a cache logger you should be able to get information about all cache operations such as hits, misses and puts.
``\Doctrine\ORM\Cache\Logging\StatisticsCacheLogger`` is a built-in implementation that provides basic statistics.
``Doctrine\ORM\Cache\Logging\StatisticsCacheLogger`` is a built-in implementation that provides basic statistics.
.. code-block:: php
<?php
/* @var $config \Doctrine\ORM\Configuration */
/** @var \Doctrine\ORM\Configuration $config */
$logger = new \Doctrine\ORM\Cache\Logging\StatisticsCacheLogger();
// Cache logger
@@ -269,12 +261,9 @@ By providing a cache logger you should be able to get information about all cach
$logger->getMissCount();
If you want to get more information you should implement
``\Doctrine\ORM\Cache\Logging\CacheLogger`` and collect
``Doctrine\ORM\Cache\Logging\CacheLogger`` and collect
all the information you want.
`See API Doc <https://www.doctrine-project.org/api/orm/current/Doctrine/ORM/Cache/Logging/CacheLogger.html>`_.
Entity cache definition
-----------------------
* Entity cache configuration allows you to define the caching strategy and region for an entity.
@@ -330,8 +319,8 @@ level cache region.
Country:
type: entity
cache:
usage : READ_ONLY
region : my_entity_region
usage: READ_ONLY
region: my_entity_region
id:
id:
type: integer
@@ -401,7 +390,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" />
@@ -421,7 +410,7 @@ It caches the primary keys of association and cache each element will be cached
State:
type: entity
cache:
usage : NONSTRICT_READ_WRITE
usage: NONSTRICT_READ_WRITE
id:
id:
type: integer
@@ -439,17 +428,18 @@ It caches the primary keys of association and cache each element will be cached
country_id:
referencedColumnName: id
cache:
usage : NONSTRICT_READ_WRITE
usage: NONSTRICT_READ_WRITE
oneToMany:
cities:
targetEntity:City
mappedBy: state
cache:
usage : NONSTRICT_READ_WRITE
usage: NONSTRICT_READ_WRITE
.. note::
> Note: for this to work, the target entity must also be marked as cacheable.
for this to work, the target entity must also be marked as cacheable.
Cache usage
~~~~~~~~~~~
@@ -466,8 +456,8 @@ Basic entity cache
$country1 = $em->find('Country', 1); // Retrieve item from cache
$country1->setName("New Name");
$country1->setName('New Name');
$em->flush(); // Hit database to update the row and update cache
$em->clear(); // Clear entity manager
@@ -492,7 +482,7 @@ Association cache
$state = $em->find('State', 1);
// Hit database to update the row and update cache entry
$state->setName("New Name");
$state->setName('New Name');
$em->persist($state);
$em->flush();
@@ -543,14 +533,14 @@ 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')
->setCacheable(true)
->getResult();
$em->clear()
$em->clear();
// Check if query result is valid and load entities from cache
$result2 = $em->createQuery('SELECT c FROM Country c ORDER BY c.name')
@@ -570,10 +560,10 @@ 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)
->setCacheMode(\Doctrine\ORM\Cache::MODE_GET)
->setCacheable(true)
->getResult();
@@ -597,7 +587,7 @@ Execute the ``UPDATE`` and invalidate ``all cache entries`` using ``Query::HINT_
<?php
// Execute and invalidate
$this->_em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1")
->setHint(Query::HINT_CACHE_EVICT, true)
->setHint(\Doctrine\ORM\Query::HINT_CACHE_EVICT, true)
->execute();
@@ -659,7 +649,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
@@ -704,19 +694,19 @@ 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
$id = array('source' => 1, 'target' => 2);
$id = ['source' => 1, 'target' => 2];
$reference = $em->find('Reference', $id);
// NOT Supported
$id = array('source' => new Article(1), 'target' => new Article(2));
$id = ['source' => new Article(1), 'target' => new Article(2)];
$reference = $em->find('Reference', $id);
Distributed environments
+1 -1
View File
@@ -353,7 +353,7 @@
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:attribute name="name" type="xs:NMTOKEN" use="optional"/>
<xs:attribute name="columns" type="xs:string" use="required"/>
<xs:attribute name="columns" type="xs:string" use="optional"/>
<xs:attribute name="fields" type="xs:string" use="optional"/>
<xs:attribute name="flags" type="xs:string" use="optional"/>
<xs:anyAttribute namespace="##other"/>
+8 -4
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Doctrine\ORM\Id;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\ORM\EntityManager;
use Serializable;
@@ -54,11 +55,14 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
{
if ($this->_maxValue === null || $this->_nextValue === $this->_maxValue) {
// Allocate new values
$conn = $em->getConnection();
$sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
$connection = $em->getConnection();
$sql = $connection->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
// Using `query` to force usage of the master server in MasterSlaveConnection
$this->_nextValue = (int) $conn->executeQuery($sql)->fetchOne();
if ($connection instanceof PrimaryReadReplicaConnection) {
$connection->ensureConnectedToPrimary();
}
$this->_nextValue = (int) $connection->executeQuery($sql)->fetchOne();
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
}
+8 -3
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Doctrine\ORM\Id;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\Deprecations\Deprecation;
use Doctrine\ORM\EntityManager;
@@ -39,9 +40,13 @@ class UuidGenerator extends AbstractIdGenerator
*/
public function generate(EntityManager $em, $entity)
{
$conn = $em->getConnection();
$sql = 'SELECT ' . $conn->getDatabasePlatform()->getGuidExpression();
$connection = $em->getConnection();
$sql = 'SELECT ' . $connection->getDatabasePlatform()->getGuidExpression();
return $conn->executeQuery($sql)->fetchOne();
if ($connection instanceof PrimaryReadReplicaConnection) {
$connection->ensureConnectedToPrimary();
}
return $connection->executeQuery($sql)->fetchOne();
}
}
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Doctrine\ORM\Query\Exec;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\Query\AST;
use Doctrine\ORM\Query\AST\DeleteStatement;
@@ -49,6 +50,10 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
$platform = $conn->getDatabasePlatform();
$quoteStrategy = $em->getConfiguration()->getQuoteStrategy();
if ($conn instanceof PrimaryReadReplicaConnection) {
$conn->ensureConnectedToPrimary();
}
$primaryClass = $em->getClassMetadata($AST->deleteClause->abstractSchemaName);
$primaryDqlAlias = $AST->deleteClause->aliasIdentificationVariable;
$rootClass = $em->getClassMetadata($primaryClass->rootEntityName);
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Doctrine\ORM\Query\Exec;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\Query\AST;
use Doctrine\ORM\Query\AST\UpdateStatement;
@@ -55,6 +56,10 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
$platform = $conn->getDatabasePlatform();
$quoteStrategy = $em->getConfiguration()->getQuoteStrategy();
if ($conn instanceof PrimaryReadReplicaConnection) {
$conn->ensureConnectedToPrimary();
}
$updateClause = $AST->updateClause;
$primaryClass = $sqlWalker->getEntityManager()->getClassMetadata($updateClause->abstractSchemaName);
$rootClass = $em->getClassMetadata($primaryClass->rootEntityName);
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Doctrine\ORM\Query\Exec;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\ORM\Query\AST;
use Doctrine\ORM\Query\SqlWalker;
@@ -37,6 +38,10 @@ class SingleTableDeleteUpdateExecutor extends AbstractSqlExecutor
*/
public function execute(Connection $conn, array $params, array $types)
{
if ($conn instanceof PrimaryReadReplicaConnection) {
$conn->ensureConnectedToPrimary();
}
return $conn->executeStatement($this->_sqlStatements, $params, $types);
}
}
@@ -195,6 +195,7 @@ abstract class SQLFilter
* Gets the SQL query part to add to a query.
*
* @param string $targetTableAlias
* @psalm-param ClassMetadata<object> $targetEntity
*
* @return string The constraint SQL if there is available, empty string otherwise.
*/
+1 -1
View File
@@ -239,7 +239,7 @@ class SchemaValidator
}
}
if (! $class->isInheritanceTypeNone() && ! $class->isRootEntity() && ! $class->reflClass->isAbstract() && ! $class->isMappedSuperclass && array_search($class->name, $class->discriminatorMap, true) === false) {
if (! $class->isInheritanceTypeNone() && ! $class->isRootEntity() && ! $class->isMappedSuperclass && array_search($class->name, $class->discriminatorMap, true) === false) {
$ce[] = "Entity class '" . $class->name . "' is part of inheritance hierarchy, but is " .
"not mapped in the root entity '" . $class->rootEntityName . "' discriminator map. " .
'All subclasses must be listed in the discriminator map.';
+7
View File
@@ -9,6 +9,7 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\EventManager;
use Doctrine\Common\Proxy\Proxy;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\LockMode;
use Doctrine\Deprecations\Deprecation;
use Doctrine\ORM\Cache\Persister\CachedPersister;
@@ -338,6 +339,12 @@ class UnitOfWork implements PropertyChangedListener
*/
public function commit($entity = null)
{
$connection = $this->em->getConnection();
if ($connection instanceof PrimaryReadReplicaConnection) {
$connection->ensureConnectedToPrimary();
}
// Raise preFlush
if ($this->evm->hasListeners(Events::preFlush)) {
$this->evm->dispatchEvent(Events::preFlush, new PreFlushEventArgs($this->em));
+4 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.13.1@5cf660f63b548ccd4a56f62d916ee4d6028e01a3">
<files psalm-version="v4.15.0@a1b5e489e6fcebe40cb804793d964e99fc347820">
<file src="lib/Doctrine/ORM/AbstractQuery.php">
<DeprecatedClass occurrences="1">
<code>IterableResult</code>
@@ -1043,6 +1043,9 @@
<code>$this-&gt;table</code>
<code>$this-&gt;table</code>
</PropertyTypeCoercion>
<RedundantCast occurrences="1">
<code>array_values</code>
</RedundantCast>
<RedundantConditionGivenDocblockType occurrences="3">
<code>$className !== null</code>
<code>$mapping !== false</code>
@@ -239,9 +239,7 @@ class SecondLevelCacheManyToOneTest extends SecondLevelCacheAbstractTest
self::assertFalse($this->cache->containsEntity(Action::class, $action3->name));
$queryCount = $this->getCurrentQueryCount();
/**
* @var $entity Token
*/
$entity = $this->_em->find(Token::class, $token->token);
self::assertInstanceOf(Token::class, $entity);
@@ -225,17 +225,6 @@ class SchemaValidatorTest extends OrmTestCase
$this->assertEquals([], $ce);
}
/**
* @group 9095
*/
public function testAbstractChildClassNotPresentInDiscriminator(): void
{
$class1 = $this->em->getClassMetadata(Issue9095AbstractChild::class);
$ce = $this->validator->validateClass($class1);
$this->assertEquals([], $ce);
}
}
/**
@@ -267,35 +256,6 @@ class ChildEntity extends MappedSuperclassEntity
{
}
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorMap({"child" = Issue9095Child::class})
*/
abstract class Issue9095Parent
{
/**
* @var mixed
* @Id
* @Column
*/
protected $key;
}
/**
* @Entity
*/
abstract class Issue9095AbstractChild extends Issue9095Parent
{
}
/**
* @Entity
*/
class Issue9095Child extends Issue9095AbstractChild
{
}
/**
* @Entity
*/
+5 -16
View File
@@ -58,23 +58,12 @@ abstract class OrmTestCase extends DoctrineTestCase
/** @var Cache|null */
protected $secondLevelCacheDriverImpl = null;
/**
* @param mixed $alias
*/
protected function createAnnotationDriver(array $paths = [], $alias = null): AnnotationDriver
protected function createAnnotationDriver(array $paths = []): AnnotationDriver
{
// Register the ORM Annotations in the AnnotationRegistry
$reader = new Annotations\AnnotationReader();
if (class_exists(Annotations\PsrCachedReader::class)) {
$reader = new Annotations\PsrCachedReader($reader, new ArrayAdapter());
} else {
$reader = new Annotations\CachedReader($reader, DoctrineProvider::wrap(new ArrayAdapter()));
}
Annotations\AnnotationRegistry::registerFile(__DIR__ . '/../../../lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
return new AnnotationDriver($reader, (array) $paths);
return new AnnotationDriver(
new Annotations\PsrCachedReader(new Annotations\AnnotationReader(), new ArrayAdapter()),
$paths
);
}
/**