Doctrine扩展本地正常运行,生产服务器部署后DATE函数报错
配置与代码情况
容器绑定EntityManager的配置
....... Config::class => create(Config::class)->constructor( require CONFIG_PATH . '/app.php' ), EntityManager::class => function (Config $config) { $configuration = ORMSetup::createAttributeMetadataConfiguration( $config->get('doctrine.entity_dir'), $config->get('doctrine.dev_mode'), ); $configuration->addCustomDatetimeFunction('DATE', 'DoctrineExtensions\Query\MySql\Date'); return new EntityManager( new Connection($config->get('doctrine.connection'), new Driver()), $configuration ); },
验证用户输入的代码(使用DATE函数)
$v->rule( function ($field, $value, $params, $fields) use (&$data) { if ($value === '') { return true; } $dateToBook = explode('T', $value)[0]; $today = (new DateTime())->format('Y-m-d'); $checkDay = $this->entityManager ->createQuery("SELECT DATE(j.dueDate) FROM App\Entity\Job j where DATE(j.dueDate) = :booked AND DATE(j.dueDate) > :today") ->setParameters([ 'booked'=> $dateToBook, 'today' => $today ])->getArrayResult(); if (count($checkDay) > 0 && $data['forceBooking'] === '') { return false; } elseif (count($checkDay) > 0 && $data['forceBooking'] !== '') { return true; } return true; }, 'dueDate' )->message('Warning: There is an event on this day');
报错信息
部署到生产服务器后,执行上述代码时报错:
Class DoctrineExtensions\Query\MySql\Date not found
报错文件路径:/home/XXXXX.cloudwaysapps.com/vxbtnydbjs/public_html/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php,行号3616。
已尝试的操作
根据官方说明,尝试手动注册ClassLoader,启动文件代码如下:
<?php declare(strict_types = 1); use Doctrine\Common\ClassLoader; use Dotenv\Dotenv; require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/configs/path_constants.php'; $dotenv = Dotenv::createImmutable(__DIR__); $dotenv->load(); $classLoader = new ClassLoader('DoctrineExtensions', __DIR__ . '/vendor/beberlei/doctrineextensions'); $classLoader->register(); return require CONFIG_PATH . '/container/container.php';
同步代码到服务器后,错误仍存在,但本地环境可正常运行。
解决建议
1. 修正ClassLoader的路径
手动注册的ClassLoader路径错误,DoctrineExtensions命名空间对应的类文件在包的src目录下,而非包根目录。修改启动文件中的ClassLoader代码:
$classLoader = new ClassLoader('DoctrineExtensions', __DIR__ . '/vendor/beberlei/doctrineextensions/src'); $classLoader->register();
2. 依赖Composer自动加载(推荐方案)
既然已经引入了vendor/autoload.php,Composer会自动处理beberlei/doctrineextensions的命名空间映射,无需手动注册ClassLoader。直接删除启动文件中手动注册ClassLoader的代码,确保require __DIR__ . '/vendor/autoload.php';是最先执行的代码之一。
同时在生产环境执行以下命令,确保自动加载文件更新:
composer dump-autoload -o
3. 验证依赖安装情况
登录生产服务器,检查vendor/beberlei/doctrineextensions/src/DoctrineExtensions/Query/MySql/Date.php文件是否存在。如果不存在,重新执行依赖安装:
composer install --no-dev --optimize-autoloader
4. 清除Doctrine缓存
生产环境下Doctrine可能启用了元数据缓存,导致新添加的自定义函数配置未生效。清除Doctrine的缓存目录(通常是var/cache/doctrine或类似路径),或者在EntityManager配置中临时关闭缓存进行测试。
内容的提问来源于stack exchange,提问作者Zuby

