ความหมายของ Three dot (…) ใน PHP


126

ความหมายของ Three dot (... ) ใน PHP คืออะไร?

ในขณะที่ฉันติดตั้ง Magento 2 ใน Sever ฉันได้รับข้อผิดพลาด ตรวจสอบรหัสและพบว่ามีจุดสามจุด (... ) ซึ่งทำให้เกิดข้อผิดพลาด ฉันพูดถึงรหัสด้านล่าง

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

การบรรจุ / การเปิดกล่องอาร์เรย์เปิดตัวใน PHP 5.6
Mark Baker

คุณตรวจสอบข้อกำหนดก่อนการติดตั้งหรือไม่: devdocs.magento.com/guides/v2.0/install-gde/…
Mathieu de Lorimier

4
เพียงแค่ความคิดเห็นแบบสุ่มนี่คือตัวดำเนินการกระจายใน JS :)
Chris Happy

@ChrisHappy ในกรณีนี้มันเป็นตัวดำเนินการที่เหลือจริงๆ
Kenny Horna

ดูเพิ่มเติม: PHP splat operator
dreftymac

คำตอบ:


193

...$strจะเรียกว่าเป็นผู้ประกอบการใน PHP

คุณลักษณะนี้ช่วยให้คุณสามารถบันทึกอาร์กิวเมนต์จำนวนตัวแปรของฟังก์ชันรวมกับอาร์กิวเมนต์ "ปกติ" ที่ส่งผ่านหากคุณต้องการ ดูง่ายที่สุดด้วยตัวอย่าง:

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

รายการพารามิเตอร์ในการประกาศฟังก์ชันมีตัว...ดำเนินการอยู่และโดยพื้นฐานแล้วจะหมายถึง "... และอย่างอื่นควรรวมเป็น $ strings" คุณสามารถส่งอาร์กิวเมนต์ 2 ตัวขึ้นไปในฟังก์ชันนี้และอาร์กิวเมนต์ที่สองและที่ตามมาจะถูกเพิ่มลงในอาร์เรย์ $ strings พร้อมใช้งาน

หวังว่านี่จะช่วยได้!


1
ขอบคุณ :) ทำไมฉันจึงควรใช้ตัวดำเนินการ SPLAT แทนที่จะเป็นเช่นนี้ฉันสามารถส่งสตริงเหล่านั้นทั้งหมดในอาร์เรย์เป็นอาร์กิวเมนต์ที่สองได้ ???
bikash.bilz

3
@ bikash.bilz ฉันจะพูดสำหรับผู้ตอบ: ผมคิดว่ามันเป็นเพียงแค่น้ำตาลประโยค ตัวดำเนินการแยกสัญญาณช่วยให้คุณประหยัดจากข้อโต้แย้งที่มี[และ]. มันไม่ค่อยมีประโยชน์ แต่ฉันคิดว่ามันดูดี
Kodos Johnson

20
คุณสามารถพิมพ์คำแนะนำพารามิเตอร์ตัวแปรได้เช่นกัน ดังนั้นใน PHP 7.2 คุณสามารถกำหนดfunction myFunc($foo, string ...$bar)ไฟล์. จากนั้น$barให้ฟังก์ชันของคุณเป็นอาร์เรย์ของสตริงและไม่มีสิ่งอื่นใดรับประกันได้ในขณะทำงาน คุณไม่สามารถทำได้ด้วยพารามิเตอร์อาร์เรย์เดียว
Jason

4
นี่เป็นมากกว่าน้ำตาลไวยากรณ์เพราะอนุญาตให้มีอาร์เรย์ในบริบทที่ต้องการจำนวนสตริงคงที่ การใช้สตริงจำนวนคงที่ทำให้คุณต้องแยกตัวประกอบซอร์สโค้ดของคุณใหม่ทุกครั้งที่จำนวนสตริงอาจเปลี่ยนแปลง
dreftymac

2
ตัวอย่างง่ายๆคือลายเซ็นของฟังก์ชันที่ใช้ในการสืบค้นฐานข้อมูล function get_data($fname,$lname,$age)จะต้องเปลี่ยนหากคุณต้องการให้ฟิลด์อื่นนอกเหนือจากสามช่องfunction get_data(...$fields)นั้นไม่จำเป็นต้องเปลี่ยนคุณต้องระบุเฉพาะฟิลด์ที่คุณต้องการ$fieldsเท่านั้น @heykatieben
dreftymac

21

ทุกคำตอบหมายถึงบล็อกโพสต์เดียวกันนอกจากนี้นี่คือเอกสารอย่างเป็นทางการเกี่ยวกับรายการอาร์กิวเมนต์ที่มีความยาวผันแปร :

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

ใน PHP 5.6 ขึ้นไปรายการอาร์กิวเมนต์อาจรวมถึง ... โทเค็นเพื่อแสดงว่าฟังก์ชันยอมรับอาร์กิวเมนต์ที่เป็นตัวแปร อาร์กิวเมนต์จะถูกส่งผ่านไปยังตัวแปรที่กำหนดเป็นอาร์เรย์

ดูเหมือนว่าโอเปอเรเตอร์ "splat" ไม่ใช่ชื่อทางการ แต่ก็ยังน่ารัก!


13

มีการใช้งานสองจุดสำหรับจุดไข่ปลา (... ) โทเค็น PHP - คิดว่ามันเป็นการบรรจุอาร์เรย์และคลายอาร์เรย์ วัตถุประสงค์ทั้งสองใช้กับอาร์กิวเมนต์ของฟังก์ชัน


ซอง

เมื่อกำหนดฟังก์ชันหากคุณต้องการจำนวนตัวแปรแบบไดนามิกที่ให้ไว้กับฟังก์ชัน (กล่าวคือคุณไม่ทราบว่าจะมีอาร์กิวเมนต์ให้กับฟังก์ชันนั้นเมื่อเรียกใช้โค้ด) ให้ใช้โทเค็นจุดไข่ปลา (... )เพื่อ จับอาร์กิวเมนต์ที่เหลือทั้งหมดที่มีให้กับฟังก์ชันนั้นลงในอาร์เรย์ที่สามารถเข้าถึงได้ภายในบล็อกฟังก์ชัน จำนวนอาร์กิวเมนต์ไดนามิกที่จับโดยจุดไข่ปลา (... ) สามารถเป็นศูนย์หรือมากกว่า

ตัวอย่างเช่น :

// 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

เมื่อใช้การบรรจุในการสร้างอินสแตนซ์ของฟังก์ชันจุดไข่ปลา (... ) จะจับอาร์กิวเมนต์ที่เหลือทั้งหมดกล่าวคือคุณยังสามารถมีอาร์กิวเมนต์เริ่มต้นคงที่ (ตำแหน่ง) จำนวนเท่าใดก็ได้:

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

แกะ

อีกวิธีหนึ่งเมื่อเรียกใช้ฟังก์ชันหากอาร์กิวเมนต์ที่คุณระบุให้กับฟังก์ชันนั้นถูกรวมเข้ากับอาร์เรย์ก่อนหน้านี้ให้ใช้โทเค็นจุดไข่ปลา (... )เพื่อแปลงอาร์เรย์นั้นเป็นอาร์กิวเมนต์แต่ละรายการที่จัดเตรียมไว้ให้กับฟังก์ชัน - แต่ละองค์ประกอบอาร์เรย์จะถูกกำหนดให้ตามลำดับ ตัวแปรอาร์กิวเมนต์ของฟังก์ชันที่ตั้งชื่อในนิยามฟังก์ชัน

ตัวอย่างเช่น:

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

การคลายแพ็กมีประโยชน์อย่างยิ่งเมื่อใช้ฟังก์ชันอาร์เรย์เพื่อจัดการอาร์เรย์หรือตัวแปร

ตัวอย่างเช่นการแกะผลลัพธ์ของ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
นี่คือคำตอบที่ดีที่สุด คำอธิบายและตัวอย่างที่ชัดเจนมาก ขอบคุณ!!!
Jee

Unpack เป็นประโยชน์อย่างยิ่งสำหรับฟังก์ชัน OrX ของ Doctrine
Erdal G.

5

ในการใช้คุณสมบัตินี้เพียงแค่เตือน PHP ว่าจำเป็นต้องคลายอาร์เรย์ออกเป็นตัวแปรโดยใช้ไฟล์... operator. ดูรายละเอียดเพิ่มเติมได้ที่นี่ตัวอย่างง่ายๆอาจมีลักษณะดังนี้:

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

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

4

ความหมายก็คือมันสลายอาร์เรย์ที่เชื่อมโยงกับรายการ ดังนั้นคุณไม่จำเป็นต้องพิมพ์พารามิเตอร์ N เพื่อเรียกใช้เมธอดเพียงตัวเดียว if method อนุญาตให้แยกพารามิเตอร์และถ้าพารามิเตอร์เป็นประเภทเดียวกัน

สำหรับฉันสิ่งที่สำคัญที่สุดเกี่ยวกับตัวดำเนินการ Splat คือสามารถช่วยในการพิมพ์พารามิเตอร์อาร์เรย์ได้:

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

ช่วยประหยัดความพยายามในการควบคุมประเภทโดยเฉพาะอย่างยิ่งในขณะที่ทำงานกับคอลเลกชันขนาดใหญ่หรือเชิงวัตถุมาก

สิ่งสำคัญที่ต้องสังเกตคือ...$arrayทำการสลายอาร์เรย์แม้จะมีประเภทของรายการก็ตามดังนั้นคุณสามารถไปในทางที่น่าเกลียดได้เช่นกัน:

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!

แต่โปรดอย่า


ก็ไม่ได้น่าเกลียดอะไร เช่นเดียวกับฟังก์ชั่น OrX ของ Doctrine ที่ต้องการรายการ แต่คุณต้องวางอาร์เรย์ (เพราะคุณไม่รู้ว่าคุณจะส่งผ่านองค์ประกอบจำนวนเท่าใด) ฉันพบวิธีนี้ดีกว่าใช้ call_user_func_array
Erdal G.

3

นี่คือสิ่งที่เรียกว่าโอเปอเรเตอร์ "splat" โดยทั่วไปแล้วสิ่งนั้นแปลว่า "อาร์กิวเมนต์จำนวนเท่าใดก็ได้"; แนะนำด้วย PHP 5.6

ดูที่นี่สำหรับรายละเอียดเพิ่มเติม


3

ดูเหมือนว่าจะไม่มีใครพูดถึงมันดังนั้นที่นี่จะอยู่ต่อไป [นอกจากนี้ยังช่วย Google (และ SE อื่น ๆ ) ให้คำแนะนำนักพัฒนาที่ขอRest Parameters ใน PHP ]:

ตามที่ระบุไว้ที่นี่เรียกว่าRest Parametersบน JS & ฉันชอบการตั้งชื่อที่มีความหมายมากกว่าสิ่งที่แยกออก!

ใน PHP ฟังก์ชันที่จัดทำโดย... argsเรียกว่าฟังก์ชัน Variadicซึ่งเปิดตัวใน PHP5.6 func_get_args()ฟังก์ชันการทำงานเดียวกันถูกใช้ในการจะดำเนินการโดยใช้

เพื่อที่จะใช้มันอย่างถูกต้องคุณควรใช้พารามิเตอร์ที่เหลือไวยากรณ์ทุกที่มันจะช่วยลดรหัสสำเร็จรูป


1
บวกหนึ่งเพื่อช่วย Google ในการค้นหา Rest Parameter ใน PHP
kapreski

1

ฉันต้องการแชร์การใช้งานของตัวดำเนินการนี้ในเฟรมเวิร์ก Magento ซึ่งมันสร้างอินสแตนซ์อ็อบเจ็กต์ด้วยพารามิเตอร์ที่กำหนดค่าได้แบบไดนามิก (คิดว่าไฟล์กำหนดค่า XML)

ดังที่เราเห็นcreateObjectฟังก์ชันจากข้อมูลโค้ดต่อไปนี้จึงใช้อาร์เรย์ของอาร์กิวเมนต์ที่เตรียมไว้สำหรับการสร้างวัตถุ จากนั้นจะใช้ตัวดำเนินการ...(สามจุด) เพื่อส่งผ่านค่าอาร์เรย์เป็นอาร์กิวเมนต์จริงไปยังตัวสร้างของคลาส

<?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) {
            ...
        }
    }

    ...

}


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.