2011-05-11 36 views
3

是否有可能通過對象/類鏈接所有PHP函數?通過鏈接鏈接全局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

你所說的「所有的PHP函數」是什麼意思?所有內置的PHP函數,例如字符串,數組,mysql函數?我認爲這是不可能的,因爲每個函數都應該返回一個對象。 –

+0

通過'$ c-> strtolower(ucwords(str_replace('St','B','StackOverFlow'))''做這個優點會是什麼?可讀性? – Lawyerson

回答

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(); 
} 
+0

看起來很熟悉;-) – Phil

+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

和propably:

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 
+0

是的!這是我真正需要的。從來沒有完全理解這些魔術功能。 – metaforce

+0

非常感謝Yoshi! – metaforce

+0

這將打破第一個不接受主題參數的函數作爲最後一個參數 – Phil

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方法,但是處理存儲的變量和可選的方法參數將是一個很大的麻煩。

+0

__call幫助了我很多!這就是我所需要的;)非常感謝 – metaforce

+0

@metadata Pfft,爲什麼[alot](http://hyperboleandahalf.blogspot.com/2010/04/alot-is-better-than-you-at-everything.html)獲得所有的讚譽? – Phil