spinen / halo-php-client
SPINEN 的 Halo PHP 客户端。
Requires
- php: ^8.1
- ext-json: *
- guzzlehttp/guzzle: ^7.0
- laravel/framework: ^9.19|^10|^11
- nesbot/carbon: ^2.62.1|^3
Requires (Dev)
- laravel/pint: ^1.4
- mockery/mockery: ^1.5.1
- phpunit/phpunit: ^10
- psy/psysh: ^0.11.1
- scrutinizer/ocular: ^1.9
- squizlabs/php_codesniffer: ^3.7
- dev-develop
- 1.0.1
- 1.0.0
- 0.7.0
- 0.6.1
- 0.6.0
- 0.5.0
- 0.4.1
- 0.4.0
- 0.3.0
- 0.2.0
- 0.1.0
- 0.0.1
- dev-master
- dev-feature/allowSettingAnArrayOfWheres
- dev-feature/addSlaAndWorkday
- dev-feature/addOrganizationAndPriority
- dev-feature/addAssetTypes
- dev-feature/addOutcomeEndpoint
- dev-feature/applyStandardParametersInModel
- dev-feature/workOnFiltering
This package is auto-updated.
Last update: 2024-09-14 22:29:40 UTC
README
PHP 包,用于与 Halo 服务解决方案 接口。我们强烈建议您查看 Halo 的 API 文档,以了解此包的功能,因为我们只是封装了他们的 API。
我们仅使用 Laravel 作为我们的应用程序,因此此包是以 Laravel 为出发点编写的。我们已经尝试使其在 Laravel 之外也能工作。如果社区有请求将此包分成两部分,我们将考虑进行这项工作。
构建状态
目录
安装
通过 Composer 安装 Halo PHP 包
$ composer require spinen/halo-php-client
Laravel 设置
-
您需要让您的
User
对象实现包含Spinen\Halo\Concerns\HasHalo
特性的 trait,这将允许它像这样访问客户端:$user->halo
<?php namespace App; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Spinen\Halo\Concerns\HasHalo; class User extends Authenticatable { use HasHalo, Notifiable; // ... }
-
将适当的值添加到您的
.env
文件中密钥
HALO_RESOURCE_SERVER=<API Resource Server> HALO_TENANT=<Optional Tenant> HALO_AUTHORIZATION_CODE_CLIENT_ID=<Needed if using Authorization Code> HALO_CLIENT_CREDENTIALS_CLIENT_ID=<Needed if using Client Credentials> HALO_CLIENT_CREDENTIALS_CLIENT_SECRET=<Needed if using Client Credentials>
-
[可选] 发布配置和迁移
配置
可以运行以下命令将名为
halo.php
的配置文件发布到config/
目录...php artisan vendor:publish --tag=halo-config
迁移
可以运行以下命令将迁移文件发布...
php artisan vendor:publish --tag=halo-migrations
您需要迁移来在您的
User
模型上设置 Halo API 令牌。
通用 PHP 设置
-
您需要构建一个数组作为配置传递给 Halo 对象。您可以在
configs
目录中查看halo.php
文件。文件中记录了所有属性。 -
根据您的需求,您可以使用 Halo 客户端或 Builder。
要获取客户端凭证的
Spinen\Halo\Api\Client
实例...$ psysh Psy Shell v0.11.14 (PHP 8.2.4 — cli) by Justin Hileman > $configs = [ "oauth" => [ "authorization_server" => "https://some.host.tld/auth", "client_credentials" => [ "id" => "client_id", "secret" => "client_secret", ], ], "resource_server" => "https://some.host.tld/api", ] > $halo = new Spinen\Halo\Api\Client(configs: $configs); = Spinen\Halo\Api\Client {#2744}
$halo
实例将像以下所有示例中的halo
属性一样工作。要获取
Spinen\Halo\Support\Builder
实例...$ psysh Psy Shell v0.11.12 (PHP 8.2.4 — cli) by Justin Hileman New version is available at psysh.org/psysh (current: v0.11.12, latest: v0.11.13) > // Get a $halo instance from above > $builder = (new Spinen\Halo\Support\Builder)->setClient($halo); = Spinen\Halo\Support\Builder {#2757} >
$builder
实例将像以下所有示例中的halo()
方法一样工作。
身份验证
Halo 在进行 API 调用时具有四种身份验证方式。在此包中,我们专注于以下两种:1) 授权代码
或 2) 客户端凭证
。使用授权代码方法可以针对特定用户进行 API 调用。如果您使用 Laravel 与此包交互,则授权流程已经为您构建。如果您不使用 Laravel,请查看 Http\Middleware\Filter
以了解我们如何将用户重定向到 Halo 服务器以请求代码,以及查看 Http\Controllers\HaloController
以了解我们如何将代码转换为令牌。该流程由 PKCE 保护。客户端凭证方法用于作为特定用户进行 API 调用,对于后台进程非常有用。
注意:您可以在同一个项目中使用任何一种方法或两种方法。
授权代码
有一个名为 Halo
的中间件,您可以将它应用到任何需要验证用户是否有 halo_token
的路由上。如果用户没有 halo_token
,则会将用户重定向到包含 client_id
的 Halo OAuth 页面,用户可以选择与您的应用程序关联的团队。选择团队后,用户将被重定向到名为 halo.sso.redirect_uri
的路由,系统将 code
转换为令牌并将其保存到用户处。在保存 halo_token
之后,用户将被重定向到由中间件保护的初始页面。
注意:您需要在路由上设置
auth
中间件,因为需要User
来检查是否存在halo_token
。
注意:目前还没有一种方法可以删除已失效的令牌,因此您需要删除用户上的
halo_token
来重新启动流程。
客户端凭证
当使用 Client Credentials
时,您可以在不需要任何用户界面或用户交互的情况下进行 API 调用。
php artisan tinker Psy Shell v0.11.14 (PHP 8.2.4 — cli) by Justin Hileman > $halo = app(Spinen\Halo\Api\Client::class); = Spinen\Halo\Api\Client {#4013} > $halo->get('tenant') = [ "id" => 0, "key" => "some_key", "hostname" => "some.host.tld", "api_root" => "https://some.host.tld/api", "alias" => "", "linked_instance_id" => 0, "has_linked_instances" => false, "isportal" => false, ]
用法
Spinen\Halo\Api\Client
支持的操作
-
delete(string $path)
- 使用 'DELETE' 作为最后一个参数的request()
方法的快捷方式 -
generateProofKey(int $length = 30)
- 生成 PKCE 需要的密钥 -
get(string $path)
- 使用 'GET' 作为最后一个参数的request()
方法的快捷方式 -
getToken()
- 获取、返回或刷新令牌 -
oauthRequestTokenUsingAuthorizationCode(string $code, string $uri, ?string $verifier = null, ?string $scope = null)
- 将 OAuth 代码转换为用于用户的范围令牌 -
oauthRequestTokenUsingClientCredentials(?string $scope = null)
- 通过客户端凭据请求范围令牌 -
oauthUri($url)
- 构建设置 redirect_url 为$url
的 OAuth 页面的 URI -
post(string $path, array $data)
- 使用 'POST' 作为最后一个参数的request()
方法的快捷方式 -
put(string $path, array $data)
- 使用 'PUT' 作为最后一个参数的request()
方法的快捷方式 -
request(?string $path, ?array $data = [], ?string $method = 'GET')
- 使用 JWT 为已登录用户对$path
进行 API 调用。 -
setConfigs(array $configs)
- 验证并设置配置 -
setDebug(bool $debug)
- 将 Guzzle 设置为调试模式 -
setToken(Token $token)
- 设置 Halo API 的令牌 -
uri(?string $path = null, ?string $url = null)
- 为 Halo API 的路径生成完整 URI。 -
validToken(?string $scope = null)
- 令牌是否有效,如果提供了范围,令牌是否被批准用于该范围
使用客户端
客户端旨在模拟 Laravel 的 Eloquent 模型。当与 Halo 资源一起工作时,您可以像在 Laravel 中一样访问属性和关系。
获取客户端对象
当使用 Authorization Code
时
通过运行此包中包含的迁移,您的 User
类将有一个 halo_token
列。当您设置用户的令牌时,它将使用 Laravel 的加密方法在您的数据库中进行加密。设置 Halo API 令牌后,您可以通过 $user->halo
访问客户端对象。
php artisan tinker Psy Shell v0.11.14 (PHP 8.2.4 — cli) by Justin Hileman > $user = App\Models\User::find(1) = App\Models\User {#4344 id: 1, name: "Jimmy", email: "jimmy.puckett@spinen.com", email_verified_at: null, ... > $user->halo; = Spinen\Halo\Api\Client {#4748} > $user->halo(); = Spinen\Halo\Support\Builder {#4706}
模型
API响应被转换为具有属性的类型,这些类型在Halo API文档中定义。您可以在src/
文件夹中查看这些模型。每个模型上都有一个名为casts
的属性,它指导客户端如何将API响应中的属性转换为相应的类型。如果casts
属性为空,则表示API文档中没有定义这些属性,因此将返回一个数组。
注意:由于Halo处于活跃开发中,模型上的文档属性可能会过时。
> $user->halo()->teams->first() = Spinen\Halo\Team {#4967 +exists: true, +incrementing: false, +parentModel: null, +wasRecentlyCreated: false, +timestamps: false, } > $user->halo()->teams->first()->toArray() = [ "id" => 1, "guid" => "<masked>", "name" => "1st Line Support", "sequence" => 10, "forrequests" => true, "foropps" => false, "forprojects" => false, "ticket_count" => 0, "department_id" => 3, "department_name" => "SPINEN - Support", "inactive" => false, "override_column_id" => 0, "teamphotopath" => "", "use" => "team", ]
关系
一些响应包含相关资源的链接。如果一个属性有关系,您可以通过调用它作为方法来访问它,并且会自动执行额外的调用并返回。值将存储在原始数据的位置,因此一旦加载就会缓存。
您也可以将这些关系称为属性,客户端会为您返回一个Collection
(就像Eloquent一样)。
集合
结果被包装在Spinen\Halo\Support\Collection
中,它扩展了Illuminate\Support\Collection
,因此您可以使用任何文档中记录的集合辅助方法Laravel Collection方法。
使用 "where" 过滤
您可以使用模型上的where
进行筛选。第一个参数是要筛选的属性。第二个参数是可选的,表示要筛选的属性的值。如果它留空,则默认为true,因此它变为where('<property', true)
。所有这些值都通过查询字符串传递。
有几个“辅助”方法是对where
筛选的别名,以使调用更加明确。
whereId('<id>')
是where('id', '<id>')
的别名。whereNot('<property>')
是where('<property', false)
的别名。
注意:Halo的API需要字符串“true”/“false”来表示布尔值,这在构建查询字符串时自动转换。
搜索
您可以使用search
在端点上执行简单的搜索。有些端点允许搜索特定字段,您可以通过search_some_field('<for>')
或searchSomeField('<for>')
访问这些字段。
> $user->halo()->clients->count() = 9 // Only clients with a "y" in the name > $user->halo()->clients()->search('y')->get()->pluck('name') // Same as: $user->halo()->clients()->where('search', 'y')->get()->pluck('name') = Spinen\Halo\Support\Collection {#5136 all: [ "Terry's Chocolates", "Tony's Tyre Emporium", ], }
限制返回的记录
您可以在构建器上调用take
或limit
方法(take
是limit
的别名)来限制返回的记录数到指定的计数参数。
> $builder->tickets()->take(7)->get() = Spinen\Halo\Support\Collection {#4999 all: [ Spinen\Halo\Ticket {#4991 +exists: true, +incrementing: false, +parentModel: null, +wasRecentlyCreated: false, +timestamps: false, }, // more... ], } > $tickets->count() = 7
排序
您可以使用orderBy
和orderByDesc
方法对API的结果进行排序。将您希望排序结果的列作为第一个参数传递。orderByDesc('<column>')
是orderBy('<column>', 'desc')
的别名。此外,您可以使用latest
或oldest
来应用orderBy
或orderByDesc
,默认使用模型中表示创建记录时间的列。您可以将不同的列传递给这两个方法之一以覆盖默认列。
// Running through map to convert date to string > $builder->tickets()->take(5)->oldest()->get()->pluck('dateoccurred', 'id')->map(fn($d) => (string)$d) = Spinen\Halo\Support\Collection {#4983 all: [ 1125 => "2019-12-14 13:30:00", 1128 => "2019-12-14 13:30:00", 1131 => "2019-12-14 13:30:00", 1134 => "2019-12-14 13:30:00", 1137 => "2019-12-14 13:30:00", ], } > $builder->tickets()->take(5)->latest()->get()->pluck('dateoccurred', 'id')->map(fn($d) => (string)$d) = Spinen\Halo\Support\Collection {#4763 all: [ 2205 => "2021-03-24 11:35:40", 2206 => "2021-03-24 10:23:47", 2200 => "2021-03-23 16:44:00", 2186 => "2021-03-23 14:17:57", 2187 => "2021-03-23 14:17:57", ], }
注意:用于
latest
的列由模型上的CREATED_AT
const
控制。
分页
一些端点支持分页。您可以使用简单的分页通过将pagination
或pageination
与一个可选的大小值链接到构建器。您可以使用page
方法获取特定页面,该方法接受页面号作为参数。您可以通过将分页大小作为第二个参数传递给page
方法来压缩调用。
// Could have been $builder->users()->paginate(2)->page(2)->get() > $builder->users()->page(3, 2)->get() = Spinen\Halo\Support\Collection {#4761 all: [ Spinen\Halo\User {#4763 +exists: true, +incrementing: false, +parentModel: null, +wasRecentlyCreated: false, +timestamps: false, }, // more... ], } > $users->count() = 2
更多示例
> $user->halo()->quotes->count() = 4 $user->halo()->statuses->pluck('name', 'id')->sort() = Spinen\Halo\Support\Collection {#4959 all: [ 3 => "Action Required", 18 => "Approved", 17 => "Awaiting Approval", 9 => "Closed", 15 => "Closed Item", 13 => "Closed Order", 20 => "Completed", 2 => "In Progress", 16 => "Invoiced", 1 => "New", 21 => "On Hold", 14 => "Open Item", 12 => "Open Order", 19 => "Rejected", 22 => "Updated", 10 => "With CAB", 5 => "With Supplier", 4 => "With User", ], }
打开项目
- 在模型中设置关系
- 在模型中添加获取器
- 在模型上添加作用域