You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的返回格式:

  1. 创建自定义队列类
    在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);
    }
}
  1. 注册自定义队列驱动
    在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']
        );
    });
}
  1. 配置队列连接
    修改config/queue.php,添加Oracle队列连接配置:
'connections' => [
    // ...其他连接
    
    'oracle-database' => [
        'driver' => 'oracle-database',
        'connection' => 'oracle', // 对应database.php中的Oracle连接名
        'table' => 'jobs',
        'queue' => 'default',
        'retry_after' => 90,
    ],
],
  1. 切换默认队列连接
    在.env文件中设置默认队列为自定义的Oracle驱动:
QUEUE_CONNECTION=oracle-database
  1. 可选:更新驱动版本
    确保yajra/laravel-oci8包是最新兼容版本,执行:
composer update yajra/laravel-oci8

完成以上步骤后,重新执行php artisan queue:work即可正常处理Oracle数据库中的队列任务。


内容的提问来源于stack exchange,提问作者Khalid Hasan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:45:26