Argumen Fungsi sebagai Konstanta Bit dalam PHP

Halo, Habr! Saya mempersembahkan kepada Anda terjemahan sebuah artikel oleh Liam Hammett : Argumen Bitmask Konstan dalam PHP .

PHP mengandung banyak fungsi standar yang menerima argumen boolean dalam bentuk konstanta bawaan dengan angka biner.
Nilai-nilai ini digabungkan menjadi satu argumen fungsi untuk mentransfer beberapa flag Boolean dengan cara yang ringkas.


Mereka mungkin bekerja sedikit berbeda dari yang dibayangkan dan digunakan banyak orang dalam kode mereka, jadi saya sarankan untuk mempertimbangkan cara kerjanya.




Bagaimana ini digunakan dalam fungsi PHP


PHP 7.2, termasuk ekstensi, mengandung lebih dari 1800+ konstanta yang telah ditentukan, dan beberapa dari mereka digunakan sebagai argumen untuk fungsi.
Salah satu contoh aplikasi semacam itu adalah opsi baru di PHP 7.3, yang memungkinkan Anda untuk melemparkan pengecualian dari fungsi json_encode untuk kesalahan konversi.


 json_encode($value, JSON_THROW_ON_ERROR); 

Menggunakan | (atau) operator bitwise, beberapa argumen fungsi berfungsi sebagai satu. Contoh dari dokumentasi PHP:


 json_encode($value, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE); 

Tidak ada sama sekali.


Tapi tetap saja, bagaimana cara kerjanya?


Menerapkan operasi bitwise untuk mencapai efek yang sama di dunia fungsi yang ditentukan pengguna sebenarnya sederhana, tetapi membutuhkan setidaknya pengetahuan dasar tentang bit apa dan bagaimana operasi bitwise bekerja dalam PHP.


Integer dapat ditentukan dalam desimal (basis 10), heksadesimal (basis 16), oktal (basis 8), atau sistem angka biner (basis 2). [...]
Untuk menulis dalam notasi biner, Anda harus meletakkan sebelum angka 0b.
- php.net

Contoh konstanta dengan rangkaian angka biner yang berbeda:


 const A = 0b0001; // 1 const B = 0b0010; // 2 const C = 0b0100; // 4 const D = 0b1000; // 8 

Perhatikan contoh dan urutan angka. Setiap nilai biner mewakili nilai dua kali lebih tinggi untuk setiap nol di akhir. Nol antara 0b dan 1 adalah opsional, tetapi dapat membantu menyelaraskan kode sumber.


Untungnya, kita perlu memahami bagaimana hanya dua operasi bitwise bekerja.


Bitwise ATAU


Jangan membingungkan operator | ( bitwise "OR" ) dengan operator yang sering digunakan || ( logis "ATAU" ), yang biasanya ditemukan di if else .
Bitwise "OR" adalah operasi biner yang tindakannya setara dengan menerapkan "OR" logis untuk setiap pasangan bit yang terletak di posisi yang sama dalam representasi biner dari operan. Dengan kata lain, jika kedua bit yang sesuai dari operan adalah 0, bit biner dari hasilnya adalah 0; jika setidaknya satu bit dari pasangan adalah 1, bit biner dari hasilnya adalah 1.


Contoh operasi bitwise "OR":


 const A = 0b0001; const B = 0b0010; const C = 0b0100; const D = 0b1000; A | B === 0b0011; A | C | D === 0b1101; 

Bitwise AND (AND)


Demikian pula, operator & ( bitwise AND ) tidak perlu bingung dengan operator && sering digunakan ( logis AND ).
Bitwise AND adalah operasi biner yang tindakannya setara dengan menerapkan logika AND untuk setiap pasangan bit yang terletak pada posisi yang sama dalam representasi biner dari operan. Dengan kata lain, jika kedua bit yang sesuai dari operan adalah 1, bit biner yang dihasilkan adalah 1; jika setidaknya satu bit dari pasangan adalah 0, bit biner yang dihasilkan adalah 0.


 const A = 0b0001; const B = 0b0010; const C = 0b0100; const D = 0b1000; const VALUE = 0b1010; A & B === 0b0000; //      A  B A & C & D === 0b0000; //      A, B  C A & A === 0b0001; //      A  A & VALUE === 0b0000; //      A  VALUE B & VALUE === 0b0010; //  1    B,    VALUE 

Bisakah angka memiliki boolean?


Perlu dicatat bahwa dalam PHP ada konsep " manipulasi tipe" ( type juggling ). Dalam bahasa non-pakar, ini artinya (PHP) akan secara otomatis mencoba mengonversi data dari satu jenis ke yang lain, jika perlu.
Jika Anda memahami bagaimana transformasi tersebut terjadi, maka ini bisa menjadi alat yang bermanfaat.
Misalnya, kita tahu bahwa angka 0 bertindak sebagai false ketika mengkonversi ke boolean, sedangkan semua angka lainnya akan true . Ingat bahwa nilai-nilai biner yang kita gunakan ini sebenarnya adalah bilangan bulat?


Untuk meringkas!


Sekarang kita bisa menggabungkan pengetahuan ini untuk membuat if konstruksi, kode di mana akan dieksekusi hanya jika hasil operasi bitwise antara angka bukan 0b0000 (atau 0 , yang dikonversi menjadi false ).


 const A = 0b0001; const B = 0b0010; function f($arg = 0) { if ($arg & A) { echo 'A'; } if ($arg & B) { echo 'B'; } } f(); // nothing f(A); // 'A' f(B); // 'B' f(A | B); // 'AB' 

Fungsi PHP json_encode (seperti json_encode ) bekerja dengan cara yang sama.


Apakah itu sepadan?


Mungkin Anda sekarang memiliki keinginan untuk menerapkan pendekatan ini untuk fungsi-fungsi dengan sejumlah besar argumen yang berpartisipasi dalam konstruksi bersyarat, tetapi ada sejumlah kelemahan dalam pemrosesan flag fungsi bitwise:


  • Anda tidak bisa melewatkan nilai non-boolean melalui argumen.
  • Tidak ada cara standar untuk mendokumentasikan argumen menggunakan docblock.
  • Anda kehilangan petunjuk umum dan dukungan untuk sebagian besar IDE.
  • Sebagai gantinya, Anda bisa meneruskan array asosiatif sebagai argumen untuk dapat mengatur nilai-nilai yang tidak nol (atau bahkan kelas ).
  • Ada alasan bagus mengapa Anda harus menghindari menggunakan "flag fungsi" yang logis sebagai argumen dan menggunakan fungsi atau metode lain untuk fungsi yang bisa berubah.

Namun, sekarang Anda tahu cara melakukannya.




Membaca daftar panjang definisi konstanta bisa sangat jelas dan sulit, jadi inilah fungsi bantu yang menyederhanakan definisi mereka.

Source: https://habr.com/ru/post/id423257/


All Articles