Rumah  >  Artikel  >  rangka kerja php  >  Mari kita bincangkan tentang cara menggunakan Saloon untuk penyepaduan API dalam Laravel

Mari kita bincangkan tentang cara menggunakan Saloon untuk penyepaduan API dalam Laravel

青灯夜游
青灯夜游ke hadapan
2022-10-27 19:28:341195semak imbas

Bagaimana untuk menggunakan Saloon untuk penyepaduan API dalam Laravel? Artikel berikut akan memperkenalkan kepada anda cara menggunakan Saloon untuk penyepaduan API dalam Laravel. Saya harap ia akan membantu anda!

Mari kita bincangkan tentang cara menggunakan Saloon untuk penyepaduan API dalam Laravel

Kami semua pernah ke sana, kami mahu menyepadukan dengan API pihak ketiga dalam Laravel dan kami bertanya kepada diri sendiri "bagaimana saya harus melakukannya?". Saya tidak asing apabila bercakap tentang penyepaduan API, tetapi setiap kali saya tertanya-tanya apakah pendekatan terbaik. Sam Carré membina pakej pada awal 2022 yang dipanggil Saloon yang menjadikan integrasi API kami menakjubkan. Walau bagaimanapun, siaran ini akan menjadi sangat berbeza, ia akan menjadi panduan tentang cara menggunakannya untuk membina integrasi dari awal.

Seperti semua perkara yang hebat, ia bermula dengan laravel new dan pergi dari sana, jadi mari kita mulakan. Sekarang apabila memasang Laravel anda boleh menggunakan sama ada laravel installer atau composer - bahagian ini terpulang kepada anda. Saya akan mengesyorkan pemasang jika anda boleh, kerana ia menyediakan pilihan mudah untuk melakukan lebih daripada sekadar membuat projek. Buat projek baharu dan bukanya dalam editor kod pilihan anda. Sebaik sahaja kami berada di sana, kami bersedia untuk pergi.

Apa yang akan kita bina? Saya sangat gembira untuk menjawab soalan ini! Kami akan membina integrasi dengan API GitHub untuk mendapatkan senarai aliran kerja yang tersedia untuk repo. Sekarang, jika anda seperti saya dan menghabiskan banyak masa pada baris arahan, ini boleh menjadi sangat berguna. Anda sedang membangunkan aplikasi, menolak perubahan pada cawangan atau mencipta PR - ia melalui aliran kerja yang mungkin menjalankan salah satu daripada banyak perkara lain. Mengetahui status aliran kerja ini kadangkala boleh memberi impak yang besar pada perkara yang anda lakukan seterusnya. Adakah ia berfungsi sepenuhnya? Adakah terdapat masalah dengan cara aliran kerja kami berjalan? Adakah ujian atau analisis statik kami lulus? Semua ini biasanya anda tunggu dan semak repo di GitHub untuk melihat status. Penyepaduan ini akan membolehkan anda menjalankan perintah artisan, mendapatkan senarai aliran kerja yang tersedia untuk repo dan membolehkan anda mencetuskan aliran kerja baharu untuk dijalankan.

Jadi sekarang komposer sepatutnya telah menjalankan tugasnya dan memasang titik permulaan yang sempurna, aplikasi Laravel. Seterusnya kami perlu memasang Saloon - tetapi kami ingin memastikan kami memasang versi laravel, jadi jalankan arahan berikut dalam terminal:

composer require sammyjo20/saloon-laravel

Sama seperti itu, kami selangkah lebih dekat kepada penyepaduan yang lebih mudah . Jika anda mempunyai sebarang soalan pada peringkat ini, pastikan anda menyemak versi Laravel dan PHP yang anda gunakan, kerana Saloon memerlukan sekurang-kurangnya Laravel 8 dan PHP 8!

Jadi, sekarang setelah kami memasang Saloon, kami perlu mencipta kelas baharu. Dalam terminologi Saloons, ini ialah "penyambung" dan semua yang dilakukan oleh penyambung ialah mencipta cara bertumpu objek untuk menyatakan - API ini melalui sambungan sedemikian. Terdapat perintah artisan yang berguna yang membolehkan anda menciptanya, jadi jalankan perintah artisan berikut untuk mencipta penyambung GitHub:

php artisan saloon:connector GitHub GitHubConnector

Arahan itu dalam dua bahagian, parameter pertama ialah penyepaduan yang anda cipta , dan yang kedua Parameter kedua ialah nama penyambung yang akan dibuat. Ini bermakna anda boleh mencipta berbilang penyambung untuk penyepaduan anda - menyambungkannya dalam pelbagai cara jika perlu.

Ini akan mencipta kelas baharu untuk anda di bawah app/Http/Integrations/GitHub/GitHubConnector.php, mari lihat untuk memahami perkara yang sedang berlaku.

Perkara pertama yang kami lihat ialah penyambung kami memanjangkan "SaloonConnector", yang akan membolehkan kami membuat penyambung kami berfungsi tanpa banyak kod plat dandang. Kemudian kami mewarisi ciri yang dipanggil "AcceptsJson". Sekarang, jika kita melihat dokumentasi Saloon, kita tahu ini adalah pemalam. Ini pada asasnya menambah pengepala pada permintaan kami yang memberitahu API pihak ke-3 bahawa kami mahu menerima respons JSON. Perkara seterusnya yang kita lihat ialah kita mempunyai kaedah untuk mentakrifkan URL asas penyambung kita - jadi mari tambahkan:

public function defineBaseUrl(): string
{
    return 'https://api.github.com';
}

Bagus dan bersih, malah kita boleh melangkah lebih jauh supaya kita mungkin untuk mengendalikan lebih sedikit rentetan longgar dalam aplikasi anda - jadi mari lihat bagaimana kita boleh melakukannya. Tambahkan rekod perkhidmatan baharu pada fail config/services.php anda:

'github' => [
    'url' => env('GITHUB_API_URL', 'https://api.github.com'),
]

Ini akan membolehkan kami mengatasinya dalam persekitaran yang berbeza - memberikan kami penyelesaian yang lebih baik dan lebih boleh diuji. Secara tempatan, kami juga boleh mengejek API GitHub menggunakan spesifikasi OpenAPI mereka dan mengujinya untuk memastikan ia berfungsi dengan betul. Walau bagaimanapun, tutorial ini adalah mengenai Saloon, jadi saya menyimpang... Sekarang mari kita memfaktorkan semula kaedah URL asas kami untuk menggunakan konfigurasi:

public function defineBaseUrl(): string
{
    return (string) config('services.github.url');
}

Seperti yang anda lihat, kami kini mendapat rekod baru yang ditambah - dan ditukar kepada rentetan untuk memastikan keselamatan jenis - config() boleh mengembalikan beberapa jenis hasil yang berbeza. Kami mahu tegas tentang perkara ini jika boleh.

接下来我们有默认 header 和默认配置,无须担心默认 header 的内容,因为我们将在一段时间内自行处理身份验证。但配置部分是我们可以为集成定义 guzzle 选项的地方,因为 Saloon 在服务引擎下使用了 Guzzle。现在让我们设置超时并继续,我们需要花一些时间配置它:

public function defaultConfig(): array
{
    return [
        'timeout' => 30,
    ];
}

我们现在已经按照我们的需要配置了我们的连接器,如果我们有需要添加的配置,可以稍后再添加。下一步是开始考虑我们要发送的请求。如果我们查看 GitHub Actions API 的 API 文档,我们有很多选择,我们将从列出特定存储库的工作流开始:/repos/{owner}/{repo}/actions/workflows。运行以下 artisan 命令创建一个新请求:

php artisan saloon:request GitHub ListRepositoryWorkflowsRequest

同样,第一个参数是集成,第二个参数是我们要创建的请求的名称。我们需要确保为我们正在创建的请求命名集成,以便它存在于正确的位置,然后我们需要给它一个名称。我将我的命名为 ListRepositoryWorkflowsRequest,因为我喜欢描述性的命名方法 - 但是,你可以随意调整以适应你喜欢的命名方式。这将创建一个新文件供我们查看:app/Http/Integrations/GitHub/Requests/ListRepositoryWorkflowsRequest.php - 现在让我们看一下。

我们再次在这里扩展了一个库类,这次是预期的 SaloonRequest。这里会包含一个连接器属性和一个方法。如果需要,我们可以修改这个方法 - 但默认的 GET 是我们现在需要的。然后我们有一个定义端点的方法。重构你的请求类,使其类似于以下示例:

 class ListRepositoryWorkflowsRequest extends SaloonRequest
{
    protected ?string $connector = GitHubConnector::class;

    protected ?string $method = Saloon::GET;

    public function __construct(
        public string $owner,
        public string $repo,
    ) {}

    public function defineEndpoint(): string
    {
        return "/repos/{$this->owner}/{$this->repo}/actions/workflows";
    }
}

我们所做的是添加一个构造函数,它接受 repo 和 owner 作为参数,然后我们可以在端点定义方法中使用它们。我们还将连接器设置为我们之前创建的 GitHubConnector。所以我们有一个我们知道可以发送的请求,我们可以从集成中走一小步,转而考虑控制台命令。

如果你之前没有在 Laravel 中创建过控制台命令,请务必查看 文档。运行以下 artisan 命令来为此集成创建第一个命令:

php artisan make:command GitHub/ListRepositoryWorkflows

这将创建以下文件:app/Console/Commands/GitHub/ListRespositoryWorkflows.php。我们现在可以开始使用命令来发送请求并获取我们关心的数据。当谈到控制台命令时,我总是做的第一件事就是考虑签名。我希望如何调用它?它需要能够解释它正在做什么,同时具备一定的辨识度。我将会用 github:workflows 作为签名,因为这很好地解释了我想做的事情。我们还可以向控制台命令添加描述,以便在浏览可用命令时更好地解释目的:「通过存储库名称从 GitHub 获取工作流列表」。

最后,我们到了命令的 handle 方法,这部分是我们实际需要做的事情。在我们的例子中,我们将发送一个请求,获取一些数据并以某种方式显示这些数据。然而,在我们能够做到这一点之前,我们还没有完成一件事。那就是身份验证。

对于每一个 API 集成,身份验证都是关键方面之一——我们需要 API 不仅知道我们是谁,而且知道我们实际上被允许发出这个请求。如果你转到 你的 GitHub 设置 并点击进入开发人员设置和个人访问令牌,在此你可以生成自己的设置。我建议使用这种方法,而不是为此使用完整的 OAuth 应用程序。我们不需要 OAuth,我们只需要用户能够访问他们需要的内容。

获得访问令牌后,我们需要将其添加到我们的 .env 文件中,并确保我们可以通过配置提取它。

GITHUB_API_TOKEN=ghp_loads-of-letters-and-numbers-here

我们现在可以在 github 下的 config/services.php 中扩展我们的服务,添加这个令牌:

'github' => [
    'url' => env('GITHUB_API_URL', 'https://api.github.com'),
    'token' => env('GITHUB_API_TOKEN'),
]

现在我们有了一个加载这个令牌的好方法,我们可以回到我们的控制台命令!我们需要修改我们的签名以允许我们接受所有者和存储库作为参数:

 class ListRepositoryWorkflows extends Command
{
    protected $signature = 'github:workflows
        {owner : The owner or organisation.}
        {repo : The repository we are looking at.}
    ';

    protected $description = 'Fetch a list of workflows from GitHub by the repository name.';

    public function handle(): int
    {
        return 0;
    }
}

现在我们可以将注意力转移到 handle 方法上:

public function handle(): int
{
    $request = new ListRepositoryWorkflowsRequest(
        owner: $this->argument('owner'),
        repo: $this->argument('repo'),
    );

    return self::SUCCESS;
}

在这里,我们开始通过将参数直接传递到请求本身来构建我们的请求,但是我们可能想要做的是创建一些局部变量来提供一些控制台反馈:

 public function handle(): int
{
    $owner = (string) $this->argument('owner');
    $repo = (string) $this->argument('repo');

    $request = new ListRepositoryWorkflowsRequest(
        owner: $owner,
        repo: $repo,
    );

    $this->info(
        string: "Fetching workflows for {$owner}/{$repo}",
    );

    return self::SUCCESS;
}

所以我们有一些反馈给用户,这对于控制台命令来说总是很重要的。现在我们需要添加我们的身份验证令牌并实际发送请求:

 public function handle(): int
{
    $owner = (string) $this->argument('owner');
    $repo = (string) $this->argument('repo');

    $request = new ListRepositoryWorkflowsRequest(
        owner: $owner,
        repo: $repo,
    );

    $request->withTokenAuth(
        token: (string) config('services.github.token'),
    );

    $this->info(
        string: "Fetching workflows for {$owner}/{$repo}",
    );

    $response = $request->send();

    return self::SUCCESS;
}

如果你修改上述内容并在 $response->json() 上执行 dd(),然后运行命令:

php artisan github:workflows laravel laravel

这将获得 laravel/laravel repo 的工作流列表。我们的命令将允许你使用任何公共存储库,如果你希望它更具体,你可以建立一个要检查的存储库选项列表,而不是接受参数 —— 但这部分取决于你个人。对于本教程,我将重点关注更广泛更开放的用例。

现在,我们从 GitHub API 得到的响应非常好且信息丰富,但它需要转换才能显示,如果我们孤立地查看它,则没有上下文。相反,我们将在我们的请求中添加另一个插件,这将允许我们将响应转换为 DTO(域传输对象),这是处理此问题的好方法。它将允许我们放松我们习惯于从 API 获取的灵活数组,并获得更具上下文感知的东西。让我们为工作流创建一个 DTO,创建一个新文件:app/Http/Integrations/GitHub/DataObjects/Workflow.php 并向其中添加以下代码:

 class Workflow
{
    public function __construct(
        public int $id,
        public string $name,
        public string $state,
    ) {}

    public static function fromSaloon(array $workflow): static
    {
        return new static(
            id: intval(data_get($workflow, 'id')),
            name: strval(data_get($workflow, 'name')),
            state: strval(data_get($workflow, 'state')),
        );
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'state' => $this->state,
        ];
    }
}

我们有一个构造函数,其中包含我们要显示的工作流的重要部分,一个 fromSaloon 方法,它将一个数组从一个 saloon 转换为一个新的 DTO,以及一个用于将 DTO 显示回数组的数组方法当我们需要它时。在我们的ListRepositoryWorkflowsRequest 中,我们需要继承一个新特征并添加一个新方法:

 class ListRepositoryWorkflowsRequest extends SaloonRequest
{
    use CastsToDto;

    protected ?string $connector = GitHubConnector::class;

    protected ?string $method = Saloon::GET;

    public function __construct(
        public string $owner,
        public string $repo,
    ) {}

    public function defineEndpoint(): string
    {
        return "/repos/{$this->owner}/{$this->repo}/actions/workflows";
    }

    protected function castToDto(SaloonResponse $response): Collection
    {
        return (new Collection(
            items: $response->json('workflows'),
        ))->map(function ($workflow): Workflow {
            return Workflow::fromSaloon(
                workflow: $workflow,
            );
        });
    }
}

我们继承了 CastsToDto trait,它允许这个请求在响应中调用 dto 方法,然后我们添加一个 castToDto 方法,我们可以控制它的转换方式。我们希望它返回一个新的集合,因为有多个工作流,使用响应正文的工作流部分。然后我们映射集合中的每个项目 - 并将其转换为 DTO。现在我们既可以这样做,也可以使用 DTO 构建集合:

protected function castToDto(SaloonResponse $response): Collection
{
    return new Collection(
        items: $response->collect('workflows')->map(fn ($workflow) =>
            Workflow::fromSaloon(
                workflow: $workflow
            ),
        )
    );
}

你可以在这里选择最适合你的方式。我个人更喜欢第一种方法,因为我喜欢逐步了解逻辑,但是这两种方法都没有错——选择权在你。现在回到命令,我们现在需要考虑我们希望如何显示这些信息:

public function handle(): int
{
    $owner = (string) $this->argument('owner');
    $repo = (string) $this->argument('repo');

    $request = new ListRepositoryWorkflowsRequest(
        owner: $owner,
        repo: $repo,
    );

    $request->withTokenAuth(
        token: (string) config('services.github.token'),
    );

    $this->info(
        string: "Fetching workflows for {$owner}/{$repo}",
    );

    $response = $request->send();

    if ($response->failed()) {
        throw $response->toException();
    }

    $this->table(
        headers: ['ID', 'Name', 'State'],
        rows: $response
            ->dto()
            ->map(fn (Workflow $workflow) =>
                  $workflow->toArray()
            )->toArray(),
    );

    return self::SUCCESS;
}

因此,我们创建一个带有标题的表,然后对于我们想要响应 DTO 的行,我们将映射返回的集合,将每个 DTO 转换回要显示的数组。从响应数组转换为 DTO 再转换回数组,这似乎违反直觉,但这会强制执行类型,以便 ID、名称和状态在预期时始终存在,并且不会给出任何有趣的结果.它允许正常响应数组可能没有它的一致性,如果我们愿意,我们可以将它转换为一个值对象,我们可以在其中附加行为。如果我们现在运行我们的命令,我们现在应该会看到一个漂亮的表格输出,它比几行字符串更容易阅读:

php artisan github:workflows laravel laravel
Fetching workflows for laravel/laravel
+----------+------------------+--------+
| ID       | Name             | State  |
+----------+------------------+--------+
| 12345678 | pull requests    | active |
| 87654321 | Tests            | active |
| 18273645 | update changelog | active |
+----------+------------------+--------+

最后,仅仅列出这些工作流程是很棒的——但让我们以科学的名义更进一步。假设你正在针对你的一个存储库运行此命令,并且想手动运行更新更改日志?或者,也许你希望使用你的实时生产服务器或你可能想到的任何事件在 cron 上触发它?我们可以将变更日志设置为每天午夜运行一次,这样我们就可以在变更日志中获得每日回顾或任何我们可能想要的内容。让我们创建另一个控制台命令来创建一个新的工作流调度事件:

php artisan saloon:request GitHub CreateWorkflowDispatchEventRequest

在这个新文件 app/Http/Integrations/GitHub/Requests/CreateWorkflowDispatchEventRequest.php 中添加以下代码,以便我们浏览它:

class CreateWorkflowDispatchEventRequest extends SaloonRequest
{
    use HasJsonBody;

    protected ?string $connector = GitHubConnector::class;

    public function defaultData(): array
    {
        return [
            'ref' => 'main',
        ];
    }

    protected ?string $method = Saloon::POST;

    public function __construct(
        public string $owner,
        public string $repo,
        public string $workflow,
    ) {}

    public function defineEndpoint(): string
    {
        return "/repos/{$this->owner}/{$this->repo}/actions/workflows/{$this->workflow}/dispatches";
    }
}

通过设置连接器,并继承 HasJsonBody 特征以允许我们发送数据。该方法已设置为 POST 请求,因为我们要发送数据。然后我们有一个构造函数,它接受构建端点的 URL 部分。

最后,我们在 defaultData 中有圆顶默认数据,我们可以使用它来设置此发布请求的默认值。与 repo 一样,我们可以在此处传递提交哈希或分支名称 - 所以我将默认设置为 main,因为这就是我通常所说的生产分支。

我们现在可以触发这个端点来调度一个新的工作流事件,所以让我们创建一个控制台命令来控制它,这样我们就可以从我们的 CLI 运行它:

php artisan make:command GitHub/CreateWorkflowDispatchEvent

现在让我们编写具体的逻辑,我们可以了解正在发生的事情:

class CreateWorkflowDispatchEvent extends Command
{
    protected $signature = 'github:dispatch
        {owner : The owner or organisation.}
        {repo : The repository we are looking at.}
        {workflow : The ID of the workflow we want to dispatch.}
        {branch? : Optional: The branch name to run the workflow against.}
    ';

    protected $description = 'Create a new workflow dispatch event for a repository.';

    public function handle(): int
    {
        $owner = (string) $this->argument('owner');
        $repo = (string) $this->argument('repo');
        $workflow = (string) $this->argument('workflow');

        $request = new CreateWorkflowDispatchEventRequest(
            owner: $owner,
            repo: $repo,
            workflow: $workflow,
        );

        $request->withTokenAuth(
            token: (string) config('services.github.token'),
        );

        if ($this->hasArgument('branch')) {
            $request->setData(
                data: ['ref' => $this->argument('branch')],
            );
        }

        $this->info(
            string: "Requesting a new workflow dispatch for {$owner}/{$repo} using workflow: {$workflow}",
        );

        $response = $request->send();

        if ($response->failed()) {
            throw $response->toException();
        }

        $this->info(
            string: 'Request was accepted by GitHub',
        );

        return self::SUCCESS;
    }
}

就像在我们有签名和描述之前一样,这次我们的签名有一个可选的分支,以防我们想要覆盖请求中的默认值。所以在我们的处理方法中,我们可以简单地检查输入是否有参数 branch,如果有,我们可以解析它并为请求设置数据。然后我们向 CLI 提供一些反馈,让用户知道我们在做什么 - 并发送请求。如果此时一切顺利,我们可以简单地输出一条消息,通知用户 GitHub 接受了请求。但是,如果出现问题,我们希望抛出特定的异常,至少在开发过程中是这样。

最后一个请求的主要警告是,我们的工作流程设置为通过在工作流程中添加一个新的 on 项目来由 webhook 触发:

on: workflow_dispatch

这就对了!我们使用 Saloon 和 Laravel 不仅列出存储库工作流程,而且如果配置正确,我们还可以触发它们按需运行:muscle:

正如我在本教程开始时所说的,有很多方法可以实现 API 集成,但有一点是肯定的 - 使用 Saloon 使它变得干净和简单,而且使用起来也非常愉快。

原文地址:https://laravel-news.com/api-integrations-using-saloon-in-laravel

译文地址:https://learnku.com/laravel/t/69007

【相关推荐:laravel视频教程

Atas ialah kandungan terperinci Mari kita bincangkan tentang cara menggunakan Saloon untuk penyepaduan API dalam Laravel. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:learnku.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam