Rumah > pembangunan bahagian belakang > tutorial php > Mewujudkan susunan dan koleksi yang ditaip dengan ketat dalam PHP

Mewujudkan susunan dan koleksi yang ditaip dengan ketat dalam PHP

Christopher Nolan
Lepaskan: 2025-02-10 11:20:11
asal
164 orang telah melayarinya

Mewujudkan susunan dan koleksi yang ditaip dengan ketat dalam PHP

Takeaways Key

    Php 5.6 memperkenalkan keupayaan untuk membuat tatasusunan yang ditaip menggunakan ... token, yang menunjukkan bahawa fungsi atau kaedah menerima panjang argumen yang berubah -ubah. Ciri ini boleh digabungkan dengan petunjuk jenis untuk memastikan bahawa hanya jenis objek tertentu yang diterima dalam array.
  • Satu batasan ciri ini ialah hanya satu array yang ditaip boleh ditakrifkan setiap kaedah. Untuk mengatasinya, tatasusunan yang ditaip boleh disuntik ke dalam kelas "pengumpulan", yang juga membolehkan jenis pulangan yang lebih spesifik daripada "array" pada kaedah GET.
  • Objek nilai boleh digunakan untuk pengesahan tersuai. Contohnya, objek nilai penarafan boleh dibuat dengan kekangan untuk memastikan penarafan sentiasa antara 0 dan 5. Ini memberikan pengesahan tambahan ahli pengumpulan individu tanpa perlu gelung ke atas setiap objek yang disuntik.
  • Arahan dan koleksi yang ditaip ketat mempunyai beberapa kelebihan. Mereka menyediakan pengesahan jenis yang mudah di satu tempat, memastikan nilai -nilai sentiasa disahkan apabila pembinaan, membolehkan penambahan logik tersuai setiap koleksi, dan mengurangkan kemungkinan pencampuran argumen dalam tandatangan kaedah.
  • Walaupun mungkin untuk menambah kaedah untuk memudahkan pengeditan kepada nilai -nilai koleksi dan objek nilai selepas pembinaan awal, lebih efisien untuk memastikan mereka tidak berubah dan menukarnya kepada jenis primitif mereka apabila perubahan perlu dibuat. Selepas membuat perubahan, koleksi atau objek nilai boleh dibina semula dengan nilai yang dikemas kini, yang kemudiannya akan disahkan lagi.
Jawatan ini pertama kali muncul di Sederhana dan diterbitkan semula di sini dengan kebenaran penulis. Kami menggalakkan anda untuk mengikuti Bert pada Sederhana dan memberinya beberapa suka di sana!

Salah satu ciri bahasa yang diumumkan kembali dalam Php 5.6 adalah penambahan ... token untuk menunjukkan bahawa fungsi atau kaedah menerima panjang argumen yang berubah -ubah.

Sesuatu yang jarang saya lihat disebutkan adalah mungkin untuk menggabungkan ciri ini dengan petunjuk jenis untuk membuat array yang ditaip pada dasarnya.

Contohnya, kita boleh mempunyai kelas filem dengan kaedah untuk menetapkan pelbagai tarikh udara yang hanya menerima objek DateTimeImmutable:

kita kini boleh lulus bilangan pembolehubah objek DateTimeImmutable yang berasingan kepada kaedah setairdates ():

<span><span><?php
</span></span><span>
</span><span><span>class Movie {  
</span></span><span>  <span>private $dates = [];
</span></span><span>
</span><span>  <span>public function setAirDates(\DateTimeImmutable ...$dates) {
</span></span><span>    <span>$this->dates = $dates;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>public function getAirDates() {
</span></span><span>    <span>return $this->dates;
</span></span><span>  <span>}
</span></span><span><span>}
</span></span>
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Jika kita lulus sesuatu yang lain daripada datetimeimmutable, rentetan misalnya, ralat maut akan dibuang:

<span><span><?php
</span></span><span>
</span><span><span>$movie = new Movie();
</span></span><span>
</span><span><span>$movie->setAirDates(
</span></span><span>  <span><span>\DateTimeImmutable</span>::createFromFormat('Y-m-d', '2017-01-28'),
</span></span><span>  <span><span>\DateTimeImmutable</span>::createFromFormat('Y-m-d', '2017-02-22')
</span></span><span><span>);
</span></span>
Salin selepas log masuk
Salin selepas log masuk

Jika kita sebaliknya sudah mempunyai pelbagai objek DateTimeImmutable yang kita mahu lulus ke setairdates (), kita dapat sekali lagi menggunakan ... token, tetapi kali ini untuk membongkar mereka:

Mewujudkan susunan dan koleksi yang ditaip dengan ketat dalam PHP

Jika array mengandungi nilai yang bukan jenis yang diharapkan, kita masih akan mendapat ralat maut yang disebut tadi.

Selain itu, kita boleh menggunakan jenis skalar dengan cara yang sama bermula dari Php 7. Sebagai contoh, kita boleh menambah kaedah untuk menetapkan senarai penilaian sebagai terapung pada kelas filem kami:

<span><span><?php
</span></span><span>
</span><span><span>class Movie {  
</span></span><span>  <span>private $dates = [];
</span></span><span>
</span><span>  <span>public function setAirDates(\DateTimeImmutable ...$dates) {
</span></span><span>    <span>$this->dates = $dates;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>public function getAirDates() {
</span></span><span>    <span>return $this->dates;
</span></span><span>  <span>}
</span></span><span><span>}
</span></span>
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Sekali lagi, ini memastikan bahawa harta penarafan akan sentiasa mengandungi terapung tanpa kita perlu gelung ke atas semua kandungan untuk mengesahkannya. Jadi sekarang kita dapat dengan mudah melakukan beberapa operasi matematik pada mereka dalam getaveragerating (), tanpa perlu bimbang tentang jenis tidak sah.

Masalah dengan jenis tatasusunan yang ditaip ini

Salah satu kelemahan menggunakan ciri ini sebagai tatasusunan yang ditaip ialah kita hanya boleh menentukan satu array sedemikian setiap kaedah. Katakan kami ingin mempunyai kelas filem yang menjangkakan senarai tarikh udara bersama -sama dengan senarai penarafan dalam pembina, bukannya menetapkannya kemudian melalui kaedah pilihan. Ini mustahil dengan kaedah yang digunakan di atas.

Satu lagi masalah ialah apabila menggunakan Php 7, jenis pulangan kaedah kami () masih perlu "array", yang sering terlalu generik.

Penyelesaian: Kelas Koleksi

Untuk memperbaiki kedua-dua masalah, kita hanya boleh menyuntik tatasusunan yang ditaip kami di dalam kelas yang dipanggil "koleksi". Ini juga meningkatkan pemisahan kebimbangan kita, kerana kita kini boleh memindahkan kaedah pengiraan untuk penarafan purata ke kelas pengumpulan yang berkaitan:

<span><span><?php
</span></span><span>
</span><span><span>$movie = new Movie();
</span></span><span>
</span><span><span>$movie->setAirDates(
</span></span><span>  <span><span>\DateTimeImmutable</span>::createFromFormat('Y-m-d', '2017-01-28'),
</span></span><span>  <span><span>\DateTimeImmutable</span>::createFromFormat('Y-m-d', '2017-02-22')
</span></span><span><span>);
</span></span>
Salin selepas log masuk
Salin selepas log masuk

Perhatikan bagaimana kami masih menggunakan senarai argumen yang ditaip dengan panjang pembolehubah dalam pembina kami, yang menjimatkan masalah untuk melengkapkan setiap penarafan untuk memeriksa jenisnya.

Jika kita mahu keupayaan untuk menggunakan kelas koleksi ini dalam gelung foreach, kita hanya perlu melaksanakan antara muka IteratorAggregate:

<span><span><?php
</span></span><span>
</span><span><span>$dates = [
</span></span><span>  <span><span>\DateTimeImmutable</span>::createFromFormat('Y-m-d', '2017-01-28'),
</span></span><span>  <span><span>\DateTimeImmutable</span>::createFromFormat('Y-m-d', '2017-02-22'),
</span></span><span><span>];
</span></span><span>
</span><span><span>$movie = new Movie();
</span></span><span><span>$movie->setAirDates(...$dates);
</span></span>
Salin selepas log masuk

bergerak, kami juga boleh membuat koleksi untuk senarai tarikh udara kami:

<span><span><?php
</span></span><span>
</span><span><span>declare(strict_types=1);
</span></span><span>
</span><span><span>class Movie {
</span></span><span>  <span>private $dates = [];
</span></span><span>  <span>private $ratings = [];
</span></span><span>
</span><span>  <span>public function setAirDates(\DateTimeImmutable ...$dates) { /* ... */ }
</span></span><span>  <span>public function getAirDates() : array { /* ... */ }
</span></span><span>
</span><span>  <span>public function setRatings(float ...$ratings) {
</span></span><span>    <span>$this->ratings = $ratings;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>public function getAverageRating() : float {
</span></span><span>    <span>if (empty($this->ratings)) {
</span></span><span>      <span>return 0;
</span></span><span>    <span>}
</span></span><span>
</span><span>    <span>$total = 0;
</span></span><span>
</span><span>    <span>foreach ($this->ratings as $rating) {
</span></span><span>      <span>$total += $rating;
</span></span><span>    <span>}
</span></span><span>
</span><span>    <span>return $total / count($this->ratings);
</span></span><span>  <span>}
</span></span><span><span>}
</span></span>
Salin selepas log masuk

Meletakkan semua kepingan teka -teki bersama -sama dalam kelas filem, kini kita boleh menyuntik dua koleksi yang ditaip secara berasingan di pembina kami. Di samping itu, kami dapat menentukan jenis pulangan yang lebih spesifik daripada "array" pada kaedah GET kami:

<span><span><?php
</span></span><span>
</span><span><span>declare(strict_types=1);
</span></span><span>
</span><span><span>class Ratings {
</span></span><span>  <span>private $ratings;
</span></span><span>
</span><span>  <span>public function __construct(float ...$ratings) {
</span></span><span>    <span>$this->ratings = $ratings;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>public function getAverage() : float {
</span></span><span>    <span>if (empty($this->ratings)) {
</span></span><span>      <span>return 0;
</span></span><span>    <span>}
</span></span><span>
</span><span>    <span>$total = 0;
</span></span><span>
</span><span>    <span>foreach ($this->ratings as $rating) {
</span></span><span>      <span>$total += $rating;
</span></span><span>    <span>}
</span></span><span>
</span><span>    <span>return $total / count($this->ratings);
</span></span><span>  <span>}
</span></span><span><span>}
</span></span>
Salin selepas log masuk

menggunakan objek nilai untuk pengesahan tersuai

Jika kami mahu menambah pengesahan tambahan kepada penarafan kami, kami masih boleh pergi satu langkah lagi, dan menentukan objek nilai penarafan dengan beberapa kekangan tersuai. Sebagai contoh, penarafan boleh dibatasi antara 0 dan 5:

<span><span><?php
</span></span><span>
</span><span><span>declare(strict_types=1);
</span></span><span>
</span><span><span>class Ratings implements IteratorAggregate {
</span></span><span>  <span>private $ratings;
</span></span><span>
</span><span>  <span>public function __construct(float ...$ratings) {
</span></span><span>    <span>$this->ratings = $ratings;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>public function getAverage() : float { /* ... */ }
</span></span><span>
</span><span>  <span>public function getIterator() {
</span></span><span>     <span>return new ArrayIterator($this->ratings);
</span></span><span>  <span>}
</span></span><span><span>}
</span></span>
Salin selepas log masuk

Kembali dalam kelas pengumpulan penilaian kami, kami hanya perlu melakukan perubahan kecil untuk menggunakan objek nilai ini dan bukannya terapung:

<span><span><?php
</span></span><span>
</span><span><span>class AirDates implements IteratorAggregate {
</span></span><span>  <span>private $dates;
</span></span><span>
</span><span>  <span>public function __construct(\DateTimeImmutable ...$dates) {
</span></span><span>    <span>$this->dates = $dates;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>public function getIterator() {
</span></span><span>     <span>return new ArrayIterator($this->airdates);
</span></span><span>  <span>}
</span></span><span><span>}
</span></span>
Salin selepas log masuk

Dengan cara ini, kami mendapat pengesahan tambahan ahli pengumpulan individu, masih tanpa perlu melayari setiap objek yang disuntik.

Kelebihan

menaip kelas koleksi dan objek nilai yang berasingan mungkin kelihatan seperti banyak kerja, tetapi mereka mempunyai beberapa kelebihan berbanding array generik dan nilai skalar:

  • Pengesahan jenis mudah di satu tempat. Kami tidak perlu melayari secara manual di atas array untuk mengesahkan jenis ahli pengumpulan kami;

  • Di mana sahaja kita menggunakan koleksi dan objek nilai ini dalam permohonan kami, kami tahu bahawa nilai mereka sentiasa disahkan apabila pembinaan. Sebagai contoh, apa -apa penarafan akan sentiasa antara 0 dan 5;
  • kita boleh dengan mudah menambah logik tersuai setiap koleksi dan/atau objek nilai. Contohnya kaedah getaverage (), yang boleh kita gunakan semula sepanjang aplikasi kami;
  • Kami mendapat kemungkinan untuk menyuntik pelbagai senarai yang ditaip dalam satu fungsi atau kaedah, yang tidak dapat kami lakukan menggunakan ... token tanpa menyuntik nilai dalam kelas pengumpulan terlebih dahulu;
  • Terdapat kemungkinan pengurangan argumen pencampuran dalam tandatangan kaedah. Sebagai contoh, apabila kita mahu menyuntik kedua -dua senarai penilaian dan senarai tarikh udara, kedua -duanya dapat dengan mudah bercampur secara tidak sengaja apabila pembinaan apabila menggunakan array generik;
  • bagaimana dengan suntingan?

Sekarang anda mungkin tertanya -tanya bagaimana anda boleh membuat perubahan pada nilai koleksi dan objek nilai anda selepas pembinaan awal.

Walaupun kita dapat menambah kaedah untuk memudahkan pengeditan, ini dengan cepat akan menjadi rumit kerana kita perlu menduplikasi kebanyakan kaedah pada setiap koleksi untuk mengekalkan kelebihan jenis petunjuk. Sebagai contoh, kaedah Tambah () pada penarafan hanya boleh menerima objek penarafan, manakala kaedah Tambah () pada Airdates hanya boleh menerima objek DateTimeImmutable. Ini menjadikan interfacing dan/atau menggunakan semula kaedah ini sangat keras.

Sebaliknya, kita hanya dapat menyimpan koleksi dan nilai objek kita tidak berubah, dan menukarnya kepada jenis primitif mereka apabila kita perlu membuat perubahan. Selepas kami selesai membuat perubahan, kami dapat membina semula apa-apa koleksi yang diperlukan atau objek nilai dengan nilai yang dikemas kini. Setelah (semula) pembinaan semua jenis akan disahkan semula, bersama-sama dengan sebarang pengesahan tambahan yang mungkin kami tentukan.

Contohnya, kita boleh menambah kaedah ToArray () mudah untuk koleksi kami, dan membuat perubahan seperti ini:

Dengan cara ini kita juga boleh menggunakan semula fungsi array sedia ada seperti array_filter ().

<span><span><?php
</span></span><span>
</span><span><span>class Movie {  
</span></span><span>  <span>private $dates = [];
</span></span><span>
</span><span>  <span>public function setAirDates(\DateTimeImmutable ...$dates) {
</span></span><span>    <span>$this->dates = $dates;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>public function getAirDates() {
</span></span><span>    <span>return $this->dates;
</span></span><span>  <span>}
</span></span><span><span>}
</span></span>
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Jika kita benar-benar perlu melakukan pengeditan pada objek pengumpulan sendiri, kita boleh menambah kaedah yang diperlukan secara perlu di mana sahaja mereka diperlukan. Tetapi perlu diingat bahawa kebanyakan mereka juga perlu melakukan pengesahan jenis hujah yang diberikan, jadi sukar untuk menggunakan semula mereka di semua kelas koleksi yang berbeza.

menggunakan semula kaedah generik

Seperti yang anda perhatikan, kami masih mendapat beberapa duplikasi kod di seluruh kelas pengumpulan kami dengan melaksanakan kedua -dua Toarray () dan getIterator () pada mereka semua. Nasib baik kaedah ini cukup generik untuk berpindah ke kelas induk generik, kerana kedua -duanya hanya mengembalikan array yang disuntik:

semua yang kita akan ditinggalkan dalam kelas pengumpulan kami akan menjadi pengesahan jenis dalam pembina, dan mana -mana logik tambahan pilihan yang khusus untuk koleksi itu, seperti ini:

<span><span><?php
</span></span><span>
</span><span><span>class Movie {  
</span></span><span>  <span>private $dates = [];
</span></span><span>
</span><span>  <span>public function setAirDates(\DateTimeImmutable ...$dates) {
</span></span><span>    <span>$this->dates = $dates;
</span></span><span>  <span>}
</span></span><span>
</span><span>  <span>public function getAirDates() {
</span></span><span>    <span>return $this->dates;
</span></span><span>  <span>}
</span></span><span><span>}
</span></span>
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Secara pilihan kita boleh membuat final koleksi kami, untuk mengelakkan mana -mana kelas kanak -kanak daripada mengacaukan dengan nilai harta dengan cara yang boleh membatalkan pengesahan jenis kami.

Kesimpulan

Walaupun masih jauh dari sempurna, ia semakin mudah untuk bekerja dengan pengesahan jenis dalam koleksi dan objek nilai dengan siaran terkini php.

Sebaik-baiknya kita akan mendapat beberapa bentuk generik dalam versi PHP masa depan untuk memudahkan penciptaan kelas pengumpulan semula yang boleh digunakan semula.

Ciri yang akan meningkatkan penggunaan objek nilai akan menjadi keupayaan untuk membuang objek kepada jenis primitif yang berbeza, sebagai tambahan kepada rentetan. Ini dapat dengan mudah dilaksanakan dengan menambahkan kaedah sihir tambahan yang setanding dengan __toString (), seperti __toint (), __tofloat (), dan lain -lain

Nasib baik terdapat beberapa RFC yang sedang berjalan untuk melaksanakan kedua -dua ciri dalam versi kemudian, jadi jari melintasi! ?

  • Generik: https://wiki.php.net/rfc/generics

  • array generik: https://wiki.php.net/rfc/generic-arrays

  • objek pemutus ke skalar: https://wiki.php.net/rfc/class_casting_to_scalar


Jika anda mendapati tutorial ini berguna, sila lawati jawatan asal pada medium dan berikan beberapa ❤️. Sekiranya anda mempunyai maklum balas, soalan, atau komen, sila tinggalkannya di bawah atau sebagai respons pada jawatan asal.

Soalan Lazim (Soalan Lazim) Mengenai Mewujudkan Array dan Koleksi yang Diketik Katil dalam PHP

Apakah faedah menggunakan tatasusunan yang ditaip ketat dalam php?

Array yang ditaip ketat dalam PHP menyediakan cara untuk memastikan semua elemen dalam array adalah jenis tertentu. Ini boleh menjadi sangat berguna dalam aplikasi yang lebih besar dan lebih kompleks di mana konsistensi data adalah penting. Dengan menguatkuasakan jenis tertentu untuk semua elemen dalam array, anda boleh menghalang potensi bug dan kesilapan yang mungkin berlaku disebabkan oleh jenis data yang tidak dijangka. Ia juga menjadikan kod anda lebih mudah diramalkan dan lebih mudah untuk debug, kerana anda selalu mengetahui jenis data yang anda kerjakan. tidak menyokong array yang ditaip secara asli. Walau bagaimanapun, anda boleh membuat kelas yang menguatkuasakan pemeriksaan jenis pada unsur -unsur yang ditambahkan pada array. Kelas ini akan mempunyai kaedah untuk menambah dan mengambil unsur -unsur, dan kaedah ini akan memeriksa jenis elemen sebelum melakukan operasi. Jika jenis elemen tidak sepadan dengan jenis yang diharapkan, ralat akan dilemparkan. Anda boleh menentukan bahawa fungsi atau kaedah mengharapkan array sebagai hujah dengan menambahkan "array" sebelum nama argumen dalam perisytiharan fungsi atau kaedah. Walau bagaimanapun, ini hanya memastikan bahawa hujah adalah array, bukan bahawa semua elemen dalam array adalah jenis tertentu.

Apakah perbezaan antara tatasusunan yang ditaip dan ketat? Dalam array yang ketat, semua elemen mestilah jenis tertentu. Sekiranya anda cuba menambah elemen jenis yang berbeza ke array yang ketat, ralat akan dilemparkan. PHP dengan menggunakan "mengisytiharkan (strict_types = 1);" Arahan pada permulaan fail PHP anda. Ini akan menguatkuasakan pemeriksaan jenis ketat untuk semua panggilan fungsi dan penyataan pulangan dalam fail. objek dalam PHP dengan membuat kelas yang menguatkuasakan pemeriksaan jenis pada objek yang ditambahkan pada array. Kelas akan mempunyai kaedah untuk menambah dan mengambil objek, dan kaedah ini akan memeriksa jenis objek sebelum melakukan operasi. Keterbatasan utama tatasusunan ketat dalam PHP ialah mereka memerlukan kod tambahan untuk dilaksanakan, kerana PHP tidak menyokongnya secara asli. Ini boleh menjadikan kod anda lebih kompleks dan lebih sukar untuk dikekalkan. Di samping itu, tatasusunan yang ditaip ketat boleh kurang fleksibel daripada tatasusunan yang ditaip secara longgar, kerana mereka tidak membenarkan unsur -unsur jenis yang berbeza. Anda boleh menggunakan jenis mengisyaratkan dengan tatasusunan multidimensi dalam PHP. Walau bagaimanapun, jenis PHP yang mengisyaratkan hanya memastikan hujah adalah array, bukannya semua elemen dalam array (atau sub-arrays) adalah jenis tertentu. PHP?

Apabila menggunakan tatasusunan yang ditaip ketat di PHP, anda boleh mengendalikan kesilapan dengan menggunakan blok percubaan. Jika ralat berlaku apabila menambah elemen ke array (contohnya, jika elemen adalah jenis yang salah), pengecualian akan dibuang. Anda boleh menangkap pengecualian ini dan mengendalikannya dengan sewajarnya. fungsi. Walau bagaimanapun, anda perlu berhati -hati, kerana fungsi ini tidak menguatkuasakan pemeriksaan jenis. Jika anda menggunakan fungsi yang mengubah array dan menambah elemen jenis yang salah, ini boleh menyebabkan kesilapan.

Atas ialah kandungan terperinci Mewujudkan susunan dan koleksi yang ditaip dengan ketat dalam PHP. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan