ไม่สามารถผ่านอาร์กิวเมนต์เป็นโมฆะเมื่อใช้การแนะนำประเภท


193

รหัสต่อไปนี้:

<?php

    class Type {

    }

    function foo(Type $t) {

    }

    foo(null);

?>

ล้มเหลวขณะใช้งาน:

PHP Fatal error:  Argument 1 passed to foo() must not be null

เหตุใดจึงไม่อนุญาตให้ส่งผ่าน null เช่นเดียวกับภาษาอื่น ๆ

คำตอบ:


357

PHP 7.1 หรือใหม่กว่า (เผยแพร่วันที่ 2 ธันวาคม 2559)

คุณสามารถประกาศตัวแปรที่จะอยู่nullกับไวยากรณ์นี้อย่างชัดเจน

function foo(?Type $t) {
}

สิ่งนี้จะส่งผลให้

$this->foo(new Type()); // ok
$this->foo(null); // ok
$this->foo(); // error

ดังนั้นหากคุณต้องการอาร์กิวเมนต์ที่เป็นทางเลือกคุณสามารถปฏิบัติตามอนุสัญญาได้Type $t = nullในขณะที่ถ้าคุณต้องการให้อาร์กิวเมนต์ยอมรับทั้งสองnullและประเภทของอาร์กิวเมนต์คุณสามารถทำตามตัวอย่างด้านบน

คุณสามารถอ่านเพิ่มเติมที่นี่


PHP 7.0 หรือเก่ากว่า

คุณต้องเพิ่มค่าเริ่มต้นเช่น

function foo(Type $t = null) {

}

ด้วยวิธีนี้คุณสามารถส่งผ่านค่า Null ได้

นี่คือเอกสารในส่วนในคู่มือเกี่ยวกับการประกาศประเภท :

ประกาศสามารถทำที่จะยอมรับค่าถ้าค่าเริ่มต้นของพารามิเตอร์ที่มีการตั้งค่าNULLNULL


10
แล้วทำไมวัตถุ null ถึงไม่ว่าง?
Pacerier

4
ภาษาส่วนใหญ่อนุญาตให้มี null ได้ทุกประเภท ในสถานการณ์นี้
Henry

24
ในความเห็นของฉันนี่เป็นโครงสร้างภาษาที่ไม่ดี 1. ในภาษาอื่น null มีความสามารถในการเป็นประเภทใดจึงทำให้ null อาร์กิวเมนต์ที่ถูกต้องในกรณีนี้ 2: Php ใช้ค่าเริ่มต้นสำหรับอาร์กิวเมนต์เพื่อระบุว่าอนุญาตให้ทำได้ซึ่งเป็นสิ่งที่คลุมเครือและทำให้พารามิเตอร์ที่เป็นไปไม่ได้แม้ว่าผู้พัฒนาต้องการบังคับให้มีการส่งผ่านค่า null อย่างชัดเจน
Henry

2
ฉันเห็นด้วยกับ @Henry นอกจากนี้ดูเหมือนว่าจะต้องใช้พารามิเตอร์หลังจากสิ่งที่ดูเหมือนว่าเป็นพารามิเตอร์เสริม
Force Hero

6
ฉันเห็นด้วยกับ @Henry เพียงวันที่ 2 เกี่ยวกับ 1 ความจริงที่ว่าคุณไม่สามารถผ่านโมฆะไปfunction foo(Type $t)เป็นสิ่งที่ดีมาก; ดูข้อมูลอ้างอิง Null: ข้อผิดพลาดพันล้านดอลลาร์
Constantin Galbenu

36

เริ่มต้นจาก PHP 7.1 มีประเภท nullableพร้อมใช้งานเนื่องจากทั้งสองประเภทฟังก์ชันและพารามิเตอร์ส่งคืน ชนิดที่?Tสามารถมีค่าของชนิดที่กำหนดหรือTnull

ดังนั้นฟังก์ชันของคุณอาจมีลักษณะเช่นนี้:

function foo(?Type $t)
{

}

ทันทีที่คุณสามารถทำงานกับ PHP 7.1 สัญกรณ์นี้ควรเป็นที่นิยมมากกว่าfunction foo(Type $t = null)เพราะยังคงบังคับให้ผู้เรียกระบุอาร์กิวเมนต์สำหรับพารามิเตอร์$tอย่างชัดเจน


12

ลอง:

function foo(Type $t = null) {

}

ตรวจสอบPHP อาร์กิวเมนต์ของฟังก์ชัน


11
ปัญหาที่ฉันมีกับสิ่งนี้คือมันเปลี่ยนนิยามของฟังก์ชัน ตอนนี้พารามิเตอร์เป็นทางเลือก - ซึ่งไม่ใช่สิ่งที่ผู้เขียนตั้งใจจริง (แม้ว่าถ้าเขาผ่านมันเป็นโมฆะก็เป็นทางเลือกโดยปริยาย)
บดขยี้

7

ตามคำตอบอื่น ๆ ที่กล่าวถึงแล้วจะสามารถทำได้เฉพาะเมื่อคุณระบุnullเป็นค่าเริ่มต้น

แต่วิธีแก้ปัญหาวัตถุที่เน้นความปลอดภัยและปลอดภัยที่สุดคือ NullObject :

interface FooInterface
{
    function bar();
}
class Foo implements FooInterface
{
    public function bar()
    {
        return 'i am an object';
    }
}
class NullFoo implements FooInterface
{
    public function bar()
    {
        return 'i am null (but you still can use my interface)';
    }
}

การใช้งาน:

function bar_my_foo(FooInterface $foo)
{
    if ($foo instanceof NullFoo) {
        // special handling of null values may go here
    }
    echo $foo->bar();
}

bar_my_foo(new NullFoo);

1
วิธีการนี้มักจะไม่สามารถทำได้เพราะแทนที่จะเป็น 1 คลาสคุณต้องมี 3 นอกจากนี้มันยังบังคับให้ผู้เขียนNullFooแทนที่วิธีนามธรรมแม้ว่าพวกเขาจะไม่มีความหมาย (โดยนิยามของnull)
TheOperator

1
จากประสบการณ์ของฉันรูปแบบ NullObject สามารถใช้งานได้จริงถ้าคุณทำงานโดยทั่วไปด้วยวิธี OO แบบคลาสสิกที่เข้มงวดมาก ในคำตอบรูปแบบ NullObject ของ imo นั้นถูกใช้ในทางที่ผิดเนื่องจากมันมีความหมายเป็นพิเศษเพื่อหลีกเลี่ยงการif (something is null)ตรวจสอบเนื่องจาก NullObject นั้นมีวัตถุประสงค์เพื่อครอบคลุมพฤติกรรมทั้งหมดของค่าที่ไม่มีอยู่และผู้ร่วมมือภายนอกไม่ควรสนใจว่าจะเป็น วัตถุนั้นไม่มีอยู่จริง (null) หรือไม่
แพ้
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.