У меня проблемы с обработчиком функций sql в CakePHP 4. Я использую SQLite 3 и Cakephp 4.2.3 Strawberry. В моей таблице базы данных есть поле TEXT под названием «дата». Наименьшее и наибольшее значения в «дате»: «2020-01-15» и «2020-12-31». У меня есть простой запрос:
$query = $this->find();
$query->select(['minDate' => $query->func()->min('date'),
'maxDate' => $query->func()->max('date')])
->where(['date <>' => ''])
->enableHydration(false);
$results = $query->toList();
$maxDate = $results[0]['maxDate'];
$minDate = $results[0]['minDate'];
Что генерирует SQL, который я хочу:
SELECT (MIN(date)) AS minDate, (MAX(date)) AS maxDate FROM temp_income TempIncome WHERE date <> :c0
Однако код возвращает значения с плавающей запятой для $minDate и $maxDate:
$minDate = 2020
$maxDate = 2020
Если я запускаю этот оператор непосредственно в SQLite Studio, я получаю правильный результат (ввод '' вместо: c0)
minDate = '2020-01-15'
maxDate = '2020-12-31'
Если я запущу запрос в CakePHP с помощью Connection Manager и того же SQL, я получу правильный ответ.
$connection = ConnectionManager::get('default');
$results = $connection->execute("SELECT min(date) as minDate, max(date) as maxDate from temp_income where date <> ''")->fetchAll('assoc');
minDate = '2020-01-15'
maxDate = '2020-12-31'
Оболочка функции торта func()->min(‘date’)
выполняет нежелательное преобразование типов.
Копнув глубже, внутри vendor/cakephp/cakephp/src/database/FunctionsBuilder.php компоновщики для min и max настроены на возврат «float», если не определен другой тип, что, по-видимому, не в данном случае. Я не знаю почему. Я еще не копал так далеко.
public function max($expression, $types = []): AggregateExpression
{
return $this->aggregate('MAX', $this->toLiteralParam($expression), $types, current($types) ?: 'float');
}
public function min($expression, $types = []): AggregateExpression
{
return $this->aggregate('MIN', $this->toLiteralParam($expression), $types, current($types) ?: 'float');
}
Правильное поведение для min() и max(), по крайней мере, в Oracle и SQL Server, и явно в SQLite, поскольку необработанный запрос работает нормально, состоит в том, чтобы возвращать тип данных аргумента.
Это ошибка в обёртке функции CakePHP? Или я что-то упускаю?
Спасибо!
min
иmax
принимают второй параметр, представляющий собой массив типов. Я не могу найти пример использования этого в документации, я думаю,->min('date', ['date'])
? - person Greg Schmidt   schedule 16.03.2021