PHP 链式 class 方法与其他 class 方法合并
PHP chained class methods merged with other classes
我先举个例子。
模具class
<?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 方法也希望可用。
插件class
class MyPlugin {
function link() {
// Code
}
function currency($number) {
// Code
}
}
class MyPlugin2 {
// Other methods
}
梦想密码
以下事件的确切变化可能没有任何意义。无论如何,我打算做的是以下。
echo mold()->merge('sada', 'asdsa')->currency(45)-link();
- 调用
mold()
创建 Mold
class. 的新实例
- 从
Mold
class. 使用的链merge()
currency()
或 link()
方法在 Mold
class 中不存在。相反,它们应该从插件之一加载。
总结
- 我知道我可以扩展 class 但它并不能真正解决问题,因为可以有多个插件 classes.
- 我知道我可以创建插件 classes 的实例,但它们需要以某种方式被
Mold
class. 知道
- 将方法追加到 class 想到以及合并 classes。
您可能会尝试应用的一个概念是 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
class,它有一个 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
中实例化 classes,但是如果您打算编写单元测试,依赖注入是可行的方法
我认为第一种方法更好,因为您可以避免自己重新编写一些模具代码 class,这是不必要的
N.B。这是一个非常原始的解决方案,只是为了让您更好地理解我会选择的想法
干杯
从技术上讲,您可以为此使用 __call()
。您的 "main" class 可以 contain/track 一组插件实例,并且可以查找和委托任何未知的方法调用(如果在插件中可用)。
虽然我不推荐这个。流利的 APIs 通常很脆弱,即使使用 one class 也会变得不方便。在流畅的调用中涉及多个 classes 可能很快就会造成混乱。一团糟甚至 IDE 都无法帮助您(或其他使用代码的人),因为它对发生的所有魔法一无所知。
我强烈建议研究像这样的 API 的替代模式。
有趣的想法。
像我想的那样解决问题的方法是使用 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();
我先举个例子。
模具class
<?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 方法也希望可用。
插件class
class MyPlugin {
function link() {
// Code
}
function currency($number) {
// Code
}
}
class MyPlugin2 {
// Other methods
}
梦想密码
以下事件的确切变化可能没有任何意义。无论如何,我打算做的是以下。
echo mold()->merge('sada', 'asdsa')->currency(45)-link();
- 调用
mold()
创建Mold
class. 的新实例
- 从
Mold
class. 使用的链 currency()
或link()
方法在Mold
class 中不存在。相反,它们应该从插件之一加载。
merge()
总结
- 我知道我可以扩展 class 但它并不能真正解决问题,因为可以有多个插件 classes.
- 我知道我可以创建插件 classes 的实例,但它们需要以某种方式被
Mold
class. 知道
- 将方法追加到 class 想到以及合并 classes。
您可能会尝试应用的一个概念是 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
class,它有一个 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
中实例化 classes,但是如果您打算编写单元测试,依赖注入是可行的方法
我认为第一种方法更好,因为您可以避免自己重新编写一些模具代码 class,这是不必要的
N.B。这是一个非常原始的解决方案,只是为了让您更好地理解我会选择的想法 干杯
从技术上讲,您可以为此使用 __call()
。您的 "main" class 可以 contain/track 一组插件实例,并且可以查找和委托任何未知的方法调用(如果在插件中可用)。
虽然我不推荐这个。流利的 APIs 通常很脆弱,即使使用 one class 也会变得不方便。在流畅的调用中涉及多个 classes 可能很快就会造成混乱。一团糟甚至 IDE 都无法帮助您(或其他使用代码的人),因为它对发生的所有魔法一无所知。
我强烈建议研究像这样的 API 的替代模式。
有趣的想法。
像我想的那样解决问题的方法是使用 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();