Laravel连接Oracle时queue:work命令无法处理任务问题
Laravel连接Oracle时
php artisan queue:work执行失败,报Array to string转换错误 连接Oracle数据库时,执行php artisan queue:work无法处理队列任务,报错栈信息如下:
#0 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Foundation\Bootstrap\HandleExceptions.php(266): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Array to string...', 'C:\\laragon\\www\\...', 32) #1 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Support\Stringable.php(32): Illuminate\Foundation\Bootstrap\HandleExceptions->Illuminate\Foundation\Bootstrap\{closure}(2, 'Array to string...', 'C:\\laragon\\www\\...', 32) #2 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Support\Str.php(68): Illuminate\Support\Stringable->__construct(Array) #3 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\DatabaseQueue.php(261): Illuminate\Support\Str::of(Array) #4 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\DatabaseQueue.php(239): Illuminate\Queue\DatabaseQueue->getLockForPopping() #5 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\DatabaseQueue.php(224): Illuminate\Queue\DatabaseQueue->getNextAvailableJob('default') #6 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Database\Concerns\ManagesTransactions.php(30): Illuminate\Queue\DatabaseQueue->Illuminate\Queue\{closure}(Object(Yajra\Oci8\Oci8Connection)) #7 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\DatabaseQueue.php(227): Illuminate\Database\Connection->transaction(Object(Closure)) #8 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(342): Illuminate\Queue\DatabaseQueue->pop('default') #9 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(351): Illuminate\Queue\Worker->Illuminate\Queue\{closure}('default') #10 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(160): Illuminate\Queue\Worker->getNextJob(Object(Illuminate\Queue\DatabaseQueue), 'default') #11 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\Console\WorkCommand.php(147): Illuminate\Queue\Worker->daemon('database', 'default', Object(Illuminate\Queue\WorkerOptions)) #12 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Queue\Console\WorkCommand.php(130): Illuminate\Queue\Console\WorkCommand->runWorker('database', 'default') #13 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(36): Illuminate\Queue\Console\WorkCommand->handle() #14 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Container\Util.php(41): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}() #15 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure)) #16 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure)) #17 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Container\Container.php(661): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL) #18 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Console\Command.php(183): Illuminate\Container\Container->call(Array) #19 C:\laragon\www\emt\vendor\symfony\console\Command\Command.php(312): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle)) #20 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Console\Command.php(153): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle)) #21 C:\laragon\www\emt\vendor\symfony\console\Application.php(1022): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\Output\ConsoleOutput)) #22 C:\laragon\www\emt\vendor\symfony\console\Application.php(314): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #23 C:\laragon\www\emt\vendor\symfony\console\Application.php(168): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #24 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Console\Application.php(102): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #25 C:\laragon\www\emt\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php(155): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #26 C:\laragon\www\emt\artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #27 {main}
切换到MySQL数据库时,该命令可正常执行。
问题原因
报错根源在Illuminate\Queue\DatabaseQueue的getLockForPopping方法中:Laravel默认实现调用数据库生成锁值时,MySQL驱动返回字符串,但Yajra/Oci8驱动对Oracle的SYS_GUID()函数返回的是数组/对象格式,导致Str::of()尝试将数组转为字符串时失败。
解决方案
通过自定义Oracle专属的队列处理类,适配Oracle的返回格式:
- 创建自定义队列类
在app/Queue目录下新建OracleDatabaseQueue.php:
<?php namespace App\Queue; use Illuminate\Queue\DatabaseQueue; class OracleDatabaseQueue extends DatabaseQueue { protected function getLockForPopping() { // 使用Oracle的SYS_GUID生成锁ID,提取字符串值 $lockResult = $this->connection->selectOne("SELECT SYS_GUID() AS lock_id FROM DUAL"); return is_object($lockResult) ? $lockResult->LOCK_ID : ($lockResult['lock_id'] ?? $this->getRandomLock()); } // 兜底生成随机锁值 protected function getRandomLock() { return \Illuminate\Support\Str::random(32); } }
- 注册自定义队列驱动
在app/Providers/AppServiceProvider.php的boot方法中添加驱动注册逻辑:
use App\Queue\OracleDatabaseQueue; use Illuminate\Support\Facades\Queue; public function boot() { Queue::extend('oracle-database', function ($app) { $config = $app['config']['queue.connections.oracle-database']; return new OracleDatabaseQueue( $app['db']->connection($config['connection']), $config['table'], $config['queue'], $config['retry_after'] ); }); }
- 配置队列连接
修改config/queue.php,添加Oracle队列连接配置:
'connections' => [ // ...其他连接 'oracle-database' => [ 'driver' => 'oracle-database', 'connection' => 'oracle', // 对应database.php中的Oracle连接名 'table' => 'jobs', 'queue' => 'default', 'retry_after' => 90, ], ],
- 切换默认队列连接
在.env文件中设置默认队列为自定义的Oracle驱动:
QUEUE_CONNECTION=oracle-database
- 可选:更新驱动版本
确保yajra/laravel-oci8包是最新兼容版本,执行:
composer update yajra/laravel-oci8
完成以上步骤后,重新执行php artisan queue:work即可正常处理Oracle数据库中的队列任务。
内容的提问来源于stack exchange,提问作者Khalid Hasan
相关产品推荐
相关产品推荐

