php PHP方法链?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3724112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 10:52:53  来源:igfitidea点击:

PHP method chaining?

phpoopmethod-chaining

提问by Sanjay Khatri

I am using PHP 5 and I've heard of a new featured in the object-oriented approach, called 'method chaining'. What is it exactly? How do I implement it?

我正在使用 PHP 5,并且听说了面向对象方法中的一个新功能,称为“方法链”。究竟是什么?我该如何实施?

回答by Kristoffer Sall-Storgaard

Its rather simple really, you have a series of mutator methodsthat all returns the original (or other) objects, that way you can keep calling methods on the returned object.

它真的很简单,你有一系列的mutator 方法,它们都返回原始(或其他)对象,这样你就可以继续调用返回对象的方法。

<?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();

This outputs "ab"

这输出“ab”

Try it online!

在线试试吧!

回答by BoltClock

Basically, you take an object:

基本上,你拿一个对象:

$obj = new ObjectWithChainableMethods();

Call a method that effectively does a return $this;at the end:

调用一个return $this;在最后有效执行 a 的方法:

$obj->doSomething();

Since it returns the same object, or rather, a referenceto the same object, you can continue calling methods of the same class off the return value, like so:

由于它返回相同的对象,或者更确切地说,是相同对象的引用,因此您可以继续从返回值调用相同类的方法,如下所示:

$obj->doSomething()->doSomethingElse();

That's it, really. Two important things:

就是这样,真的。两个重要的事情:

  1. As you note, it's PHP 5 only. It won't work properly in PHP 4 because it returns objects by value and that means you're calling methods on different copies of an object, which would break your code.

  2. Again, you need to return the object in your chainable methods:

    public function doSomething() {
        // Do stuff
        return $this;
    }
    
    public function doSomethingElse() {
        // Do more stuff
        return $this;
    }
    
  1. 正如您所注意到的,它只是 PHP 5。它在 PHP 4 中无法正常工作,因为它按值返回对象,这意味着您在对象的不同副本上调用方法,这会破坏您的代码。

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

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

回答by mwangaben

Try this code:

试试这个代码:

<?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'

?>

回答by alexn

Method chaining means that you can chain method calls:

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

$object->method1()->method2()->method3()

This means that method1() needs to return an object, and method2() is given the result of method1(). Method2() then passes the return value to method3().

这意味着method1() 需要返回一个对象,method2() 被赋予method1() 的结果。Method2() 然后将返回值传递给 method3()。

Good article: http://www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html

好文章:http: //www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html

回答by Rashedul Islam Sagor

Another Way for static method chaining :

静态方法链的另一种方式:

class Maker 
{
    private static $result      = null;
    private static $delimiter   = '.';
    private static $data        = [];

    public static function words($words)
    {
        if( !empty($words) && count($words) )
        {
            foreach ($words as $w)
            {
                self::$data[] = $w;
            }
        }        
        return new static;
    }

    public static function concate($delimiter)
    {
        self::$delimiter = $delimiter;
        foreach (self::$data as $d)
        {
            self::$result .= $d.$delimiter;
        }
        return new static;
    }

    public static function get()
    {
        return rtrim(self::$result, self::$delimiter);
    }    
}

Calling

打电话

echo Maker::words(['foo', 'bob', 'bar'])->concate('-')->get();

echo "<br />";

echo Maker::words(['foo', 'bob', 'bar'])->concate('>')->get();

回答by Lukas Dong

There are 49 lines of code which allows you to chain methods over arrays like 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";
});

See this article which shows you how to chain all the PHP's seventy array_ functions.

请参阅这篇文章,它向您展示了如何链接所有 PHP 的 70 个 array_ 函数。

http://domexception.blogspot.fi/2013/08/php-magic-methods-and-arrayobject.html

http://domexception.blogspot.fi/2013/08/php-magic-methods-and-arrayobject.html

回答by Dmitry Sheiko

If you mean method chaining like in JavaScript (or some people keep in mind jQuery), why not just take a library that brings that dev. experience in PHP? For example Extras - https://dsheiko.github.io/extras/This one extends PHP types with JavaScript and Underscore methods and provides chaining:

如果你的意思是像 JavaScript 中的方法链(或者有些人记得 jQuery),为什么不直接采用一个能够带来开发的库。PHP 的经验?例如 Extras - https://dsheiko.github.io/extras/这个使用 JavaScript 和 Underscore 方法扩展 PHP 类型并提供链接:

You can chain a particular type:

您可以链接特定类型:

<?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();

or

或者

<?php
use \Dsheiko\Extras\Strings;
$res = Strings::from( " 12345 " )
            ->replace("/1/", "5")
            ->replace("/2/", "5")
            ->trim()
            ->substr(1, 3)
            ->get();
echo $res; // "534"

Alternatively you can go polymorphic:

或者你可以去多态:

<?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"

回答by JuanBruno

Below is my model that is able to find by ID in the database. The with($data) method is my additional parameters for relationship so I return the $this which is the object itself. On my controller I am able to chain it.

下面是我的模型,可以在数据库中通过 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);
    }
}