是否可以通过对象/类链接所有PHP函数?
我有这个想法,我想像这样:
$c = new Chainer();
$c->strtolower('StackOverFlow')->ucwords(/* the value from the first function argument */)->str_replace('St', 'B', /* the value from the first function argument */);
这应该产生:
Backoverflow
感谢。
答案 0 :(得分:6)
看看:
http://php.net/manual/en/language.oop5.magic.php
特别:
http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods
并且可以说:
http://php.net/manual/en/function.call-user-func-array.php
许多人发布了他们的例子,我也会尝试:
<?php
class Chainer
{
protected $buffer = null;
public function __call($name, $args) {
if (method_exists($this, $name)) {
$this->buffer = call_user_func_array(array($this, $name), $args);
}
elseif (function_exists($name)) {
if ($this->buffer !== null) {
$args[] = $this->buffer;
}
$this->buffer = call_user_func_array($name, $args);
}
return $this;
}
public function strpos($needle, $offset = 0) {
return strpos($this->buffer, $needle, $offset);
}
public function __toString() {
return (string)$this->buffer;
}
}
$c = new Chainer();
echo $c->strtolower('StackOverFlow')->ucwords()->str_replace('St', 'B')->strpos('overflow'); // output: 4
答案 1 :(得分:4)
你的意思是str_replace('St', 'B', ucwords(strtolower('StackOverFlow')))
吗?
上面调用的方法是函数,而不是绑定到任何类的方法。 Chainer
必须实施这些方法。如果这是你想要做的(也许是为了一个不同的目的,这只是一个例子)你的Chainer
的实现可能如下所示:
class Chainer {
private $string;
public function strtolower($string) {
$this->string = strtolower($string);
return $this;
}
public function ucwords() {
$this->string = ucwords($this->string);
return $this;
}
public function str_replace($from, $to) {
$this->string = str_replace($from, $to, $this->string);
return $this;
}
public function __toString() {
return $this->string;
}
}
这在上面的示例中会有所作为,但您可以这样称呼它:
$c = new Chainer;
echo $c->strtolower('StackOverFlow')
->ucwords()
->str_replace('St', 'B')
; //Backoverflow
请注意,您永远不会从链中退出/* the value from the first function argument */
的值,因为这没有意义。也许你可以用一个全局变量来做,但那将是非常可怕的。
关键是,您可以通过每次返回$this
来链接方法。在返回的值上调用下一个方法,因为您返回了该返回值(返回$this
)。重要的是要知道哪些方法开始和停止链。
我认为这种实现最有意义:
class Chainer {
private $string;
public function __construct($string = '') {
$this->string = $string;
if (!strlen($string)) {
throw new Chainer_empty_string_exception;
}
}
public function strtolower() {
$this->string = strtolower($this->string);
return $this;
}
public function ucwords() {
$this->string = ucwords($this->string);
return $this;
}
public function str_replace($from, $to) {
$this->string = str_replace($from, $to, $this->string);
return $this;
}
public function __toString() {
return $this->string;
}
}
class Chainer_empty_string_exception extends Exception {
public function __construct() {
parent::__construct("Cannot create chainer with an empty string");
}
}
try {
$c = new Chainer;
echo $c->strtolower('StackOverFlow')
->ucwords()
->str_replace('St', 'B')
; //Backoverflow
}
catch (Chainer_empty_string_exception $cese) {
echo $cese->getMessage();
}
答案 2 :(得分:2)
如果Chainer
类看起来像
class Chainer
{
private $string;
public function __construct($string = null)
{
$this->setString($string);
}
public function setString($string)
{
$this->string = $string;
return $this;
}
public function __toString()
{
return $this->string;
}
public function strtolower($string = null)
{
if (null !== $string) {
$this->setString($string);
}
$this->string = strtolower($this->string);
return $this;
}
public function ucwords($string = null)
{
if (null !== $string) {
$this->setString($string);
}
$this->string = ucwords($this->string);
return $this;
}
public function str_replace($search, $replace, $string = null)
{
if (null !== $string) {
$this->string = $string;
}
$this->string = str_replace($search, $replace, $this->string);
return $this;
}
}
虽然看起来很傻。
您可能可以使用魔术__call
方法,但处理存储的变量和可选方法参数将是一个很大的痛苦。