Jenis pengembalian tidak dapat dikembalikan dalam PHP7

159

PHP 7 memperkenalkan deklarasi tipe kembali . Yang berarti saya sekarang dapat menunjukkan nilai kembali adalah kelas tertentu, antarmuka, array, callable atau salah satu dari jenis skalar yang baru dapat diindikasikan, sebagaimana dimungkinkan untuk parameter fungsi.

function returnHello(): string {
    return 'hello';
}

Seringkali terjadi bahwa suatu nilai tidak selalu ada, dan Anda mungkin mengembalikan sesuatu dengan jenis tertentu, atau nol. Meskipun Anda dapat membuat parameter nullable dengan menetapkan default ke null ( DateTime $time = null), tampaknya tidak ada cara untuk melakukan ini untuk tipe pengembalian. Apakah memang demikian, atau apakah saya entah bagaimana tidak menemukan cara melakukannya? Ini tidak berfungsi:

function returnHello(): string? {
    return 'hello';
}

function returnHello(): string|null {
    return 'hello';
}
Jeroen De Dauw
sumber
8
PHP7 belum mengizinkan jenis pengembalian yang dapat dibatalkan, tetapi ada RFC yang bertujuan untuk mengatasinya di PHP 7.1 di sini . Notasi yang diusulkan akan menjadifunction returnString(?string $stringNull) : ?string { return $stringNull;}
Elias Van Ootegem
1
Saya akhirnya meniru nullability dengan menyalahgunakan pengecualian dalam aplikasi saya untuk saat ini. Jika Anda baik-baik saja dengan menjadi konyol, ini mungkin berguna: github.com/JeroenDeDauw/OhMyPhp/blob/master/src/…
Jeroen De Dauw
Mungkin lebih masuk akal untuk menggunakan Trowableantarmuka PHP7 (khusus, memperluas TypeError)
Elias Van Ootegem

Jawaban:

258

PHP 7.1 Sekarang mendukung jenis pengembalian yang dapat dibatalkan . RFC pertama yang saya tautkan adalah yang mereka pilih:

function nullOrString(int $foo) : ?string
{
    return $foo%2 ? "odd" : null;
}

jawaban lama:

Karena komentar saya sebenarnya adalah jawaban untuk pertanyaan:

PHP 7 tidak akan mendukung tipe pengembalian yang nullable dulu, tapi ada RFC di luar untuk mengatasi hal itu, bertujuan mendarat di PHP 7.1. Jika lolos, sintaks akan mempengaruhi semua tip-petunjuk (baik tipik tipe maupun tip-tip):

public function returnStringOrNull(?array $optionalArray) : ?string
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);//string returned here
    }
    return null;
}

Ada juga RFC yang bersaing untuk menambah jenis serikat, yang akan dapat melakukan hal yang sama, tetapi akan terlihat berbeda:

public function returnStringOrNull(array|null $optionalArray) : string|null
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);//string returned here
    }
    return null;
}

Untuk saat ini, Anda harus menulis:

public function returnStringOrNull( array $optionalArray = null)
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);
    }
}

Atau cukup kembalikan string kosong agar konsisten dengan jenis pengembalian, dan periksa nilai falsy:

public function returnStringOrNull( array $optionalArray = null) : string
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);
    }
    return '';
}
//call
$string = $x->returnStringOrNull();
if (!$string) {
    $string = $x->returnStringOrNull(range(1, 10));
}
Elias Van Ootegem
sumber
5
PHP 7 won't support nullable return-types just yet, but there's an RFC out to address just that- yeah, RFC, "dulu". Jangan salah paham - saya pengguna PHP yang sangat berat karena PHP3 yang benar-benar jelek sampai sekarang, tidak ada celah, tetapi ketika saya melihat semua RFC ini mereka menolak untuk 7, kesan saya hanya "WTF ?!". Pengguna melihat kekacauan dan bersedia untuk membersihkannya dengan cara yang kompatibel mundur dan mereka hanya mendapatkan "tidak". Bersihkan metode penamaan berantakan? Tetap nullbukan warga yang terlalu spesial? Tidak, tidak dibutuhkan. Tambahkan opsi untuk membuat semua hal sensitif huruf? Nah .. Dan kemudian, mengejutkan bahwa orang-orang beralih.
Marcin Orlowski
1
@MarcinOrlowski: Jenis pengembalian-nullable akan masuk akal. Saya telah mengikuti beberapa RFC's selama 7, dan saya setuju sebagian besar dengan mereka menolak banyak dari mereka. Perubahan yang mereka fokuskan tidak begitu banyak pada bahasa seperti pada runtime dan compiler. Untuk beberapa RFC yang ditolak, ada baiknya membaca melalui utas diskusi untuk memahami mengapa mereka memilih untuk tidak menerapkan perubahan tersebut (mis. Deprecating var). Apa yang disayangkan adalah bahwa sebagai gantinya, mereka menerima satu terlalu banyak yang bagus (misalnya, operator pesawat ruang angkasa)
Elias Van Ootegem
@EliasVanOotegem Jenis Nullable sekarang didukung dengan benar, karena 7.1 dirilis pada 1 Desember.
lonesomeday
@lonesomeday: Memang benar, menambahkan tautan + contoh dasar ke bagian bawah jawaban saya
Elias Van Ootegem
mmm ish tipe yang bagus untuk memperbarui jawaban ini! yaitu jenis serikat tampaknya tidak didukung dalam PHP 7.1
Dennis
67

Jenis Nullable tersedia di PHP 7.1.

Ini adalah contoh sintaks:

public function getName(): ?string
{
    return $this->name; // name can be null
}

PHP 7.1 sekarang GA dan Anda dapat memutakhirkan dari PHP 7.0 (hanya ada beberapa perubahan yang tidak kompatibel yang harus Anda periksa)

kacang
sumber
22
IMO itu adalah lelucon untuk memberikan deklarasi tipe pengembalian tanpa menerapkan "nullable". Jenis pengembalian tidak dapat digunakan sampai fitur "nullable" diimplementasikan.
joonas.fi
2
@ joonas.fi IMO yang diketik dengan ketat nilai-nilai pengembalian harus selalu dari jenis itu, pengembalian nol tidak berlaku untuk kontrak itu dan lebih baik melempar pengecualian yang memberikan lebih banyak makna dengan alasan nilai nol.
Steve Buzonas
8
@SteveBuzonas jika Anda mempertimbangkan metode getAgeInYears () pada objek yang mewakili Seseorang, bagaimana Anda memodelkan seseorang yang belum memberi tahu kami umurnya? Kembali nol? Kembali 0? Mengembalikan null secara semantik berarti "kita tidak tahu", sedangkan 0 semantik berarti "orang tersebut berusia 0 tahun". Karena itu saya berpendapat getAgeInYears ():? Int untuk menjadi desain terbaik. Melempar pengecualian harus disediakan untuk ... kasus luar biasa. Tidak mengetahui usia seseorang dalam kebanyakan sistem seharusnya tidak dianggap sebagai kasus luar biasa.
joonas.fi
@ joonas.fi sangat benar, dan itu adalah praktik umum. Namun, implementasi Anda sekarang perlu menyadari bahwa bidang tersebut dapat dibatalkan dan ditangani secara eksplisit. Yang sangat baik mungkin dilakukan x kecuali ketika nol yang bisa dengan mudah diimplementasikan dengan coba / tangkap. Lebih lanjut, jika seseorang benar-benar membutuhkan nilai dalam bidang nullable untuk melanjutkan eksekusi, pengecualian kemungkinan merupakan opsi yang lebih baik.
Steve Buzonas
Saya perhatikan bahwa sintaks ini menyebabkan PHPMD melempar banyak kesalahan. Semoga mereka segera memperbaikinya.
Tom Jowitt
0

Ini bekerja dengan semua jenis.
Contoh:

public function getOpportunity(): ?Opportunity
{
    return $this->opportunity;
}
Bayma Bruno
sumber