Files
cms-core/Documentation/Changelog/13.0/Breaking-102875-QueryBuilderChanges.rst

265 lines
7.5 KiB
ReStructuredText

.. include:: /Includes.rst.txt
.. _breaking-102875-1705944493:
========================================
Breaking: #102875 - QueryBuilder changes
========================================
See :issue:`102875`
Description
===========
Doctrine DBAL 4 removed methods from the :php:`QueryBuilder` which has been
adopted to the extended :php:`\TYPO3\CMS\Core\Database\Query\QueryBuilder`.
Removed methods:
* :php:`QueryBuilder::add()`: Use new reset methods and normal set methods
instead.
* :php:`QueryBuilder::getQueryPart($partName)`: No replacement, internal state.
* :php:`QueryBuilder::getQueryParts()`: No replacement, internal state.
* :php:`QueryBuilder::resetQueryPart($partName)`: Replacement methods has been added,
see list.
* :php:`QueryBuilder::resetQueryParts()`: Replacement methods has been added,
see list.
* :php:`QueryBuilder::execute()`: Use :php:`QueryBuilder::executeQuery()` or
:php:`QueryBuilder::executeStatement()` directly.
* :php:`QueryBuilder::setMaxResults()`: Using `(int)0` as `max result` will
no longer work and retrieve no records. Use `NULL` instead to allow all
results.
Signature changes:
* :php:`QueryBuilder::quote(string $value)`: Second argument has been dropped
and the value must now be of type :php:`string`.
Impact
======
Calling any of the mentioned removed methods will result in a PHP error. Also
signature changes introducing type hint will result in a PHP error if called
with an invalid type.
Affected installations
======================
Only those installations that use the mentioned methods.
Migration
=========
Extension author need to replace the removed methods with the alternatives which
:php:`QueryBuilder::add('query-part-name')`
-------------------------------------------
Use the direct set/select methods instead:
.. csv-table:: Replacements
:header: "before", "after"
":php:`->add('select', $array)`", ":php:`->select(...$array)`"
":php:`->add('where', $wheres)`", ":php:`->where(...$wheres)`"
":php:`->add('having', $havings)`", ":php:`->having(...$havings)`"
":php:`->add('orderBy', $orderBy)`", ":php:`->orderBy($orderByField, $orderByDirection)->addOrderBy($orderByField2)`"
":php:`->add('groupBy', $groupBy)`", ":php:`->groupBy($groupField)->addGroupBy($groupField2)`"
.. note::
This can be done already in TYPO3 v12 with at least Doctrine DBAL 3.8.
:php:`QueryBuilder::resetQueryParts()` and :php:`QueryBuilder::resetQueryPart()`
--------------------------------------------------------------------------------
However, several replacements have been put in place depending on the
:php:`$queryPartName` parameter:
.. csv-table:: Replacements
:header: "before", "after"
"'select'", "Call :php:`->select()` with a new set of columns"
"'distinct'", ":php:`->distinct(false)`"
"'where'", ":php:`->resetWhere()`"
"'having'", ":php:`->resetHaving()`"
"'groupBy'", ":php:`->resetGroupBy()`"
"'orderBy", ":php:`->resetOrderBy()`"
"'values'", "Call :php:`->values()` with a new set of values."
.. note::
This can be done already in TYPO3 v12 with at least Doctrine DBAL 3.8.
:php:`QueryBuilder::execute()`
------------------------------
Doctrine DBAL 4 removed :php:`QueryBuilder::execute()` in favour of the two
methods :php:`QueryBuilder::executeQuery()` for select/count and :php:`QueryBuilder::executeStatement()`
for insert, delete and update queries.
Before
~~~~~~
.. code-block:: php
:emphasize-lines: 9,20
use TYPO3\CMS\Core\Database\ConnectionPool;
// select query
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$rows = $queryBuilder
->select('*')
->from('pages')
->execute()
->fetchAllAssociative();
// delete query
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$deletedRows = (int)$queryBuilder
->delete('pages')
->where(
$queryBuilder->expr()->eq('pid', $this->createNamedParameter(123),
)
->execute();
After
~~~~~
.. code-block:: php
:emphasize-lines: 9,20
use TYPO3\CMS\Core\Database\ConnectionPool;
// select query
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$rows = $queryBuilder
->select('*')
->from('pages')
->executeQuery()
->fetchAllAssociative();
// delete query
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$deletedRows = (int)$queryBuilder
->delete('pages')
->where(
$queryBuilder->expr()->eq('pid', $this->createNamedParameter(123),
)
->executeStatement();
:php:`QueryBuilder::quote(string $value)`
-----------------------------------------
:php:`quote()` uses :php:`Connection::quote()` and therefore adopts the changed
signature and behaviour.
Before
~~~~~~
.. code-block:: php
:emphasize-lines: 15
use TYPO3\CMS\Core\Database\Connection as Typo3Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
// select query
$pageId = 123;
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$rows = $queryBuilder
->select('*')
->from('pages')
->where(
$queryBuilder->expr()->eq(
'uid',
$queryBuilder->quote($pageId, Typo3Connection::PARAM_INT)
),
)
->executeQuery()
->fetchAllAssociative();
After
~~~~~
.. code-block:: php
:emphasize-lines: 14
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
// select query
$pageId = 123;
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$rows = $queryBuilder
->select('*')
->from('pages')
->where(
$queryBuilder->expr()->eq(
'uid',
$queryBuilder->quote((string)$pageId)
),
)
->executeQuery()
->fetchAllAssociative();
.. tip::
To provide TYPO3 v12 and v13 with one code base, :php:`->quote((string)$value)`
can be used to ensure dual Core compatibility.
:php:`QueryBuilder::setMaxResults()`
------------------------------------
Using `(int)0` as `max result` will no longer work and retrieve no records.
Use `NULL` instead to allow all results.
Before
~~~~~~
.. code-block:: php
:emphasize-lines: 12
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
// select query
$pageId = 123;
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$rows = $queryBuilder
->select('*')
->from('pages')
->setFirstResult(0)
->setMaxResults(0)
->executeQuery()
->fetchAllAssociative();
After
~~~~~
.. code-block:: php
:emphasize-lines: 12
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
// select query
$pageId = 123;
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$rows = $queryBuilder
->select('*')
->from('pages')
->setFirstResult(0)
->setMaxResults(null)
->executeQuery()
->fetchAllAssociative();
.. index:: Database, PHP-API, NotScanned, ext:core