Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
利用Laravel中的Guzzle提高代码质量_Laravel_Guzzle - Fatal编程技术网

利用Laravel中的Guzzle提高代码质量

利用Laravel中的Guzzle提高代码质量,laravel,guzzle,Laravel,Guzzle,我是拉威尔的新人,所以请不要太苛刻 我正在构建一个简单的web,它通过Guzzle连接到一个外部API(几个端点),获取一些数据,清理并存储它们 目前,从一个端点来看,我有以下工作: public function handle(Client $client) { try { $request= $client->request('GET', 'https://api.url./something', [ 'heade

我是拉威尔的新人,所以请不要太苛刻

我正在构建一个简单的web,它通过Guzzle连接到一个外部API(几个端点),获取一些数据,清理并存储它们

目前,从一个端点来看,我有以下工作:

public function handle(Client $client)
{
        try {
            $request= $client->request('GET', 'https://api.url./something', [
                'headers' => [
                    'X-RapidAPI-Key'=> env("FOOTBALL_API_KEY"),
                    'Accept'     => 'application/json'
                ]
            ]);
            $request = json_decode($request->getBody()->getContents(), true);
            foreach ($request as $array=>$val) {
                foreach ($val['leagues'] as $id) {
                    League::firstOrCreate(collect($id)->except(['coverage'])->toArray());
                }
            }
        } catch (GuzzleException $e) {
        };
}
因此,我想提出一些代码建议,如何从设计的角度使我的代码更好

我的想法是:

a) 将Guzzle绑定为
服务提供商

b) 使用设计模式实现对端点的调用。
URI
builder

任何协助都将不胜感激

愿原力与你同在。

详细反馈 特定于所提供代码本身的一些指针:

  • guzzle客户端
    请求
    返回的响应与指定给它的参数名称不匹配
  • 调用
    json\u decode
    可能会失败,在这种情况下,它们将返回
    null
    。在防御性编程方面,最好检查那些失败的情况
  • 您的案例对回复中的数据进行了一些假设。在使用响应之前,最好检查它是否是您期望的实际格式
  • 您捕获了所有异常,但在这些情况下什么也不做。我认为你可以通过以下两种方式来改善这一点:
    • 记录异常
    • 引发另一个异常,您将在类中捕获该异常,调用
      handle()
      方法
    • 以上两个选项
  • 您可以选择注入api键,而不是通过
    env()
    方法直接获取它。这将防止中描述的问题
一般反馈 感觉您的代码混合了责任,这被认为是不好的做法。
handle()
方法现在执行以下操作:

  • 发送API请求
  • 解码API请求
  • 验证API响应
  • 解析API响应
  • 创建模型
<>你可以考虑把其中的一些或全部移到单独的类中,比如:

  • ApiClient
    负责发送请求
  • 负责将响应转换为
    \stdClass
  • ResponseValidator
    负责检查响应是否具有预期的数据结构
  • repsonseparaser
    负责将响应
    \stdClass
    转换为集合
  • LeagueFactory
    负责将系列转化为
    League
    型号
有人可能认为前四个类应该放在一个名为
ApiClient
的类中。那完全取决于你

所以最后你会想出这样的办法:

<?php


namespace App\Example;

use Psr\Log\LoggerInterface;

class LeagueApiHandler
{
    /**
     * @var ApiClient
     */
    private $apiClient;
    /**
     * @var ResponseDecoder
     */
    private $decoder;
    /**
     * @var ResponseValidator
     */
    private $validator;
    /**
     * @var ResponseParser
     */
    private $parser;
    /**
     * @var LeagueFactory
     */
    private $factory;
    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(
        ApiClient $apiClient,
        ResponseDecoder $decoder,
        ResponseValidator $validator,
        ResponseParser $parser,
        LeagueFactory $factory,
        LoggerInterface $logger
    ) {
        $this->apiClient = $apiClient;
        $this->decoder = $decoder;
        $this->validator = $validator;
        $this->parser = $parser;
        $this->factory = $factory;
        $this->logger = $logger;
    }

    public function handle()
    {
        try {
            $response = $this->apiClient->send();
        } catch (\RuntimeException $e) {
            $this->logger->error('Unable to send api request', $e->getMessage());
            return;
        };

        try {
            $decodedResponse = $this->decoder->decode($response);
        } catch (\RuntimeException $e) {
            $this->logger->error('Unable to decode api response');
            return;
        };

        if (!$this->validator->isValid($decodedResponse)) {
            $this->logger->error('Unable to decode api response');
            return;
        }

        $collections = $this->parser->toCollection($decodedResponse);
        foreach ($collections as $collection) {
            $this->factory->create($collection);
        }
    }
}

非常感谢您的反馈,非常感谢。我会处理你的评论。你能给我提供一些材料来研究“如何在laravel中设计代码”吗?我没有任何laravel特定的资料给你,但你可以看看作者写的。他有一些关于干净编码的好主意
namespace App\Example;

use GuzzleHttp\Client;

class ApiClient
{
    /**
     * @var Client
     */
    private $client;
    /**
     * @var string
     */
    private $apiKey;

    public function __construct(Client $client, string $apiKey)
    {
        $this->client = $client;
        $this->apiKey = $apiKey;
    }

    public function send()
    {
        try {
            return $this->client->request('GET', 'https://api.url./something', [
                'headers' => [
                    'X-RapidAPI-Key' => $this->apiKey,
                    'Accept' => 'application/json'
                ]
            ]);
        } catch (GuzzleException $e) {
            throw new \RuntimeException('Unable to send request to api', 0, $e);
        };
    }
}
namespace App\Example;

use Psr\Http\Message\ResponseInterface;

class ResponseDecoder
{
    public function decode(ResponseInterface $response): \stdClass
    {

        $response = json_decode($response->getBody()->getContents(), true);
        if ($response === null) {
            throw new \RuntimeException('Unable to decode api response');
        }

        return $response;
    }
}
namespace App\Example;

class ResponseValidator
{
    public function isValid(\stdClass $response): bool
    {
        if (is_array($response) === false) {
            return false;
        }

        foreach ($response as $array) {
            if (!isset($array['leagues'])) {
                return false;
            }
        }

        return true;
    }
}
namespace App\Example;

use Illuminate\Support\Collection;

class ResponseParser
{
    /**
     * @param \stdClass $response
     * @return Collection[]
     */
    public function toCollection(\stdClass $response): array
    {
        $collections = [];
        foreach ($response as $array => $val) {
            foreach ($val['leagues'] as $id) {
                $collections[] = collect($id)->except(['coverage'])->toArray();
            }
        }
        return $collections;
    }
}
namespace App\Example;

use Illuminate\Support\Collection;

class LeagueFactory
{
    public function create(Collection $collection): void
    {
        League::firstOrCreate($collection);
    }
}