Tidak dapat meneruskan argumen nol saat menggunakan tipe hinting

193

Kode berikut:

<?php

    class Type {

    }

    function foo(Type $t) {

    }

    foo(null);

?>

gagal saat dijalankan:

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

Mengapa tidak diizinkan lulus nol seperti bahasa lain?

Abdullah
sumber

Jawaban:

357

PHP 7.1 atau lebih baru (dirilis 2 Desember 2016)

Anda dapat secara eksplisit mendeklarasikan variabel yang ada nulldengan sintaks ini

function foo(?Type $t) {
}

ini akan menghasilkan

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

Jadi, jika Anda menginginkan argumen opsional, Anda dapat mengikuti konvensi Type $t = nullsedangkan jika Anda perlu membuat argumen menerima keduanya nulldan tipenya, Anda dapat mengikuti contoh di atas.

Anda dapat membaca lebih lanjut di sini .


PHP 7.0 atau lebih tua

Anda harus menambahkan nilai default seperti

function foo(Type $t = null) {

}

Dengan begitu, Anda bisa memberikan nilai nol.

Ini didokumentasikan di bagian dalam manual tentang Deklarasi Jenis :

Deklarasi dapat dibuat untuk menerima NULLnilai jika nilai default dari parameter diatur ke NULL.

DonCallisto
sumber
10
Jadi mengapa tidak null objek nol ?
Pacerier
4
Sebagian besar bahasa mengizinkan null untuk memiliki jenis apa pun. Dalam skenario ini.
Henry
24
Menurut pendapat saya ini adalah konstruksi bahasa yang buruk. 1. Dalam bahasa lain null memiliki kemampuan untuk jenis apa pun sehingga membuat null argumen yang valid dalam kasus ini. 2: Php menggunakan nilai default untuk argumen untuk menentukan bahwa null diijinkan, ini tidak jelas dan itu membuat parameter wajib tidak mungkin bahkan jika pengembang ingin memaksa null untuk secara eksplisit disahkan.
Henry
2
Saya setuju dengan @Henry, selain itu terlihat aneh memiliki params diperlukan setelah apa yang tampak seperti param opsional.
Pahlawan Paksa
6
Saya setuju dengan @Henry hanya pada 2. Mengenai 1 fakta bahwa Anda tidak dapat melewati nol function foo(Type $t)adalah hal yang SANGAT baik; lihat Referensi Null: Kesalahan Miliar Dolar
Constantin Galbenu
36

Mulai dari PHP 7.1, tersedia tipe nullable , karena keduanya berfungsi mengembalikan tipe dan parameter. Tipe ?Tdapat memiliki nilai dari Tipe yang ditentukan T, atau null.

Jadi, fungsi Anda bisa terlihat seperti ini:

function foo(?Type $t)
{

}

Segera setelah Anda dapat bekerja dengan PHP 7.1, notasi ini lebih disukai daripada function foo(Type $t = null), karena masih memaksa pemanggil untuk secara eksplisit menentukan argumen untuk parameter $t.

TheOperator
sumber
12

Mencoba:

function foo(Type $t = null) {

}

Lihat argumen fungsi PHP .

SeanWM
sumber
11
Masalah yang saya miliki dengan ini adalah bahwa ia mengubah definisi fungsi. Sekarang parameternya adalah opsional - yang sebenarnya bukan yang dimaksudkan oleh penulis (walaupun, jika ia meneruskannya nol, secara implisit opsional).
hancurkan
7

Seperti jawaban lain yang telah disebutkan, ini hanya mungkin jika Anda menetapkan nullsebagai nilai default.

Tetapi solusi berorientasi objek terbersih-tipe terbersih akan menjadi 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)';
    }
}

Pemakaian:

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);
Fabian Schmengler
sumber
1
Pendekatan ini sering tidak praktis, karena alih-alih 1 kelas, Anda sekarang perlu 3. Selain itu, memaksa penulis NullFoountuk menimpa metode abstrak, meskipun mereka tidak memiliki makna (menurut definisi null).
TheOperator
1
Dalam pengalaman saya, pola NullObject bisa praktis, jika Anda bekerja secara umum dengan cara OO klasik yang sangat ketat. Dalam jawabannya, imo pola NullObject sedikit disalahgunakan, karena ini terutama dimaksudkan untuk menghindari if (something is null)cek, karena NullObject dimaksudkan untuk mencakup semua perilaku dari nilai yang tidak ada dan kolaborator luar tidak perlu tertarik pada apakah suatu objek tidak ada (null) atau tidak.
hilang