契约篇
大约 4 分钟
契约篇
提示
laravel-fast-api-youhujun底座提炼封装了契约层,用于实现通用基础功能和自由业务特殊业务逻辑的解耦
下面通过示例来说明如何处理使用
注册用户示例
提示
再次建议,如下面示例,针对该契约,业务内部传递参数使用AddUserHandlerContractDTO,避免使用数组传递参数,
这样数据结构更清晰,便于维护
/**
* 注册用户
*
* @param [array] $param 传递的参数
* @param [User] $userObject 可选参数用户对象,可以从外部注册用户,然后传递过来,如果不传递,就在这里注册用户
* @return [User] $userObject 返回注册成功的用户对象
*/
public function registerUser(BusinessRegisterUserDTO $businessDTO, ?User $userObject = null): User
{
//执行注册
DB::beginTransaction();
//如果没有从外面传入用户,就最简注册
if (!isset($userObject) || empty($userObject)) {
$user_uid = get_snow_flake_id();
$userLevelObject = UserLevel::where('level_code','V0')->get()->first();
$insertDataArray = [
'user_uid' => $user_uid,
'phone' => isset($paramArray['phone']) ? $paramArray['phone'] : null,
'password' => isset($paramArray['password']) ? Hash::make($paramArray['password']) : null,
'level_id' => $userLevelObject->id,
'real_auth_status' => 10,
'account_status' => 1,
'account_name' => \bin2hex(\random_bytes(4)),
'auth_token' => Str::uuid()->toString(),
'source' => isset($paramArray['source']) ? $paramArray['source'] : 0
];
$userObject = ShardHelperFacade::createWithShard(User::class, $user_uid, $insertDataArray);
if (!isset($userObject->biz_id)) {
DB::rollBack();
throw new CommonException('AddUserError');
}
}
CommonUserRegisterEvent::dispatch($businessDTO,$userObject);
//契约参数处理
$businessContractDTO = new AddUserHandlerContractDTO();
$businessContractDTO->userObject = $userObject;
$businessContractDTO->source_user_uid = isset($businessDTO->source_user_uid) ? $businessDTO->source_user_uid : 0;
$businessContractDTO->invite_id = isset($businessDTO->invite_id) ? $businessDTO->invite_id : 0;
$businessContractDTO->invite_code = isset($businessDTO->invite_code) ? $businessDTO->invite_code : '';
app(AddUserHandlerContract::class)->handle($businessContractDTO);
//提交
DB::commit();
return $userObject;
}契约层
从下面示例中可以看出,一个是通用业务逻辑aseAddUserHandlerContractService,一个是业务内部的业务逻辑YouHuAddUserHandlerContractService
<?php
/*
* @Descripttion:
* @version: v1
* @Author: youhujun youhu8888@163.com
* @Date: 2026-01-10 22:16:21
* @LastEditors: youhujun youhu8888@163.com & xueer
* @LastEditTime: 2026-05-23 15:42:33
* @FilePath: \youhu-laravel-api-12\app\Contracts\LaravelFastApi\V1\Common\User\AddUserHandlerContract.php
* Copyright (C) 2026 youhujun. All rights reserved.
*/
namespace App\Contracts\LaravelFastApi\V1\Common\User;
use App\DTOs\Contracts\V1\User\User\AddUserHandlerContractDTO;
/**
* @see \App\Services\Contract\LaravelFastApi\V1\Common\User\BaseAddUserHandlerContractService
* @see \App\Services\Contract\YouHu\V1\Common\User\YouHuAddUserHandlerContractService
*/
interface AddUserHandlerContract
{
/**
*
* @param $handleParamArray
*/
public function handle(AddUserHandlerContractDTO $businessContractDTO): void;
}底层实现
通过封装的助手函数
<?php
/*
* @Descripttion:
* @version: v1
* @Author: youhujun youhu8888@163.com
* @Date: 2026-01-03 14:27:54
* @LastEditors: youhujun youhu8888@163.com
* @LastEditTime: 2026-01-03 15:24:01
* @FilePath: src\config\container_helper.php
* Copyright (C) 2026 youhujun. All rights reserved.
*/
use Illuminate\Contracts\Foundation\Application;
if (!function_exists('resolve_with_validation')) {
/**
* 从容器中解析一个类,并验证它是否实现了指定的接口。
*
* @param Application $app The Laravel application instance.
* @param string|null $concrete The concrete class to resolve. If null, the default will be used.
* @param string $interface The interface that the resolved class must implement.
* @param string|null $default The default concrete class to use if $concrete is null or invalid.
* @return mixed The resolved and validated instance.
*
* @throws \InvalidArgumentException If the resolved class does not implement the interface.
*/
function resolve_with_validation(Application $app, ?string $concrete, string $interface, ?string $default = null)
{
// 1. 如果没有提供具体实现,或者提供的实现不存在,则使用默认实现
if (empty($concrete) || !class_exists($concrete)) {
// 如果连默认实现都没有,则无法继续,抛出异常
if (empty($default) || !class_exists($default)) {
throw new \InvalidArgumentException("No valid concrete class provided for interface [{$interface}].");
}
return $app->make($default);
}
// 2. 从容器中解析实例
$instance = $app->make($concrete);
// 3. 验证实例是否实现了指定的接口
if (!$instance instanceof $interface) {
throw new \InvalidArgumentException(
"Class [{$concrete}] does not implement the required interface [{$interface}]."
);
}
// 4. 验证通过,返回实例
return $instance;
}
}配置
提示
这是自定义配置文件,发布组件包以后自然而然就可以看到
config\custom\common\contract\common_contract.php
<?php
/*
* @Description:
* @version: v1
* @Author: youhujun youhu8888@163.com & xueer
* @Date: 2026-04-09 15:51:53
* @LastEditors: youhujun youhu8888@163.com & xueer
* @LastEditTime: 2026-04-09 15:54:53
* @FilePath: \youhu-laravel-api-12\config\custom\common\contract\common_contract.php
* Copyright (C) 2026 youhujun & xueer . All rights reserved.
*/
return [
'youhu'=>[
'add_user_handler' => \App\Services\Contract\YouHu\V1\Common\User\YouHuAddUserHandlerContractService::class,
],
];服务提供者中
public function register()
{
//用户注册
$this->bindContract(
\App\Contracts\LaravelFastApi\V1\Common\User\AddUserHandlerContract::class,
'youhu.add_user_handler',
\App\Services\Contract\LaravelFastApi\V1\Common\User\BaseAddUserHandlerContractService::class
);
}
private function bindContract(string $interface, string $configKey, string $defaultImpl)
{
$this->app->bind($interface, function ($app) use ($interface, $configKey, $defaultImpl) {
return resolve_with_validation(
$app,
config("common_contract.{$configKey}"),
$interface,
$defaultImpl
);
});
}通过上面的示例可以看出,bindContract方法传递了三个参数,分别是$interface,$configKey,$defaultImpl
总结
laravel-fast-api-youhujun 的契约层设计,是基于Laravel的服务提供者和容器,通过resolve_with_validation方法,来实现的,提供了灵活的契约绑定和解耦方案。
提示
游鹄生态倡导组件化可插拔的开发方案,所以在业务层面,我们也提供了契约层的封装,方便业务层面进行扩展和自定义,具体使用请参考代码
1定义基础实现服务层和自有特殊业务服务层
例如:
\App\Contracts\LaravelFastApi\V1\Common\User\AddUserHandlerContract::class,
\App\Services\Contract\LaravelFastApi\V1\Common\User\BaseAddUserHandlerContractService::class2配置文件common_contract添加$configKey
例如:
'youhu'=>[
'add_user_handler' => \App\Services\Contract\YouHu\V1\Common\User\YouHuAddUserHandlerContractService::class,
],3在服务提供者中注册契约
$this->bindContract(
\App\Contracts\LaravelFastApi\V1\Common\User\AddUserHandlerContract::class,
'youhu.add_user_handler',
\App\Services\Contract\LaravelFastApi\V1\Common\User\BaseAddUserHandlerContractService::class
);