Phương pháp PHP xâu chuỗi?


170

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


1
Tôi muốn nói nhất nếu không phải tất cả những câu hỏi đó là về kỹ thuật liên quan đến chuỗi, đây là cách cụ thể hơn để đạt được nó.
Kristoffer Sall-Storgaard

@Kristoffer OP có thể dễ dàng tìm thấy cách đạt được từ những câu hỏi này.
Gordon

2
Ngoài ra, @Kristoffer, việc tìm kiếm phương thức xâu chuỗi php trên Google sẽ cung cấp cho OP một hướng dẫn của Saledit như là kết quả đầu tiên. Tôi không ngại trả lời những câu hỏi dễ, nhưng một số người quá lười biếng.
Gordon

6
Tôi đệ trình cho sự nhìn chăm chú của bạn, cây quyết định phương pháp dứt khoát
ndlowrey

Câu trả lời:


333

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"

Hãy thử trực tuyến!


10
Điều này đôi khi cũng được gọi là Giao diện
trôi chảy

17
@Nitesh không đúng. Giao diện lưu loát sử dụng Phương thức Xâu chuỗi làm cơ chế chính của chúng, nhưng nó không giống nhau . Phương thức xâu chuỗi đơn giản trả về đối tượng máy chủ, trong khi Giao diện Fluent nhằm mục đích tạo DSL . Ex: $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.
Gordon

3
hàm công khai __toString () {return $ this-> str; } Điều này sẽ không yêu cầu phương thức cuối cùng "getStr ()" nếu bạn đã lặp lại chuỗi.
tfont

6
@tfont Đúng, nhưng sau đó chúng tôi sẽ giới thiệu các phương pháp ma thuật. Một khái niệm tại một thời điểm nên là đủ.
Kristoffer Sall-Storgaard

3
Kể từ PHP 5.4, thậm chí có thể mọi thứ trong một dòng:$a = (new fakeString())->addA()->addB()->getStr();
Philzen

48

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:

  1. 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.

  2. 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;
    }

Bạn có thể làm return &$thistrong PHP4 không?
alex

@alex: Tôi không có PHP 4 để kiểm tra ngay bây giờ, nhưng tôi khá chắc chắn là không.
BoltClock

4
Tôi cũng không nghĩ vậy, nhưng nó sẽ hoạt động đúng không? Có lẽ nếu PHP4 không như vậy PHP4-ish.
alex

Bạn có thể nhận được các bước đơn giản hoàn chỉnh của phương pháp xâu chuỗi tại techflirt.com/tutorials/oop-in-php/php-method-chained.html
Ankur Kumar Singh

28

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'

?>

1
đây là những gì tôi gọi là một lời giải thích tốt ... phương pháp xâu chuỗi luôn mang lại cho tôi sự ngông cuồng !!
MYNE

Cách tôi xác định (bên trong phương thức) các phần tử đầu tiên và cuối cùng (các cuộc gọi) trong chuỗi. Bởi vì đôi khi đây chỉ là một danh sách các hoạt động được thực hiện theo thứ tự, nhưng một số việc nên được thực hiện sau khi thu thập tất cả các yếu tố. Giống như thực hiện một truy vấn SQL ở đây - nhưng hãy cẩn thận, bạn có thể thực hiện nhiều cuộc gọi được xâu chuỗi trên một đối tượng! Firt và cuối cùng trong mỗi.
Andris

12

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


5
Giải thích là một chút tắt. Các giá trị trả lại không được thông qua xung quanh. Các phương thức chỉ cần trả về đối tượng máy chủ.
Gordon

@Gordon Vâng, đối tượng máy chủ không được trả lại. Bất kỳ đối tượng có thể được trả lại và bị xiềng xích.
alexn

2
Sau đó, tôi sẽ lập luận rằng nó không phải là chuỗi phương thức như được định nghĩa bởi Fowler, ví dụ: Tạo các phương thức sửa đổi trả về đối tượng máy chủ để có thể gọi nhiều bộ sửa đổi trong một biểu thức. - nếu bạn trả lại các đối tượng khác, nhiều khả năng đó là Giao diện thông thạo :)
Gordon

Ồ, tôi nhận ra rằng tôi đang bình luận về một bài viết gần 8 năm tuổi .. Nhưng liên kết của bạn mà bạn có ở đó, đang chuyển hướng đến một số trang web khác. Chỉ cần fyi.
willbeeler

11

Một cách khác cho chuỗi phương thức tĩnh:

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

Gọi điện thoại

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

echo "<br />";

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

6

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


5
Đây thực sự không phải là một câu trả lời nhiều như một liên kết đến một trang web có câu trả lời tiềm năng.
faintsignal

-1

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"

Điều này không thực sự trả lời câu hỏi ("Phương thức xâu chuỗi là gì?"). Ngoài ra, câu hỏi ban đầu là 8 tuổi và đã có một số câu trả lời hay hơn
GordonM

-1

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

bạn có thể giải thích điều này làm gì?
ichimaru

bất kỳ lời giải thích những gì này?
Patrick
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.