Laravel Pest测试中MySQL YEAR函数报错的解决方法
修复测试环境中SQL函数不存在的错误
问题原因
生产/开发环境使用MySQL,支持YEAR()、MONTH()、DATE_FORMAT()这类专属函数,但Laravel默认测试环境采用SQLite内存数据库,SQLite不兼容这些MySQL专属函数,因此测试时抛出no such function: YEAR错误。
解决方案
方案一:使用跨数据库兼容的SQL语法
替换MySQL专属函数为SQLite和MySQL都支持的标准语法,或根据数据库类型动态切换函数:
use Illuminate\Support\Facades\DB; // 根据当前数据库驱动选择对应函数 $driver = DB::getDriverName(); $yearFunc = $driver === 'sqlite' ? "strftime('%Y', groups.created_at)" : "YEAR(groups.created_at)"; $monthFunc = $driver === 'sqlite' ? "strftime('%m', groups.created_at)" : "MONTH(groups.created_at)"; $shortMonthFunc = $driver === 'sqlite' ? "strftime('%b', groups.created_at)" : "DATE_FORMAT(groups.created_at, '%b')"; Group::query() ->selectRaw("$yearFunc as year, $monthFunc as month, $shortMonthFunc as short_month_format, count(*) as count") ->whereIn('id', $ids) ->get();
方案二:让测试环境使用MySQL
修改测试配置文件(phpunit.xml或pest.php),将测试数据库切换为MySQL,确保测试与生产环境数据库一致:
<!-- phpunit.xml 示例 --> <php> <env name="DB_CONNECTION" value="mysql"/> <env name="DB_DATABASE" value="your_test_database"/> <env name="DB_USERNAME" value="root"/> <env name="DB_PASSWORD" value="your_password"/> </php>
注意:需提前创建测试专用数据库,测试前执行数据迁移。
方案三:为SQLite注册自定义函数
在测试基类中为SQLite注册缺失的MySQL函数,让SQLite兼容这些语法:
// tests/TestCase.php use Illuminate\Support\Facades\DB; protected function setUp(): void { parent::setUp(); if (DB::getDriverName() === 'sqlite') { $pdo = DB::connection()->getPdo(); // 注册YEAR函数 $pdo->sqliteCreateFunction('YEAR', fn($date) => date('Y', strtotime($date))); // 注册MONTH函数 $pdo->sqliteCreateFunction('MONTH', fn($date) => date('m', strtotime($date))); // 注册DATE_FORMAT函数 $pdo->sqliteCreateFunction('DATE_FORMAT', fn($date, $format) => date($format, strtotime($date))); } }
内容的提问来源于stack exchange,提问作者Theodory
相关产品推荐
相关产品推荐

