大家都是怎么设计项目中的传参的?
以前项目中传参基本上如果只有一个参数则直接传,如果多个的话就合并成数组
public function user(int $id)
public function users(array $params)
数组的问题是可读性太差了,接收的方法内部可能还需要做一些判断, 后面进行优化,使用了laravel-data 扩展,将验证参数转换成Data对象
<?php
namespace App\Data\User;
use Spatie\LaravelData\Data;
class UserUpdateData extends Data
{
public function __construct(
public ?string $nickname,
public ?string $birthday,
public ?int $city_id,
public ?int $height,
public ?int $weight,
public ?int $profession_id,
public ?int $gender
) {
}
}
public function update(int $userId, UserUpdateData $data)
传对象肯定是比传array的可维护性更好,但是这里有几个纠结的点
根据接口参数定义Data类,同一个controller定义一个Data还是每个接口都定义一个Data呢?
controller 将Data传递到service层,Service层经过处理再传递到Model层,传递的参数可能会发生变化,比如增加其他的字段,service到model层重新创建Data? 这样感觉创建的文件有点多,还会有一定的冗余。
实际项目的传参怎么设计欢迎各位大佬指教交流~
本作品采用《CC 协议》,转载必须注明作者和本文链接
这就好比Request,有的人就喜欢封装,写多了基本一个接口定义一套,我是觉得很麻烦 :joy:我们之前传params的情况会在注释里把params的字段都列出来,方便后面人维护调用。现在的情况是代码没人review自己定义,我是参数少的,多参数接收传递,加个默认值然后empty判断,参数多的写params,用的时候判断下,必备不存在的还是优先返回,能跑就行
为此我设计了一个灵活的 DTO ,完全借鉴了 Laravel 的 Attribute
我用 Request/JsonRequest, 在开头获取所有会用到的数据
感觉想太多了,一般情况下
Request
文件里面就已经包含了所有参数那么多参数,那么可能要做优化了。
现在升级到 PHP 8 之后,完全可以使用命名参数
一般接口控制器层面,每个 action 都会有对应的 Request 类吧,如果是这种开发方式,可以将 Request 类和 DTO通过反射结合起来就好了,字段名称只需要定义一次,Service 里面使用 DTO
DTO
Request
通过上面的 DTO 反射生成 Request 类
Controller
Service
听大家推荐过但目前还没用这个包。PHP 的关联数组无法进行元组类型约束那样的效果,肯定还是传对象进行约束更好,也便于一些框架进行编排或进行静态分析。
我的习惯是不太关注文件的多少,当发现重复代码,可以通过 Trait 或 继承 抽象化来实现 DRY (Dont Repeat Yourself)。
可以只在在 service 层面 做 入参控制
在 controller 层 用 request 来控制 入参
controller 只负责对请求参数的一些简单组装操作,业务的参数在 DTO 或者 service 内校验
要求语义化,扩展性好,可读性高,这必须OOP,每个方法定义个独立的参数类,自己封装下好了。