【问题标题】:Laravel - Turn part of a function into a queued statementLaravel - 将部分函数转换为排队语句
【发布时间】:2015-09-08 10:27:58
【问题描述】:

我想在我的控制器中对函数的一部分进行排队,主要是因为它访问第 3 方 API 并从所述请求中计算某些信息。我也想这样做来增加我对队列的了解!

我要排队的代码是:

唯一需要使用此if statement 推送的变量是$postcode$clinic ID(在语句上方已确定)。

if($clinic->postcode != $postcode)
    {

     $client = new Client([ 'base_uri' => 'https://api.postcodes.io/','timeout' => 2.0, 'verify' => false ]);
     $response = $client->get('postcodes/'.$postcode)->getBody();

     $input = json_decode($response);

     $clinic->latitude   = $input->result->latitude;
     $clinic->longitude  = $input->result->longitude;
     $clinic->save();
}

到目前为止,我已经创建了queue 表并进行了迁移。

然后我运行命令:php artisan make:job GetClinicLatAndLongPoints --queued

我的问题是,我怎样才能把这个函数放在GetClinicLatAndLongPoints 中,包括传递两个变量来这样做?

到目前为止:

public function handle(Clinic $clinic, $postcode)
    {

    }

但我不确定如何布置!任何指导将不胜感激。

【问题讨论】:

  • 你使用的是什么版本的 laravel,你都标记了!大声笑
  • 糟糕,对不起!我已经删除了 Laravel 4。我正在使用最新的 Laravel 5.1.*!
  • 您是否尝试将其复制粘贴到您的句柄函数中?还要确保您的队列正在运行 (php artisan queue:listen)
  • 是的,但我不确定如何传递必要的变量以使 if statement 正常工作。
  • 我认为 L5 支持 Eloquent Model 实例的对象序列化。只需发送模型,看看会发生什么;)

标签: php laravel laravel-5 task-queue


【解决方案1】:

您可以将Clinic 模型的实例和邮政编码传递给您的工作的构造函数,这可能看起来像

namespace App\Jobs;

use App\Clinic;
use App\Jobs\Job;
use GuzzleHttp\Client;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Queue\ShouldQueue;

class GetClinicLatAndLongPoints extends Job implements SelfHandling, ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    private $clinic;
    private $postcode;

    public function __construct(Clinic $clinic, $postcode)
    {
        $this->clinic = $clinic; // Laravel will automatically deserialize the model instance
        $this->postcode = $postcode;
    }

    public function handle()
    {
        $coordinates = $this->getCoordinates($this->postcode);

        if (! is_null($coordinates)) {
            // You may want to add error handling
            $this->clinic->latitude   = $coordinates['latitude'];
            $this->clinic->longitude  = $coordinates['longitude'];
            $this->clinic->save();
        }
    }

    private function getCoordinates($postcode)
    {
        $client = new Client(['base_uri' => 'https://api.postcodes.io/','timeout' => 2.0, 'verify' => false]);
        $response = json_decode($client->get('postcodes/'.$postcode)->getBody()->getContents());
        if (! $response || json_last_error() !== JSON_ERROR_NONE) {
            return null;
        }
        if ($response->status == 200 &&
            isset($response->result->latitude) &&
            isset($response->result->longitude)) {
            return [
                'latitude' => $response->result->latitude,
                'longitude' => $response->result->longitude
            ];
        }
        return null;
    }
}

在你的控制器中你调度你的工作

if ($clinic->postcode != $postcode) {
    $this->dispatch(new GetClinicLatAndLongPoints($clinic, $postcode));
}

附带说明:尽管 Laravel 附带数据库队列驱动程序,但在生产环境中使用它并不是一个好主意。最好使用job queues 之一,即beanstalkd

【讨论】:

  • 多么棒的答案,非常清楚!非常感谢您的帮助@peterm!作为您答案的补充,我必须将use App\Jobs\GetClinicLatAndLongPoints; 添加到控制器中。我目前遇到的唯一问题是 GetClinicLatAndLongPoints 脚​​本中的以下错误 - "FatalErrorException in GetClinicLatAndLongPoints.php line 13: Class 'App\Jobs\Job' not found"。 GetClinicLat... 不在“工作”文件夹中,也就是说,只是 Jobs 文件夹。我不确定这是为什么?
  • 事实证明我没有 Laravel 自带的默认 Job.php!复制它会使一切正常工作。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
  • 1970-01-01
  • 1970-01-01
  • 2013-12-01
  • 2014-10-09
  • 2012-02-04
  • 1970-01-01
相关资源
最近更新 更多