@fecommerce [[#5楼](#comment5)](#comment5)
我只是不赞成 间接实现B依赖A
这个说法哈,因为 B 只依赖于接口,实例化 B 的时候和 A 没有任何关系。
class A
{
public function foo(){
$b = new B();
$b->bar();
}
}
class B
{
public function bar(){
}
}
这是 A 依赖于 B 的情况。
interface IB
{
public function bar();
}
class B implements IB
{
public function bar() {}
}
class A
{
private $b;
public function __construct(IB $b)
{
$this->b = $b;
}
public function foo(){
$this->b->bar();
}
}
定义一个接口 IB
,然后通过构造方法把依赖注入进去。
就变成了的 A 依赖于接口 IB
,在实例化 A 的时候,需要传入接口 IB
的实现,这里可以说 A 间接依赖于 B
。
$a = new A(new B());
但是 B 只依赖于接口 IB
,是接口的一个实现,和 A 没有关系,并没有 间接实现B依赖A
。
$b = new B();
我翻了下文档…… 发现楼主这个确实是 Yii 的事件的正确使用姿势…… 好尴尬啊…… 没看文档没看源码就直接回答了…… 只是看起来有点像装饰器模式…… 怎么办…… 好尴尬……
http://www.yiiframework.com/doc-2.0/yii-db-baseactiverecord.html#beforeSave()-detail
这里的 beforeSave
和 afterSave
其实就是触发的 EVENT_BEFORE_INSERT
和 EVENT_AFTER_INSERT
事件。
@xjdata [[#11楼](#comment11)](#comment11) yii2 的 ActiveRecord 已经提前预制好了 ⑨ 个事件,如下:
http://www.yiiframework.com/doc-2.0/yii-db-baseactiverecord.html#EVENT_AFTER_DELETE-detail
你只需要添加对应的处理就可以了:
http://www.getyii.com/doc-2.0/guide/concept-events.html#
看这个文档的 类级别的事件处理器
部分,那个例子应该就是你想要的了……
仔细想了下,你的问题其实是跨域问题吧……
看这个,第二段:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
注意:有些浏览器不允许从HTTPS的域跨域访问HTTP,比如Chrome和Firefox,这些浏览器在请求还未发出的时候就会拦截请求,这是一个特例。)
所以你这个问题,看看对方的 api 支不支持 https 协议,不行的话只能放弃全站 https 了。
还有个可行的方法是在服务端发起对第三方 api 的请求,这样就不会受浏览器的限制了……
有点问题…… 反转A和B的依赖关系,让A依赖B反转为B依赖A
,那 B 依赖于 A 又怎么解决……
看这个 https://codingstyle.cn/topics/192:
依赖倒置原则则强调:为了让依赖关系是稳定的,不应该由实现侧根据自己的技术实现方式定义接口,然后强迫上层(即客户)依赖这种不稳定的API定义,而是应该站在上层(即客户)的角度去定义API(正所谓依赖倒置)。
但是,虽然接口由上层定义,但最终接口的实现却依然由下层完成,因此依赖倒置描述为:上层不依赖下层,下层也不依赖上层,双方共同依赖于抽象。
还有这里 http://my.oschina.net/zgldh/blog/389243#OSC_h1_1 ,Laravel 框架的作者写的:
最后的原则是依赖反转原则,它规定高等级的代码不应该依赖低等级的代码。首先,高等级的代码应该依赖着抽象层,抽象层就像是“中间人”一样,负责连接着高等级和低等级的代码。其次,抽象定义不应该依赖着具体实现,但具体实现应该依赖着抽象定义。
<?php
abstract class Model
{
private $event;
public function __construct(Event $event)
{
$this->event = $event;
}
public function save()
{
$this->event->notify('saving', $this);
}
}
class User extends Model
{
}
class Blog extends Model
{
}
class Event
{
private $events;
public function addObserver($name, IObserver $observer){
$this->events[$name][] = $observer;
}
public function notify($name, $model){
echo get_class($model) . PHP_EOL;
foreach ($this->events[$name] as $observer) {
$observer->doSomething($model);
}
}
}
interface IObserver{
public function doSomething(Model $model);
}
class LogObserver implements IObserver{
public function doSomething(Model $model){
echo 'Log...' . PHP_EOL;
}
}
class CacheObserver implements IObserver{
public function doSomething(Model $model){
echo 'Cache...' . PHP_EOL;
}
}
$event = new Event();
$event->addObserver('saving', new LogObserver());
$event->addObserver('saving', new CacheObserver());
$user = new User($event);
$user->save();
$blog = new Blog($event);
$blog->save();
执行结果:
User
Log...
Cache...
Blog
Log...
Cache...
@xjdata [#8楼](#comment8) 这是可以满足那段描述的一个实现。
别看那么长…… 其实就是 Model
里的 save()
方法触发 saving
事件,然后 Event
里依次通知(执行)注册(添加)好的观察者LogObserver
和 CacheObserver
。
这个应该是装饰器模式,作用是可以动态的添加和修改功能(其实只是看起来比较像装饰器模式,无视无视……)
事件的话,也就是观察者模式,触发一个事件后通知所有观察这个事件的观察者,观察者可以是多个。比如当保存一个 Model 的时候,触发 saving 事件,这个时候就可以编写一个保存日志和一个更新缓存的观察者,以后只要保存 Model ,就可以把日志记录下来,同时更新缓存