通过类链接全局 PHP 函数

发布于 2024-11-06 11:01:36 字数 345 浏览 0 评论 0原文

是否可以通过一个对象/类链接所有 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

谢谢。

Is it possible to chain all PHP functions through an object/class?

I have this on my mind and I imagine it something like this:

$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 */);

this should produce:

Backoverflow

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

百合的盛世恋 2024-11-13 11:01:36

看一下:

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

Have a look at:

http://php.net/manual/en/language.oop5.magic.php

especially:

http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods

and propably:

http://php.net/manual/en/function.call-user-func-array.php

As so many posted their examples, I'll try too:

<?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
时光暖心i 2024-11-13 11:01:36

您的意思是 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

请注意,您永远不会从链中返回 /* 第一个函数参数的值 */ 的值,因为这是没有意义的。也许你可以用一个全局变量来做到这一点,但这将是非常可怕的。

关键是,您可以通过每次返回 $this 来链接方法。对返回值调用 next 方法,该值是同一个对象,因为您返回了它(返回 $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();
}

Do you mean to do str_replace('St', 'B', ucwords(strtolower('StackOverFlow'))) ?

The methods you are calling above are functions, not methods tied to any class. Chainer would have to implement these methods. If this is what you want to do (perhaps for a different purpose and this is just an example) your implementation of Chainer might look like this:

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;
   }
}

This would work in your above example somewhat, but you would call it like this:

$c = new Chainer;
echo $c->strtolower('StackOverFlow')
   ->ucwords()
   ->str_replace('St', 'B')
; //Backoverflow

Note that you never get the value of /* the value from the first function argument */ back out from the chain as this wouldn't make sense. Maybe you could do it with a global variable, but that would be quite hideous.

The point is, you can chain methods by returning $this each time. The next method is called on the returned value which is the same object because you returned it (returned $this). It is important to know which methods start and stop the chain.

I think that this implementation makes the most sense:

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();
}
最初的梦 2024-11-13 11:01:36

你可以这样做,只要 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 方法,但是处理存储的变量和可选方法参数将是一个很大的痛苦。

You can do this provided the Chainer class looks something like

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;
    }
}

Looks pretty silly to me though.

You might be able to incorporate a magic __call method but it's going to be a major pain to deal with the stored variable and optional method arguments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文