Ý nghĩa của Three dot (…) trong PHP


125

Ý nghĩa của Three dot (...) trong PHP là gì?

Trong khi cài đặt Magento 2 trong Sever của mình, tôi đã gặp lỗi. Điều tra mã và thấy rằng có Dấu ba chấm (...), đang tạo ra lỗi. Tôi đã đề cập đến đoạn mã dưới đây

return new $type(...array_values($args));

đóng gói / giải nén mảng được giới thiệu trong PHP 5.6
Mark Baker

Bạn đã kiểm tra các yêu cầu trước khi cài đặt: devdocs.magento.com/guides/v2.0/install-gde/...
Mathieu de Lorimier

4
Chỉ là một nhận xét ngẫu nhiên, đây là toán tử spread trong JS. :)
Chris Happy

@ChrisHappy trong trường hợp này nó thực sự là toán tử còn lại .
Kenny Horna

Câu trả lời:


191

...$strđược gọi là toán tử splat trong PHP .

Tính năng này cho phép bạn nắm bắt một số lượng biến đối số cho một hàm, kết hợp với các đối số "bình thường" được truyền vào nếu bạn muốn. Dễ thấy nhất với một ví dụ:

function concatenate($transform, ...$strings) {
    $string = '';
    foreach($strings as $piece) {
        $string .= $piece;
    }
    return($transform($string));
}

echo concatenate("strtoupper", "I'd ", "like ", 4 + 2, " apples");
// This would print:
// I'D LIKE 6 APPLES

Danh sách tham số trong khai báo hàm có ...toán tử trong đó và về cơ bản nó có nghĩa là "... và mọi thứ khác nên chuyển thành $ string". Bạn có thể truyền 2 hoặc nhiều đối số vào hàm này và đối số thứ hai và các đối số tiếp theo sẽ được thêm vào mảng $ string, sẵn sàng được sử dụng.

Hi vọng điêu nay co ich!


1
Cảm ơn :), tại sao tôi nên sử dụng toán tử SPLAT, thay vì điều này, tôi có thể chuyển tất cả các chuỗi đó trong một mảng làm đối số thứ hai ???
bikash.bilz

3
@ bikash.bilz Tôi sẽ nói cho người trả lời: Tôi nghĩ đó chỉ là đường cú pháp . Toán tử biểu tượng giúp bạn tránh được xung quanh các đối số với []. Nó không mang lại nhiều lợi ích nhưng tôi nghĩ nó có vẻ đẹp.
Kodos Johnson

20
Bạn cũng có thể gõ-gợi ý các tham số khác nhau. Vì vậy, trên PHP 7.2, bạn có thể định nghĩa function myFunc($foo, string ...$bar). Sau đó, $barcung cấp cho hàm của bạn một mảng các chuỗi và không có gì khác, được đảm bảo tại thời điểm chạy. Bạn không thể làm điều đó với một tham số mảng duy nhất.
Jason

4
Đây không chỉ là một đường cú pháp vì nó cho phép một mảng trong các ngữ cảnh mà nếu không sẽ yêu cầu một số lượng chuỗi cố định. Việc sử dụng một số lượng chuỗi cố định đòi hỏi bạn phải tính lại mã nguồn của mình mỗi khi số lượng chuỗi có thể thay đổi.
dreftymac

2
Một ví dụ dễ hiểu là chữ ký hàm được sử dụng để truy vấn cơ sở dữ liệu. function get_data($fname,$lname,$age)sẽ phải thay đổi nếu bạn muốn các trường khác ngoài ba trường function get_data(...$fields)đó không phải thay đổi, bạn chỉ cần chỉ định các trường bạn muốn $fields. @heykatieben
dreftymac

21

Mọi câu trả lời đều đề cập đến cùng một bài đăng trên blog, ngoài chúng ra, đây là tài liệu chính thức về danh sách đối số có độ dài thay đổi :

http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list

Trong PHP 5.6 trở lên, danh sách đối số có thể bao gồm ... mã thông báo để biểu thị rằng hàm chấp nhận một số lượng biến đối số. Các đối số sẽ được chuyển vào biến đã cho dưới dạng một mảng

Có vẻ như toán tử "splat" không phải là tên chính thức, nhưng nó vẫn dễ thương!


13

Có HAI cách sử dụng đối với dấu chấm lửng (...) mã thông báo PHP — hãy nghĩ chúng như đóng gói một mảng và giải nén một mảng. Cả hai mục đích đều áp dụng cho các đối số của hàm.


Đóng gói

Khi xác định một hàm, nếu bạn cần một số biến động được cung cấp cho hàm (tức là bạn không biết có bao nhiêu đối số sẽ được cung cấp cho hàm đó khi được gọi trong mã), hãy sử dụng dấu chấm lửng (...) để nắm bắt tất cả các đối số còn lại được cung cấp cho hàm đó vào một mảng có thể truy cập được bên trong khối hàm. Số lượng đối số động được thu thập bởi dấu chấm lửng (...) có thể bằng 0 hoặc nhiều hơn.

Ví dụ :

// function definition
function sum(...$numbers) { // use ellipsis token when defining function
    $acc = 0;
    foreach ($numbers as $nn) {
        $acc += $nn;
    }
    return $acc;
}

// call the function
echo sum(1, 2, 3, 4); // provide any number of arguments

> 10

// and again...
echo sum(1, 2, 3, 4, 5);

> 15

// and again...
echo sum();

> 0

Khi đóng gói được sử dụng trong khởi tạo hàm, dấu chấm lửng (...) nắm bắt tất cả các đối số còn lại , tức là bạn vẫn có thể có bất kỳ số lượng đối số ban đầu, cố định (vị trí) nào:

function sum($first, $second, ...$remaining_numbers) {
    $acc = $first + $second;
    foreach ($remaining_numbers as $nn) {
        $acc += $nn;
    }
    return $acc;
}

// call the function
echo sum(1, 2); // provide at least two arguments

> 3

// and again...
echo sum(1, 2, 3, 4); // first two are assigned to fixed arguments, the rest get "packed"

> 10

Giải nén

Ngoài ra, khi gọi một hàm, nếu các đối số bạn cung cấp cho hàm đó trước đó được kết hợp thành một mảng, hãy sử dụng dấu chấm lửng (...) để chuyển đổi mảng đó thành các đối số riêng lẻ được cung cấp cho hàm — mỗi phần tử mảng được gán cho các biến đối số hàm có tên trong định nghĩa hàm.

Ví dụ:

function add($aa, $bb, $cc) {
    return $aa + $bb + $cc;
}

$arr = [1, 2, 3];
echo add(...$arr); // use ellipsis token when calling function

> 6

$first = 1;
$arr = [2, 3];
echo add($first, ...$arr); // used with positional arguments

> 6

$first = 1;
$arr = [2, 3, 4, 5]; // array can be "oversized"
echo add($first, ...$arr); // remaining elements are ignored

> 6

Việc giải nén đặc biệt hữu ích khi sử dụng các hàm mảng để thao tác với mảng hoặc biến.

Ví dụ: giải nén kết quả của array_slice :

function echoTwo ($one, $two) {
    echo "$one\n$two";
}

$steaks = array('ribeye', 'kc strip', 't-bone', 'sirloin', 'chuck');

// array_slice returns an array, but ellipsis unpacks it into function arguments
echoTwo(...array_slice($steaks, -2)); // return last two elements in array

> sirloin
> chuck

4
Đây là câu trả lời tốt nhất. Giải thích rất rõ ràng và ví dụ. Cảm ơn bạn!!!
Jee

Unpack rất hữu ích cho chức năng OrX của Doctrine
Erdal G.

5

Để sử dụng tính năng này, chỉ cần cảnh báo PHP rằng nó cần giải nén mảng thành các biến bằng cách sử dụng ... operator . Xem ở đây để biết thêm chi tiết, một ví dụ đơn giản có thể trông như thế này:

$email[] = "Hi there";
$email[] = "Thanks for registering, hope you like it";

mail("someone@example.com", ...$email);

4

Có nghĩa là nó phân tách một mảng kết hợp thành một danh sách. Vì vậy, bạn không cần phải nhập N tham số để gọi một phương thức, chỉ cần một. Phương thức if cho phép một tham số được phân tách và nếu các tham số có cùng kiểu.

Đối với tôi, điều quan trọng nhất về toán tử splat là nó có thể giúp gõ các tham số mảng:

$items = [
    new Item(), 
    new Item()
];

$collection = new ItemCollection();
$collection->add(...$items); // !

// what works as well:
// $collection->add(new Item());
// $collection->add(new Item(), new Item(), new Item()); // :(

class Item  {};

class ItemCollection {

    /**
     * @var Item[]
     */
    protected $items = [];

    public function add(Item ...$items)
    {
        foreach ($items as &$item) {
            $this->items[] = $item;
        }
    }
} 

nó tiết kiệm một số nỗ lực trong việc kiểm soát kiểu, đặc biệt là trong khi làm việc với các bộ sưu tập lớn hoặc hướng đối tượng.

Điều quan trọng cần lưu ý là ...$arrayphân hủy một mảng bất chấp loại mục của nó , vì vậy bạn cũng có thể đi theo cách xấu xí:

function test(string $a, int $i) {
    echo sprintf('%s way as well', $a);

    if ($i === 1) {
        echo('!');
    }
}

$params = [
    (string) 'Ugly',
    (int) 1
];

test(...$params);

// Output:
// Ugly way as well!

Nhưng làm ơn đừng.


Nó không phải là xấu xí. Giống như với các hàm OrX của Doctrine cần một danh sách, nhưng bạn cần vượt qua một mảng (vì bạn không biết mình sẽ truyền bao nhiêu phần tử). Tôi thấy cách này tốt hơn là sử dụng call_user_func_array
Erdal G.

3

Đây được gọi là toán tử "splat". Về cơ bản, điều đó chuyển thành "bất kỳ số lượng đối số nào"; được giới thiệu với PHP 5.6

Xem tại đây để biết thêm chi tiết.


3

Có vẻ như chưa ai đề cập đến nó, vì vậy hãy ở đây [Nó cũng sẽ giúp Google (& các SE khác) hướng dẫn các nhà phát triển yêu cầu Tham số phần còn lại trong PHP ]:

Như được chỉ ra ở đây, nó được gọi là Tham số nghỉ trên JS & tôi thích cách đặt tên có ý nghĩa này hơn thứ biểu tượng đó!

Trong PHP, chức năng được cung cấp bởi ... args được gọi là các hàm Variadic được giới thiệu trên PHP5.6. Chức năng tương tự đã được sử dụng để được triển khai bằng cách sử dụng func_get_args().

Để sử dụng nó đúng cách, bạn nên sử dụng cú pháp tham số phần còn lại, bất cứ nơi nào nó giúp giảm mã soạn sẵn .


1
cộng với một cho giúp đỡ google trong việc tìm kiếm các Parameter Nghỉ ngơi trong PHP
kapreski

1

Tôi muốn chia sẻ cách sử dụng toán tử này trong khuôn khổ Magento, nơi nó khởi tạo các đối tượng với các tham số có thể định cấu hình động (nghĩ là tệp cấu hình XML).

Như chúng ta có thể thấy createObjecthàm từ đoạn mã sau, hàm này nhận một mảng các đối số được chuẩn bị cho việc tạo đối tượng. Sau đó, nó sử dụng toán tử ...(ba dấu chấm) để truyền các giá trị mảng dưới dạng đối số thực cho hàm tạo của lớp.

<?php

namespace Magento\Framework\ObjectManager\Factory;

abstract class AbstractFactory implements \Magento\Framework\ObjectManager\FactoryInterface
{
    ...

    /**
     * Create object
     *
     * @param string $type
     * @param array $args
     *
     * @return object
     * @throws RuntimeException
     */
    protected function createObject($type, $args)
    {
        try {
            return new $type(...array_values($args));
        } catch (\TypeError $exception) {
            ...
        }
    }

    ...

}


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.