8 ответов:
его довольно просто на самом деле, у вас есть серия методы мутатор что все возвращает исходные (или другие) объекты, таким образом, вы можете продолжать вызывать методы на возвращаемый объект.
<?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();так как он возвращает тот же объект, а точнее, a ссылка к тому же объекту, вы можете продолжать вызывать методы того же класса от возвращаемого значения, например:
$obj->doSomething()->doSomethingElse();вот и все, правда. Две важные вещи:
как вы заметили, это только PHP 5. Он не будет работать на PHP 4 потому что он возвращает объекты по значению, и это означает, что вы вызываете методы на разных копиях объекта, что нарушит ваш код.
опять же, вам нужно вернуть объект в цепочке методов:
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
есть 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"; });см. эту статью, в которой показано, как связать все семьдесят функций array_ PHP.
http://domexception.blogspot.fi/2013/08/php-magic-methods-and-arrayobject.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();
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); } }
Если вы имеете в виду метод цепочки, как в JavaScript (или некоторые люди имеют в виду jQuery), почему бы просто не взять библиотеку, которая приносит этот dev. опыт работы в PHP? Например Экстры -https://dsheiko.github.io/extras/ это расширяет типы PHP с помощью JavaScript и методов подчеркивания и обеспечивает цепочку:
вы можете связать определенный тип:
<?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"
Comments