Я использую PHP 5, и я слышал о новом признаке в объектно-ориентированном подходе, называемом «цепочка методов». Что это такое? Как его реализовать?
Это довольно просто, у вас есть серия методов мутаторов, которые возвращают исходные (или другие) объекты, таким образом вы можете продолжать выполнять функции вызова.
<?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();
Вот и все. Две важные вещи:
Как вы заметили, это только PHP 5. Он не будет работать должным образом в PHP 4, потому что он возвращает объекты по значению, а это значит, что вы вызываете методы на разных копиях объекта, что нарушит ваш код.
Опять же, вам нужно вернуть объект в свои цепные методы:
public function doSomething() { // Do stuff return $this; } public function doSomethingElse() { // Do more stuff return $this; }
Цепочка метода означает, что вы можете цеплять вызовы методов:
$object->method1()->method2()->method3()
Это означает, что method1 () должен возвращать объект, а method2 () получает результат метода1 (). Затем метод2 () передает возвращаемое значение методу3 ().
Хорошая статья: http://www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html
Попробуйте этот код:
<?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' ?>
Есть 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.
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); } }