PHP方法链接?

PHP方法链接?,php,oop,method-chaining,Php,Oop,Method Chaining,我正在使用PHP5,我听说了面向对象方法中的一个新特性,叫做“方法链接”。到底是什么?我该如何实现它呢?它非常简单,真的。您有一系列返回原始(或其他)对象的操作。这样,您就可以继续对返回的对象调用方法 <?php class fakeString { private $str; function __construct() { $this->str = ""; } function addA()

我正在使用PHP5,我听说了面向对象方法中的一个新特性,叫做“方法链接”。到底是什么?我该如何实现它呢?

它非常简单,真的。您有一系列返回原始(或其他)对象的操作。这样,您就可以继续对返回的对象调用方法

<?php
class fakeString
{
    private $str;
    function __construct()
    {
        $this->str = "";
    }
    
    function addA()
    {
        $this->str .= "a";
        return $this;
    }
    
    function addB()
    {
        $this->str .= "b";
        return $this;
    }
    
    function getStr()
    {
        return $this->str;
    }
}


$a = new fakeString();


echo $a->addA()->addB()->getStr();

方法链接意味着您可以链接方法调用:

$object->method1()->method2()->method3()
这意味着method1()需要返回一个对象,method2()得到method1()的结果。Method2()然后将返回值传递给method3()


好文章:

基本上,你拿一个物体:

$obj = new ObjectWithChainableMethods();
调用有效执行
返回$this的方法结尾处:

$obj->doSomething();
由于它返回相同的对象,或者更确切地说,是对相同对象的引用,因此可以继续从返回值中调用相同类的方法,如下所示:

$obj->doSomething()->doSomethingElse();
就这样,真的。两件重要的事情:

  • 正如您所注意到的,它只是PHP5。它在PHP4中无法正常工作,因为它按值返回对象,这意味着您在对象的不同副本上调用方法,这会破坏您的代码

  • 同样,您需要在可链接方法中返回对象:

    public function doSomething() {
        // Do stuff
        return $this;
    }
    
    public function doSomethingElse() {
        // Do more stuff
        return $this;
    }
    

  • 有49行代码允许您在数组上链接方法,如下所示:

    $fruits = new Arr(array("lemon", "orange", "banana", "apple"));
    $fruits->change_key_case(CASE_UPPER)->filter()->walk(function($value,$key) {
         echo $key.': '.$value."\r\n";
    });
    
    请参阅本文,它向您展示了如何链接所有PHP的七十个数组函数

    请尝试以下代码:

    <?php
    class DBManager
    {
        private $selectables = array();
        private $table;
        private $whereClause;
        private $limit;
    
        public function select() {
            $this->selectables = func_get_args();
            return $this;
        }
    
        public function from($table) {
            $this->table = $table;
            return $this;
        }
    
        public function where($where) {
            $this->whereClause = $where;
            return $this;
        }
    
        public function limit($limit) {
            $this->limit = $limit;
            return $this;
        }
    
        public function result() {
            $query[] = "SELECT";
            // if the selectables array is empty, select all
            if (empty($this->selectables)) {
                $query[] = "*";  
            }
            // else select according to selectables
            else {
                $query[] = join(', ', $this->selectables);
            }
    
            $query[] = "FROM";
            $query[] = $this->table;
    
            if (!empty($this->whereClause)) {
                $query[] = "WHERE";
                $query[] = $this->whereClause;
            }
    
            if (!empty($this->limit)) {
                $query[] = "LIMIT";
                $query[] = $this->limit;
            }
    
            return join(' ', $query);
        }
    }
    
    // Now to use the class and see how METHOD CHAINING works
    // let us instantiate the class DBManager
    $testOne = new DBManager();
    $testOne->select()->from('users');
    echo $testOne->result();
    // OR
    echo $testOne->select()->from('users')->result();
    // both displays: 'SELECT * FROM users'
    
    $testTwo = new DBManager();
    $testTwo->select()->from('posts')->where('id > 200')->limit(10);
    echo $testTwo->result();
    // this displays: 'SELECT * FROM posts WHERE id > 200 LIMIT 10'
    
    $testThree = new DBManager();
    $testThree->select(
        'firstname',
        'email',
        'country',
        'city'
    )->from('users')->where('id = 2399');
    echo $testThree->result();
    // this will display:
    // 'SELECT firstname, email, country, city FROM users WHERE id = 2399'
    
    ?>
    

    下面是我的模型,可以在数据库中按ID查找。with($data)方法是关系的附加参数,因此我返回$this,它是对象本身。在我的控制器上,我可以链接它

    class JobModel implements JobInterface{
    
            protected $job;
    
            public function __construct(Model $job){
                $this->job = $job;
            }
    
            public function find($id){
                return $this->job->find($id);
            }
    
            public function with($data=[]){
                $this->job = $this->job->with($params);
                return $this;
            }
    }
    
    class JobController{
        protected $job;
    
        public function __construct(JobModel $job){
            $this->job = $job;
        }
    
        public function index(){
            // chaining must be in order
            $this->job->with(['data'])->find(1);
        }
    }
    
    静态方法链接的另一种方式: 使命感
    echo-Maker::words(['foo','bob','bar'])->concate('-')->get();
    回声“
    ”; echo Maker::words(['foo','bob','bar'])->concate('>')->get();
    如果您指的是JavaScript中的方法链接(或者有些人会记住jQuery),为什么不使用一个库来提供PHP中的开发经验呢?例如,Extras-这一个使用JavaScript和下划线方法扩展PHP类型,并提供链接:

    您可以链接特定类型:

    <?php
    use \Dsheiko\Extras\Arrays;
    // Chain of calls
    $res = Arrays::chain([1, 2, 3])
        ->map(function($num){ return $num + 1; })
        ->filter(function($num){ return $num > 1; })
        ->reduce(function($carry, $num){ return $carry + $num; }, 0)
        ->value();
    

    我认为这是最相关的答案

    <?php
    
    class Calculator
    {
      protected $result = 0;
    
      public function sum($num)
      {
        $this->result += $num;
        return $this;
      }
    
      public function sub($num)
      {
        $this->result -= $num;
        return $this;
      }
    
      public function result()
      {
        return $this->result;
      }
    }
    
    $calculator = new Calculator;
    echo $calculator->sum(10)->sub(5)->sum(3)->result(); // 8
    

    流畅的界面允许您链接方法调用,这会导致在同一对象上应用多个操作时键入的字符更少

    class Bill { 
    
        public $dinner    = 20;
    
        public $desserts  = 5;
    
        public $bill;
    
        public function dinner( $person ) {
            $this->bill += $this->dinner * $person;
            return $this;
        }
        public function dessert( $person ) {
            $this->bill += $this->desserts * $person;
            return $this;
        }
    }
    
    $bill = new Bill();
    
    echo $bill->dinner( 2 )->dessert( 3 )->bill;
    


    你能在PHP4中执行
    return&$this
    吗?@alex:我现在没有要测试的PHP4,但我很确定没有。我也不这么认为,但它应该可以正常工作?也许如果PHP4不是那么PHP4-ish,这有时也被称为流利Interface@Nitesh这是不正确的。使用作为其主要机制,但是。方法链接只是返回宿主对象,而Fluent接口旨在创建一个宿主对象。例如:
    $foo->setBar(1)->setBaz(2)
    vs
    $table->select()->from('foo')->其中('bar=1')->订单('ASC)
    。后者跨越多个对象。公共函数_-toString(){return$this->str;}如果您已经在回显链,则不需要最后一个方法“getStr()”。@t如果为True,那么我们将引入神奇的方法。一次一个概念就足够了。由于PHP5.4,甚至可以将所有内容都放在一行中:
    a=(new fakeString())->addA()->addB()->getStr()我想说,如果不是所有这些问题都是关于链接的技术细节的话,那么更多的是关于如何实现链接的问题。@Kristofer OP可以很容易地从这些问题中找到它是如何实现的。@Kristofer此外,搜索将作为第一个结果给出OP a。我不介意回答简单的问题,但有些人就是太懒了。我提交给你阅读,解释有点不对劲。不会传递返回值。这些方法只是返回宿主对象。@Gordon好吧,宿主对象不会返回。任何对象都可以被返回和链接。然后我认为这不是Fowler定义的方法链接,例如-如果你返回其他对象,它更可能是一个流畅的界面:)哇,我意识到我在评论一篇将近8年的帖子。。但你的链接,你有,是重定向到其他网站。仅供参考。这就是我所说的一个很好的解释…链接方法总是让我鸡皮疙瘩!!如何识别(在方法内部)链中的第一个和最后一个元素(调用)。因为有时候这只是一个按顺序执行的操作列表,而是在收集所有元素之后应该做的事情。就像在这里执行SQL查询一样——但是要注意,您可以对一个对象执行多个链式调用!这不是一个真正的答案,而是一个链接到一个有潜在答案的网页。这并不是真正的答案(“什么是方法链接?”)。另外,原来的问题已经8年了,已经有了一些更好的答案。你能解释一下这是做什么的吗?有什么解释吗?这个答案缺少教育意义上的解释。
    
    <?php
    use \Dsheiko\Extras\Strings;
    $res = Strings::from( " 12345 " )
                ->replace("/1/", "5")
                ->replace("/2/", "5")
                ->trim()
                ->substr(1, 3)
                ->get();
    echo $res; // "534"
    
    <?php
    use \Dsheiko\Extras\Any;
    
    $res = Any::chain(new \ArrayObject([1,2,3]))
        ->toArray() // value is [1,2,3]
        ->map(function($num){ return [ "num" => $num ]; })
        // value is [[ "num" => 1, ..]]
        ->reduce(function($carry, $arr){
            $carry .= $arr["num"];
            return $carry;
    
        }, "") // value is "123"
        ->replace("/2/", "") // value is "13"
        ->then(function($value){
          if (empty($value)) {
            throw new \Exception("Empty value");
          }
          return $value;
        })
        ->value();
    echo $res; // "13"
    
    <?php
    
    class Calculator
    {
      protected $result = 0;
    
      public function sum($num)
      {
        $this->result += $num;
        return $this;
      }
    
      public function sub($num)
      {
        $this->result -= $num;
        return $this;
      }
    
      public function result()
      {
        return $this->result;
      }
    }
    
    $calculator = new Calculator;
    echo $calculator->sum(10)->sub(5)->sum(3)->result(); // 8
    
    class Bill { 
    
        public $dinner    = 20;
    
        public $desserts  = 5;
    
        public $bill;
    
        public function dinner( $person ) {
            $this->bill += $this->dinner * $person;
            return $this;
        }
        public function dessert( $person ) {
            $this->bill += $this->desserts * $person;
            return $this;
        }
    }
    
    $bill = new Bill();
    
    echo $bill->dinner( 2 )->dessert( 3 )->bill;