mirror of
https://github.com/doctrine/orm.git
synced 2026-04-27 00:18:04 +02:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cccb2e2fdf | |||
| 18138d895e | |||
| fa2b52c974 | |||
| 5bf814032f | |||
| 02a4e4099d | |||
| 12a70bbefb | |||
| 5a4ddb2870 | |||
| 68fa55f310 | |||
| 0b0c3e7e58 | |||
| 92434f91c7 | |||
| 6414ad4cbb | |||
| 8b6fe52f74 | |||
| 32cd2106d0 | |||
| 77b7107d05 | |||
| 2dde65c4ba |
+2
-2
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(' .
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 doesn’t 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
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.';
|
||||
|
||||
@@ -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
@@ -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->table</code>
|
||||
<code>$this->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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user