ผ่าน Array เป็นอาร์กิวเมนต์ไม่ใช่ Array ใน PHP


148

ฉันดูเหมือนจะจำได้ว่าใน PHP มีวิธีที่จะส่งผ่านอาร์เรย์เป็นรายการของข้อโต้แย้งสำหรับฟังก์ชั่นการลงทะเบียนอาร์เรย์ในfunc($arg1, $arg2)ลักษณะมาตรฐาน แต่ตอนนี้ฉันหลงทางไปแล้ว ฉันจำลักษณะของการส่งผ่านโดยอ้างอิงถึงวิธี "glob" พารามิเตอร์ขาเข้า ... แต่ไม่ใช่วิธีการยกเลิกรายการอาร์เรย์ลงในรายการของการขัดแย้ง

อาจจะง่ายเหมือนfunc(&$myArgs)แต่ฉันค่อนข้างแน่ใจว่าไม่ใช่ แต่น่าเสียดายที่คู่มือ php.net ยังไม่ได้เปิดเผยอะไรเลย ไม่ว่าฉันจะต้องใช้คุณสมบัตินี้เป็นพิเศษสำหรับปีที่แล้ว

คำตอบ:


178

1
ฉันสาบานได้เลยว่ามันเป็นฟังก์ชั่นที่ไม่ใช่หน้าที่เหมือนอักขระนำหน้าหรืออะไรบางอย่าง ขอบคุณ
Robert K

8
แต่ฉันไม่รู้ Python! ฉันต้องเป็นโรคจิตโดยไม่ตั้งใจ ... : D
Robert K

45
การเปิดกล่องบรรจุอาร์กิวเมนต์ตามที่เรียกว่าจะถูกเพิ่มใน PHP 5.6 ( wiki.php.net/rfc/argument_unpacking ) มันจะใช้ตัวดำเนินการ 'แดง': '... ' ไวยากรณ์ของมัน: $args = [1,2,3]; function(...$args){}
arothuis

4
แต่ถ้าฟังก์ชันที่คุณต้องการเรียกใช้เป็นวิธีการอินสแตนซ์บนวัตถุไม่ใช่ชื่อฟังก์ชันในพื้นที่ส่วนกลาง
ahnbizcad

6
@ahnbizcad คุณควรใช้ a callableซึ่งใช้เหมือนกันcall_user_func_arrayเฉพาะกับอาร์เรย์ที่องค์ประกอบแรกคือวัตถุและที่สองคือวิธีการ ตัวอย่างเช่นcall_user_func_array([$object, 'method'], $myArgs);
SteveB

149

ดังที่ได้กล่าวไว้แล้วใน PHP 5.6+ คุณสามารถ (ควร!) ใช้...โทเค็น (หรือที่รู้จักกันในชื่อ "เครื่องหมายตัวดำเนินการ splat" ซึ่งเป็นส่วนหนึ่งของฟังก์ชันฟังก์ชัน Variadic ) เพื่อเรียกฟังก์ชันที่มีอาร์กิวเมนต์มากมาย

<?php
function variadic($arg1, $arg2)
{
    // Do stuff
    echo $arg1.' '.$arg2;
}

$array = ['Hello', 'World'];

// 'Splat' the $array in the function call
variadic(...$array);

// 'Hello World'

หมายเหตุ: รายการอาเรย์จะถูกแมปกับอาร์กิวเมนต์ตาม ตำแหน่ง ในอาเรย์ไม่ใช่คีย์

ตามความเห็นของ CarlosCarucceรูปแบบของการโต้แย้งการเปิดออกเป็นวิธีที่เร็วที่สุดในทุกกรณี ในการเปรียบเทียบบางมันมากกว่า 5 call_user_func_arrayเท่าเร็วกว่า

นอกเหนือ

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

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

นี่เป็นวิธีที่ดีในการตรวจสอบให้แน่ใจว่าอาร์เรย์มีรายการที่มีประเภทเฉพาะ:

<?php

// Define the function...

function variadic($var, SomeClass ...$items)
{
    // $items will be an array of objects of type `SomeClass`
}

// Then you can call...

variadic('Hello', new SomeClass, new SomeClass);

// or even splat both ways

$items = [
    new SomeClass,
    new SomeClass,
];

variadic('Hello', ...$items);

7
call_user_func_arrayนี้มีการปรับปรุงกว่าประสิทธิภาพที่ยอดเยี่ยม ดังนั้นหากคุณใช้ php 5.6+ ฉันอยากจะแนะนำอันนี้ นี่คือการทดสอบที่ถูกอ้างถึงในphp wiki อย่างเป็นทางการ
CarlosCarucce

2
น่าเสียดายจริง ๆ นี่ไม่ใช่คำตอบที่ทำเครื่องหมายไว้ ทางที่ดีขึ้นอย่างแน่นอน
ไม่

81

โปรดทราบด้วยว่าหากคุณต้องการใช้วิธีการแบบอินสแตนซ์กับอาร์เรย์คุณจะต้องผ่านฟังก์ชันดังนี้:

call_user_func_array(array($instance, "MethodName"), $myArgs);

4
@understack $foo->bar()ตัวอย่างเช่นในหน้าที่เชื่อมโยงarray($instance, "MethodName")ให้เห็นว่ามันควรจะเป็น
Paul Calcraft

11
น่ากลัวผมใช้นี้เพื่อหลีกเลี่ยงการทำซ้ำตัวสร้างข้อโต้แย้งในชั้นเรียนเด็ก :)call_user_func_array(array(parent, "__construct"), func_get_args());
เจสัน

10

เพื่อความสมบูรณ์ขณะที่ PHP 5.1 ก็ใช้งานได้เช่นกัน:

<?php
function title($title, $name) {
    return sprintf("%s. %s\r\n", $title, $name);
}
$function = new ReflectionFunction('title');
$myArray = array('Dr', 'Phil');
echo $function->invokeArgs($myArray);  // prints "Dr. Phil"
?>

ดู: http://php.net/reflectionfunction.invokeargs

สำหรับวิธีการที่คุณใช้ReflectionMethod :: invokeArgsแทนและส่งผ่านวัตถุเป็นพารามิเตอร์แรก


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