laravel 容器,支付模块设计
假设我现在需要做一个支付服务,那么我先设计一个接口
interface PayInterface{
public function pay(Order $order) : string;
}
然后实现这个接口
class WeiXinPay implements PayInterface{
protected $appID = "xxxx";
protected $mchID = "xxxx";
protected $mchKey = "xxxx";
public function pay(Order $order) :string{
//具体实现
}
}
然后在PayServiceProvider中注册这个服务
$this->app->bind(PayInterface::class , WeiXinPay::class);
写个单元测试试试
public function testPay(){
$orderSn = Strings::randomString('NUMBER+',12);
$order = factory(Order::class)->make([
'sn' => $orderSn,
'amount' => 1,
'attach' => 1,
]);
/**
* @var $service PayInterface
*/
$service = $this->app->make(PayInterface::class);
$res = $service->pay($order);
$this->assertIsString($res);
}
这里看上去没有问题,一切都如预期一样。
但是很快需求就变了,WeiXinPay的三个属性appID,mchID,mchKey不能写死,需要从外部读取。我便开始改造我的代码。
如何优雅的得到WeiXinPay依赖的三个参数呢? 我想到了再定义一个接口,这样:
interface PaySettingsInterface {
public function getSettings() : array;
}
然后实现他
//从env文件读取
class EnvPaySettings implements PaySettingsInterface{
public function getSettings() : array{
return [
'app_id' => 'xxxx',
'app_secret' => 'yyyyy',
'key' => 'zzzz'
];
}
}
//从数据库读取
class DataBasePaySettings implements PaySettingsInterface{
public function getSettings() : array{
$settings = DB::table('pay_settings')->get();
return $settings;
}
}
修改我的WeiXinPay
class WeiXinPay implements PayInterface{
protected $settings;
public __construct(PaySettingsInterface $settings){
$this->settings = $settings->getSettings();
}
public function pay(Order $order) :string{
//具体实现
}
}
修改PayServiceProvider
//这一行我可以方便的随时修改EnvPaySetting为DataBasePaySettings
$this->app->bind(PaySettingsInterface::class,EnvPaySettings::class);
$this->app->bind(PayInterface::class , WeiXinPay::class);
再跑我的单元测试
public function testPay(){
$orderSn = Strings::randomString('NUMBER+',12);
$order = factory(Order::class)->make([
'sn' => $orderSn,
'amount' => 1,
'attach' => 1,
]);
/**
* @var $service PayInterface
*/
$service = $this->app->make(PayInterface::class);
$res = $service->pay($order);
$this->assertIsString($res);
}
一切还是没变,都如预期一样,我的单元测试代码一行都没有改。
但是,又有新的需求出现了,老板说,支付的时候要每个收款人的mchID,appID,appKey都不一样。
于是我开始改我的代码,第一个思路是再写一个UserPaySettings,说干就干
class User extends Model{
//model 的其它定义
public function settings(){
$settings = //获取settings的代码
return $settings;
}
}
//从用户关联读取
class UserPaySettings implements PaySettingsInterface{
protected $user;
public function __construct(User $user){
$this->user = $user;
}
public function getSettings() : array{
$settings = $this->user->settings();
return $settings;
}
}
好了。我天真的再去修改我的PayServiceProvider,把之前的EnvPaySettings替换成UserPaySettings
$this->app->bind(PaySettingsInterface::class,UserPaySettings::class);
$this->app->bind(PayInterface::class , WeiXinPay::class);
再天真的跑一下我的单元测试,还是一行代码都没改
public function testPay(){
$orderSn = Strings::randomString('NUMBER+',12);
$order = factory(Order::class)->make([
'sn' => $orderSn,
'amount' => 1,
'attach' => 1,
]);
/**
* @var $service PayInterface
*/
$service = $this->app->make(PayInterface::class);
$res = $service->pay($order);
$this->assertIsString($res);
}
然后就报错了。因为UserPaySettings是要注入一个User模型的
怎么办,通过容器貌似已经无法再自动注入了,因为传递进去的User模型是变化的。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)