Tôi đang sử dụng PHP 5 và tôi đã nghe nói về một tính năng mới trong cách tiếp cận hướng đối tượng, được gọi là 'chuỗi phương thức'. Chính xác nó là cái gì? Làm thế nào để tôi thực hiện nó?
Tôi đang sử dụng PHP 5 và tôi đã nghe nói về một tính năng mới trong cách tiếp cận hướng đối tượng, được gọi là 'chuỗi phương thức'. Chính xác nó là cái gì? Làm thế nào để tôi thực hiện nó?
Câu trả lời:
Thực sự khá đơn giản, bạn có một loạt các phương thức trình biến đổi mà tất cả trả về các đối tượng gốc (hoặc khác), theo cách đó bạn có thể tiếp tục gọi các phương thức trên đối tượng được trả về.
<?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();
Kết quả này "ab"
$foo->setBar(1)->setBaz(2)
vs $table->select()->from('foo')->where('bar = 1')->order('ASC)
. Cái sau kéo dài nhiều đối tượng.
$a = (new fakeString())->addA()->addB()->getStr();
Về cơ bản, bạn lấy một đối tượng:
$obj = new ObjectWithChainableMethods();
Gọi một phương thức có hiệu quả thực hiện return $this;
ở cuối:
$obj->doSomething();
Vì nó trả về cùng một đối tượng, hay đúng hơn là một tham chiếu đến cùng một đối tượng, bạn có thể tiếp tục gọi các phương thức của cùng một lớp khỏi giá trị trả về, như vậy:
$obj->doSomething()->doSomethingElse();
Đó là nó, thực sự. Hai điều quan trọng:
Như bạn lưu ý, đó chỉ là PHP 5. Nó sẽ không hoạt động đúng trong PHP 4 vì nó trả về các đối tượng theo giá trị và điều đó có nghĩa là bạn đang gọi các phương thức trên các bản sao khác nhau của một đối tượng, điều này sẽ phá vỡ mã của bạn.
Một lần nữa, bạn cần trả về đối tượng trong các phương thức chuỗi của bạn:
public function doSomething() {
// Do stuff
return $this;
}
public function doSomethingElse() {
// Do more stuff
return $this;
}
return &$this
trong PHP4 không?
Hãy thử mã này:
<?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'
?>
Phương thức chuỗi có nghĩa là bạn có thể xâu chuỗi các cuộc gọi phương thức:
$object->method1()->method2()->method3()
Điều này có nghĩa là phương thức1 () cần trả về một đối tượng và phương thức 2 () được đưa ra kết quả của phương thức1 (). Phương thức 2 () sau đó chuyển giá trị trả về cho phương thức3 ().
Bài viết hay: http://www.talkphp.com/advified-php-programming/1163-php5-method-chained.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();
Có 49 dòng mã cho phép bạn xâu chuỗi các phương thức trên các mảng như thế này:
$fruits = new Arr(array("lemon", "orange", "banana", "apple"));
$fruits->change_key_case(CASE_UPPER)->filter()->walk(function($value,$key) {
echo $key.': '.$value."\r\n";
});
Xem bài viết này chỉ cho bạn cách xâu chuỗi tất cả bảy mươi hàm Array_ của PHP.
http://domexception.blogspot.fi/2013/08/php-magic-methods-and-arrayobject.html
Nếu bạn có nghĩa là phương thức xâu chuỗi như trong JavaScript (hoặc một số người ghi nhớ jQuery), tại sao không chỉ lấy một thư viện mang dev đó. kinh nghiệm về PHP? Ví dụ: Extras - https://dsheiko.github.io/extras/ Cái này mở rộng các loại PHP bằng các phương thức JavaScript và Underscore và cung cấp chuỗi:
Bạn có thể xâu chuỗi một loại cụ thể:
<?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();
hoặc là
<?php
use \Dsheiko\Extras\Strings;
$res = Strings::from( " 12345 " )
->replace("/1/", "5")
->replace("/2/", "5")
->trim()
->substr(1, 3)
->get();
echo $res; // "534"
Ngoài ra, bạn có thể đi đa hình:
<?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"
Dưới đây là mô hình của tôi có thể tìm thấy bằng ID trong cơ sở dữ liệu. Phương thức with ($ data) là các tham số bổ sung của tôi cho mối quan hệ vì vậy tôi trả về $ this là chính đối tượng. Trên bộ điều khiển của tôi, tôi có thể xâu chuỗi nó.
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);
}
}