我先举一个例子。
铸模类
<?php
class Mold {
public $current;
function merge($first, $second) {
$this->current = $first . $second;
return $this;
}
function phone() {
$this->current = '<a href="tel:' . $this->current . '">' . $this->current . '</a>';
return $this;
}
function __toString() {
return $this->current;
}
}
function mold() {
return new Mold();
}
实际行动
这按预期工作。
echo mold()->merge('sada', 'asdsa')->phone();
我有一个或多个类,它们的方法也希望可以使用。
插件类
class MyPlugin {
function link() {
// Code
}
function currency($number) {
// Code
}
}
class MyPlugin2 {
// Other methods
}
梦想代码
以下事件的确切更改可能没有任何意义。无论如何,我打算做的是以下事情。
echo mold()->merge('sada', 'asdsa')->currency(45)-link();
mold()
会创建Mold
类的新实例。merge()
类中使用的链Mold
。currency()
或link()
方法在Mold
类中不存在。相反,应该从其中一个插件中加载它们。Mold
类需要以某种方式知道它们。答案 0 :(得分:1)
从技术上讲,您可以使用__call()
。您的“主要”类可以包含/跟踪一组插件实例,并且可以查找和委托任何未知的方法调用(如果在插件中可用)。
我不会推荐这个。流利的API通常很脆弱,即使使用 one 类也可能会带来不便。使多个类参与流利的调用可能很快就会造成混乱。混乱,甚至IDE也无法帮助您(或其他使用代码的人),因为它无法掌握所有发生的魔术。
我强烈建议您研究此类API的替代模式。
答案 1 :(得分:0)
您可能会尝试应用的概念是Composition Over Inheritance。
一种解决方案可能是组成当前的Mold
对象并传递两个插件实例,以便它可以在其方法上使用它们,例如:
<?php
class Mold {
public $current;
public function __construct(Plugin1 $plugin1, Plugin2 $plugin2) {
$this->plugin1 = $plugin1;
$this->plugin2 = $plugin2;
}
public function merge($first, $second) {
$this->current = $first . $second;
return $this;
}
public function phone() {
$this->current = '<a href="tel:' . $this->current . '">' . $this->current . '</a>';
return $this;
}
public function __toString() {
return $this->current;
}
public function link() {
$this->plugin1->link();
return $this;
}
}
function mold() {
return new Mold(new Plugin1(), new Plugin2());
}
另一种解决方案是创建一个MoldHandler
类,该类具有一个Mold
对象作为属性以及其他插件,可以直接在其中使用。
public class MoldHanlder {
protected $mold;
protected $plugin1;
protected $plugin2;
public function __contruct($mold, $plugin1, $plugin2) {
$this->mold = $mold;
$this->plugin1 = $plugin1;
$this->plugin2 = $plugin2;
}
public function merge() {
$this->mold = $this->mold->merge();
return $this;
}
public function link() {
$foo = $this->plugin1->method();
return $this;
}
...
}
您也可以只实例化construct
内部的类,但是如果您打算编写单元测试,则依赖注入是解决之道
我认为第一种方法更好,因为您避免自己重写Mold类的一些代码,这是不必要的
这是一个非常原始的解决方案,只是为了让您更好地理解我会选择的想法 欢呼
答案 2 :(得分:-1)
有趣的想法。
解决我所想到的问题的一种方法是使用traits,例如评论中建议的@ vivek_23。
以下是其工作原理的完整示例
<?php
// Core methods
class MoldCore {
public $current;
function merge($first, $second) {
$this->current = $first . $second;
return $this;
}
function phone() {
$this->current = '<a href="tel:' . $this->current . '">' . $this->current . '</a>';
return $this;
}
function __toString() {
return $this->current;
}
}
// Plugin 1
trait Plugin1 {
public function yaay() {
$this->current .= ' Plugin1 yaay';
return $this;
}
}
// Plugin 2
trait Plugin2 {
public function hello() {
$this->current = str_replace('Plugin1', 'Modified', $this->current);
return $this;
}
public function world() {
$this->current .= ' Plugin2 world';
return $this;
}
}
// Glue plugins with MoldCore
class Mold extends MoldCore {
use Plugin1, Plugin2;
}
$mold = new Mold();
echo $mold->merge('sada', 'asdsa')->phone()->yaay()->hello();