Skip to content

Commit f79d166

Browse files
committed
Merge branch '2.19.x' into 3.1.x
* 2.19.x: Fix BIGINT validation (#11414) Fix templated phpdoc return type (#11407) [Documentation] Merging "Query Result Formats" with "Hydration Modes" Fix psalm errors: remove override of template type Update dql-doctrine-query-language.rst Adding `NonUniqueResultException` [Documentation] Query Result Formats
2 parents 9c22814 + b274893 commit f79d166

9 files changed

+202
-257
lines changed

Diff for: docs/en/reference/dql-doctrine-query-language.rst

+140-211
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ The Query class
976976
---------------
977977

978978
An instance of the ``Doctrine\ORM\Query`` class represents a DQL
979-
query. You create a Query instance be calling
979+
query. You create a Query instance by calling
980980
``EntityManager#createQuery($dql)``, passing the DQL query string.
981981
Alternatively you can create an empty ``Query`` instance and invoke
982982
``Query#setDQL($dql)`` afterwards. Here are some examples:
@@ -993,58 +993,146 @@ Alternatively you can create an empty ``Query`` instance and invoke
993993
$q = $em->createQuery();
994994
$q->setDQL('select u from MyProject\Model\User u');
995995
996-
Query Result Formats
997-
~~~~~~~~~~~~~~~~~~~~
996+
Query Result Formats (Hydration Modes)
997+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
998+
999+
The way in which the SQL result set of a DQL SELECT query is transformed
1000+
to PHP is determined by the so-called "hydration mode".
1001+
1002+
``getResult()``
1003+
^^^^^^^^^^^^^^^
1004+
1005+
Retrieves a collection of objects. The result is either a plain collection of objects (pure) or an array
1006+
where the objects are nested in the result rows (mixed):
1007+
1008+
.. code-block:: php
1009+
1010+
<?php
1011+
use Doctrine\ORM\AbstractQuery;
1012+
1013+
$query = $em->createQuery('SELECT u FROM User u');
1014+
$users = $query->getResult();
1015+
// same as:
1016+
$users = $query->getResult(AbstractQuery::HYDRATE_OBJECT);
1017+
1018+
- Objects fetched in a FROM clause are returned as a Set, that means every
1019+
object is only ever included in the resulting array once. This is the case
1020+
even when using JOIN or GROUP BY in ways that return the same row for an
1021+
object multiple times. If the hydrator sees the same object multiple times,
1022+
then it makes sure it is only returned once.
1023+
1024+
- If an object is already in memory from a previous query of any kind, then
1025+
then the previous object is used, even if the database may contain more
1026+
recent data. This even happens if the previous object is still an unloaded proxy.
1027+
1028+
``getArrayResult()``
1029+
^^^^^^^^^^^^^^^^^^^^
1030+
1031+
Retrieves an array graph (a nested array) for read-only purposes.
1032+
1033+
.. note::
1034+
1035+
An array graph can differ from the corresponding object
1036+
graph in certain scenarios due to the difference of the identity
1037+
semantics between arrays and objects.
1038+
1039+
.. code-block:: php
1040+
1041+
<?php
1042+
$users = $query->getArrayResult();
1043+
// same as:
1044+
$users = $query->getResult(AbstractQuery::HYDRATE_ARRAY);
1045+
1046+
``getScalarResult()``
1047+
^^^^^^^^^^^^^^^^^^^^^
1048+
1049+
Retrieves a flat/rectangular result set of scalar values that can contain duplicate data. The
1050+
pure/mixed distinction does not apply.
1051+
1052+
.. code-block:: php
1053+
1054+
<?php
1055+
$users = $query->getScalarResult();
1056+
// same as:
1057+
$users = $query->getResult(AbstractQuery::HYDRATE_SCALAR);
1058+
1059+
Fields from classes are prefixed by the DQL alias in the result.
1060+
A query of the kind `SELECT u.name ...` returns a key `u_name` in the result rows.
1061+
1062+
``getSingleScalarResult()``
1063+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
1064+
1065+
Retrieves a single scalar value from the result returned by the database. If the result contains
1066+
more than a single scalar value, a ``NonUniqueResultException`` is thrown. The pure/mixed distinction does not apply.
1067+
1068+
.. code-block:: php
1069+
1070+
<?php
1071+
$query = $em->createQuery('SELECT COUNT(u.id) FROM User u');
1072+
$numUsers = $query->getSingleScalarResult();
1073+
// same as:
1074+
$numUsers = $query->getResult(AbstractQuery::HYDRATE_SINGLE_SCALAR);
1075+
1076+
``getSingleColumnResult()``
1077+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
1078+
1079+
Retrieves an array from a one-dimensional array of scalar values:
1080+
1081+
.. code-block:: php
1082+
1083+
<?php
1084+
$query = $em->createQuery('SELECT a.id FROM User u');
1085+
$ids = $query->getSingleColumnResult();
1086+
// same as:
1087+
$ids = $query->getResult(AbstractQuery::HYDRATE_SCALAR_COLUMN);
1088+
1089+
``getSingleResult()``
1090+
^^^^^^^^^^^^^^^^^^^^^
1091+
1092+
Retrieves a single object. If the result contains more than one object, a ``NonUniqueResultException``
1093+
is thrown. If the result contains no objects, a ``NoResultException`` is thrown. The pure/mixed distinction does not apply.
1094+
1095+
``getOneOrNullResult()``
1096+
^^^^^^^^^^^^^^^^^^^^^^^^
1097+
1098+
Retrieves a single object. If the result contains more than one object, a ``NonUniqueResultException``
1099+
is thrown. If no object is found, ``null`` will be returned.
1100+
1101+
Custom Hydration Modes
1102+
^^^^^^^^^^^^^^^^^^^^^^
1103+
1104+
You can easily add your own custom hydration modes by first
1105+
creating a class which extends ``AbstractHydrator``:
1106+
1107+
.. code-block:: php
1108+
1109+
<?php
1110+
namespace MyProject\Hydrators;
1111+
1112+
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
1113+
1114+
class CustomHydrator extends AbstractHydrator
1115+
{
1116+
protected function _hydrateAll()
1117+
{
1118+
return $this->_stmt->fetchAllAssociative();
1119+
}
1120+
}
9981121
999-
The format in which the result of a DQL SELECT query is returned
1000-
can be influenced by a so-called ``hydration mode``. A hydration
1001-
mode specifies a particular way in which a SQL result set is
1002-
transformed. Each hydration mode has its own dedicated method on
1003-
the Query class. Here they are:
1004-
1005-
1006-
- ``Query#getResult()``: Retrieves a collection of objects. The
1007-
result is either a plain collection of objects (pure) or an array
1008-
where the objects are nested in the result rows (mixed).
1009-
- ``Query#getSingleResult()``: Retrieves a single object. If the
1010-
result contains more than one object, an ``NonUniqueResultException``
1011-
is thrown. If the result contains no objects, an ``NoResultException``
1012-
is thrown. The pure/mixed distinction does not apply.
1013-
- ``Query#getOneOrNullResult()``: Retrieve a single object. If the
1014-
result contains more than one object, a ``NonUniqueResultException``
1015-
is thrown. If no object is found null will be returned.
1016-
- ``Query#getArrayResult()``: Retrieves an array graph (a nested
1017-
array) that is largely interchangeable with the object graph
1018-
generated by ``Query#getResult()`` for read-only purposes.
1019-
1020-
.. note::
1021-
1022-
An array graph can differ from the corresponding object
1023-
graph in certain scenarios due to the difference of the identity
1024-
semantics between arrays and objects.
1025-
1026-
1027-
1028-
- ``Query#getScalarResult()``: Retrieves a flat/rectangular result
1029-
set of scalar values that can contain duplicate data. The
1030-
pure/mixed distinction does not apply.
1031-
- ``Query#getSingleScalarResult()``: Retrieves a single scalar
1032-
value from the result returned by the dbms. If the result contains
1033-
more than a single scalar value, an exception is thrown. The
1034-
pure/mixed distinction does not apply.
1035-
1036-
Instead of using these methods, you can alternatively use the
1037-
general-purpose method
1038-
``Query#execute(array $params = [], $hydrationMode = Query::HYDRATE_OBJECT)``.
1039-
Using this method you can directly supply the hydration mode as the
1040-
second parameter via one of the Query constants. In fact, the
1041-
methods mentioned earlier are just convenient shortcuts for the
1042-
execute method. For example, the method ``Query#getResult()``
1043-
internally invokes execute, passing in ``Query::HYDRATE_OBJECT`` as
1044-
the hydration mode.
1045-
1046-
The use of the methods mentioned earlier is generally preferred as
1047-
it leads to more concise code.
1122+
Next you just need to add the class to the ORM configuration:
1123+
1124+
.. code-block:: php
1125+
1126+
<?php
1127+
$em->getConfiguration()->addCustomHydrationMode('CustomHydrator', 'MyProject\Hydrators\CustomHydrator');
1128+
1129+
Now the hydrator is ready to be used in your queries:
1130+
1131+
.. code-block:: php
1132+
1133+
<?php
1134+
$query = $em->createQuery('SELECT u FROM CmsUser u');
1135+
$results = $query->getResult('CustomHydrator');
10481136
10491137
Pure and Mixed Results
10501138
~~~~~~~~~~~~~~~~~~~~~~
@@ -1148,165 +1236,6 @@ will return the rows iterating the different top-level entities.
11481236
[2] => Object (User)
11491237
[3] => Object (Group)
11501238
1151-
1152-
Hydration Modes
1153-
~~~~~~~~~~~~~~~
1154-
1155-
Each of the Hydration Modes makes assumptions about how the result
1156-
is returned to user land. You should know about all the details to
1157-
make best use of the different result formats:
1158-
1159-
The constants for the different hydration modes are:
1160-
1161-
1162-
- ``Query::HYDRATE_OBJECT``
1163-
- ``Query::HYDRATE_ARRAY``
1164-
- ``Query::HYDRATE_SCALAR``
1165-
- ``Query::HYDRATE_SINGLE_SCALAR``
1166-
- ``Query::HYDRATE_SCALAR_COLUMN``
1167-
1168-
Object Hydration
1169-
^^^^^^^^^^^^^^^^
1170-
1171-
Object hydration hydrates the result set into the object graph:
1172-
1173-
.. code-block:: php
1174-
1175-
<?php
1176-
$query = $em->createQuery('SELECT u FROM CmsUser u');
1177-
$users = $query->getResult(Query::HYDRATE_OBJECT);
1178-
1179-
Sometimes the behavior in the object hydrator can be confusing, which is
1180-
why we are listing as many of the assumptions here for reference:
1181-
1182-
- Objects fetched in a FROM clause are returned as a Set, that means every
1183-
object is only ever included in the resulting array once. This is the case
1184-
even when using JOIN or GROUP BY in ways that return the same row for an
1185-
object multiple times. If the hydrator sees the same object multiple times,
1186-
then it makes sure it is only returned once.
1187-
1188-
- If an object is already in memory from a previous query of any kind, then
1189-
then the previous object is used, even if the database may contain more
1190-
recent data. Data from the database is discarded. This even happens if the
1191-
previous object is still an unloaded proxy.
1192-
1193-
This list might be incomplete.
1194-
1195-
Array Hydration
1196-
^^^^^^^^^^^^^^^
1197-
1198-
You can run the same query with array hydration and the result set
1199-
is hydrated into an array that represents the object graph:
1200-
1201-
.. code-block:: php
1202-
1203-
<?php
1204-
$query = $em->createQuery('SELECT u FROM CmsUser u');
1205-
$users = $query->getResult(Query::HYDRATE_ARRAY);
1206-
1207-
You can use the ``getArrayResult()`` shortcut as well:
1208-
1209-
.. code-block:: php
1210-
1211-
<?php
1212-
$users = $query->getArrayResult();
1213-
1214-
Scalar Hydration
1215-
^^^^^^^^^^^^^^^^
1216-
1217-
If you want to return a flat rectangular result set instead of an
1218-
object graph you can use scalar hydration:
1219-
1220-
.. code-block:: php
1221-
1222-
<?php
1223-
$query = $em->createQuery('SELECT u FROM CmsUser u');
1224-
$users = $query->getResult(Query::HYDRATE_SCALAR);
1225-
echo $users[0]['u_id'];
1226-
1227-
The following assumptions are made about selected fields using
1228-
Scalar Hydration:
1229-
1230-
1231-
1. Fields from classes are prefixed by the DQL alias in the result.
1232-
A query of the kind 'SELECT u.name ..' returns a key 'u_name' in
1233-
the result rows.
1234-
1235-
Single Scalar Hydration
1236-
^^^^^^^^^^^^^^^^^^^^^^^
1237-
1238-
If you have a query which returns just a single scalar value you can use
1239-
single scalar hydration:
1240-
1241-
.. code-block:: php
1242-
1243-
<?php
1244-
$query = $em->createQuery('SELECT COUNT(a.id) FROM CmsUser u LEFT JOIN u.articles a WHERE u.username = ?1 GROUP BY u.id');
1245-
$query->setParameter(1, 'jwage');
1246-
$numArticles = $query->getResult(Query::HYDRATE_SINGLE_SCALAR);
1247-
1248-
You can use the ``getSingleScalarResult()`` shortcut as well:
1249-
1250-
.. code-block:: php
1251-
1252-
<?php
1253-
$numArticles = $query->getSingleScalarResult();
1254-
1255-
Scalar Column Hydration
1256-
^^^^^^^^^^^^^^^^^^^^^^^
1257-
1258-
If you have a query which returns a one-dimensional array of scalar values
1259-
you can use scalar column hydration:
1260-
1261-
.. code-block:: php
1262-
1263-
<?php
1264-
$query = $em->createQuery('SELECT a.id FROM CmsUser u');
1265-
$ids = $query->getResult(Query::HYDRATE_SCALAR_COLUMN);
1266-
1267-
You can use the ``getSingleColumnResult()`` shortcut as well:
1268-
1269-
.. code-block:: php
1270-
1271-
<?php
1272-
$ids = $query->getSingleColumnResult();
1273-
1274-
Custom Hydration Modes
1275-
^^^^^^^^^^^^^^^^^^^^^^
1276-
1277-
You can easily add your own custom hydration modes by first
1278-
creating a class which extends ``AbstractHydrator``:
1279-
1280-
.. code-block:: php
1281-
1282-
<?php
1283-
namespace MyProject\Hydrators;
1284-
1285-
use Doctrine\ORM\Internal\Hydration\AbstractHydrator;
1286-
1287-
class CustomHydrator extends AbstractHydrator
1288-
{
1289-
protected function _hydrateAll()
1290-
{
1291-
return $this->_stmt->fetchAllAssociative();
1292-
}
1293-
}
1294-
1295-
Next you just need to add the class to the ORM configuration:
1296-
1297-
.. code-block:: php
1298-
1299-
<?php
1300-
$em->getConfiguration()->addCustomHydrationMode('CustomHydrator', 'MyProject\Hydrators\CustomHydrator');
1301-
1302-
Now the hydrator is ready to be used in your queries:
1303-
1304-
.. code-block:: php
1305-
1306-
<?php
1307-
$query = $em->createQuery('SELECT u FROM CmsUser u');
1308-
$results = $query->getResult('CustomHydrator');
1309-
13101239
Iterating Large Result Sets
13111240
~~~~~~~~~~~~~~~~~~~~~~~~~~~
13121241

Diff for: phpstan-baseline.neon

-5
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,6 @@ parameters:
115115
count: 1
116116
path: src/EntityManagerInterface.php
117117

118-
-
119-
message: "#^Template type T of method Doctrine\\\\ORM\\\\EntityManagerInterface\\:\\:getClassMetadata\\(\\) is not referenced in a parameter\\.$#"
120-
count: 1
121-
path: src/EntityManagerInterface.php
122-
123118
-
124119
message: "#^Method Doctrine\\\\ORM\\\\EntityRepository\\:\\:matching\\(\\) should return Doctrine\\\\Common\\\\Collections\\\\AbstractLazyCollection\\<int, T of object\\>&Doctrine\\\\Common\\\\Collections\\\\Selectable\\<int, T of object\\> but returns Doctrine\\\\ORM\\\\LazyCriteriaCollection\\<\\(int\\|string\\), object\\>\\.$#"
125120
count: 1

0 commit comments

Comments
 (0)