[php] PHP 메소드 체인?

PHP 5를 사용하고 있으며 ‘method chaining’이라는 객체 지향 접근 방식의 새로운 기능에 대해 들었습니다. 정확히 무엇입니까? 어떻게 구현합니까?



답변

오히려 간단 합니다. 모두 원래 (또는 다른) 객체를 반환 하는 일련의 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();

이것은 “ab”를 출력합니다

온라인으로 사용해보십시오!


답변

기본적으로 객체를 가져옵니다.

$obj = new ObjectWithChainableMethods();

return $this;마지막에 효과적으로 수행하는 메소드를 호출하십시오 .

$obj->doSomething();

동일한 객체 또는 동일한 객체에 대한 참조 를 반환하므로 다음과 같이 동일한 클래스의 메서드를 반환 값에서 계속 호출 할 수 있습니다.

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

그게 다야. 중요한 두 가지 :

  1. 아시다시피, 그것은 PHP 5 전용입니다. PHP 4에서는 값으로 객체를 반환하므로 객체의 다른 사본에서 메소드를 호출하여 코드를 손상시킬 수 있기 때문에 제대로 작동하지 않습니다.

  2. 다시 말하지만, 연결 가능한 메소드에서 객체를 반환해야합니다.

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

답변

이 코드를 사용해보십시오 :

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

?>


답변

메소드 체인은 메소드 호출을 체인 할 수 있음을 의미합니다.

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

즉, method1 ()은 객체를 반환해야하며 method2 ()에는 method1 ()의 결과가 제공됩니다. 그런 다음 Method2 ()는 반환 값을 method3 ()에 전달합니다.

좋은 기사 : http://www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html


답변

정적 메소드 체인의 또 다른 방법 :

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

부름

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

echo "<br />";

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


답변

다음과 같은 배열을 통해 메소드를 연결할 수있는 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의 70 가지 array_ 함수를 연결하는 방법을 보여주는이 기사를 참조하십시오.

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


답변

JavaScript와 같은 메소드 체인 (또는 일부 사람들은 jQuery를 염두에 두는 것)을 의미한다면, 그 개발자를 가져 오는 라이브러리를 가져 가십시오. PHP 경험? 예를 들어 Extras- https ://dsheiko.github.io/extras/ 이것은 JavaScript 및 Underscore 메소드로 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
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"