Saya berdebat dengan seorang kolega tentang penggunaan yang benar (jika ada) trigger_error
dalam konteks metode sihir . Pertama, saya pikir itu trigger_error
harus dihindari kecuali untuk kasus yang satu ini.
Katakanlah kita memiliki kelas dengan satu metode foo()
class A {
public function foo() {
echo 'bar';
}
}
Sekarang katakan kita ingin memberikan antarmuka yang sama persis tetapi menggunakan metode ajaib untuk menangkap semua panggilan metode
class B {
public function __call($method, $args) {
switch (strtolower($method)) {
case 'foo':
echo 'bar';
break;
}
}
}
$a = new A;
$b = new B;
$a->foo(); //bar
$b->foo(); //bar
Kedua kelas sama dalam cara mereka merespons foo()
tetapi berbeda ketika memanggil metode yang tidak valid.
$a->doesntexist(); //Error
$b->doesntexist(); //Does nothing
Argumen saya adalah bahwa metode ajaib harus memanggil trigger_error
ketika metode yang tidak diketahui ditangkap
class B {
public function __call($method, $args) {
switch (strtolower($method)) {
case 'foo':
echo 'bar';
break;
default:
$class = get_class($this);
$trace = debug_backtrace();
$file = $trace[0]['file'];
$line = $trace[0]['line'];
trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
break;
}
}
}
Sehingga kedua kelas berperilaku (hampir) identik
$a->badMethod(); //Call to undefined method A::badMethod() in [..] on line 28
$b->badMethod(); //Call to undefined method B::badMethod() in [..] on line 32
Kasing saya adalah implementasi ActiveRecord. Saya menggunakan __call
untuk menangkap dan menangani metode yang pada dasarnya melakukan hal yang sama tetapi memiliki pengubah seperti Distinct
atau Ignore
, misalnya
selectDistinct()
selectDistinctColumn($column, ..)
selectAll()
selectOne()
select()
atau
insert()
replace()
insertIgnore()
replaceIgnore()
Metode seperti where()
, from()
, groupBy()
, dll keras-kode.
Argumen saya disorot ketika Anda secara tidak sengaja menelepon insret()
. Jika implementasi rekaman aktif saya hardcoded semua metode maka itu akan menjadi kesalahan.
Seperti halnya abstraksi yang bagus, pengguna harus tidak mengetahui detail implementasi dan hanya mengandalkan antarmuka. Mengapa implementasi yang menggunakan metode sihir berperilaku berbeda? Keduanya harus menjadi kesalahan.
sumber
4.something
?__call()
untuk melakukan routing dinamis, apakah benar-benar tidak masuk akal untuk mengharapkan bahwa di suatu tempat di jalur seseorang mungkin ingin menangani kasus di mana itu gagal? Bagaimanapun, ini berputar-putar, jadi ini akan menjadi komentar terakhir saya. Lakukan apa yang Anda mau, pada akhirnya hari ini datang ke panggilan penilaian: Dukungan yang lebih baik vs konsistensi. Kedua metode akan menghasilkan efek yang sama pada aplikasi jika tidak ada penanganan khusus.Saya akan membuang pendapat saya di luar sana, tetapi jika Anda menggunakan di
trigger_error
mana saja, maka Anda melakukan sesuatu yang salah. Pengecualian adalah caranya.Keuntungan pengecualian:
Mengatasi masalah Anda, memanggil metode yang tidak ada mungkin merupakan kemungkinan yang valid . Ini sepenuhnya tergantung pada konteks kode yang Anda tulis, tetapi ada beberapa kasus di mana ini mungkin terjadi. Mengatasi kasus penggunaan yang tepat, beberapa server database mungkin mengizinkan beberapa fungsi yang tidak dimiliki orang lain. Menggunakan
try
/catch
dan pengecualian dalam__call()
vs. fungsi untuk memeriksa kapabilitas adalah argumen yang berbeda sama sekali.Satu-satunya use case yang dapat saya pikirkan untuk digunakan
trigger_error
adalah untukE_USER_WARNING
atau lebih rendah. MemicuE_USER_ERROR
meskipun selalu merupakan kesalahan menurut pendapat saya.sumber
trigger_error
dalam konteks __call atau __callStatic meniru perilaku default bahasaNoMethodError
yang bisa Anda tangkap jika diinginkan. Kesalahan adalah kesalahan besar dalam PHP menurut pendapat pribadi saya. Hanya karena inti menggunakan metode yang rusak untuk melaporkan kesalahan tidak berarti kode Anda sendiri harus.Kesalahan PHP standar harus dianggap usang. PHP menyediakan ErrorException kelas bawaan untuk mengubah kesalahan, peringatan, dan pemberitahuan menjadi pengecualian dengan jejak stack yang tepat dan tepat. Anda menggunakannya seperti ini:
Dengan menggunakan itu, pertanyaan ini menjadi diperdebatkan. Kesalahan bawaan sekarang meningkatkan pengecualian dan kode Anda juga harus demikian.
sumber
E_NOTICE
menjadi pengecualian. Itu akan buruk.IMO, ini adalah kasus penggunaan yang valid untuk
trigger_error
:Dengan menggunakan strategi ini, Anda mendapatkan
$errcontext
parameter jika Anda melakukannya$exception->getTrace()
di dalam fungsihandleException
. Ini sangat berguna untuk keperluan debugging tertentu.Sayangnya, ini hanya berfungsi jika Anda menggunakan
trigger_error
langsung dari konteks Anda, yang berarti Anda tidak dapat menggunakan fungsi pembungkus / metode untuk aliastrigger_error
fungsi (jadi Anda tidak dapat melakukan sesuatu sepertifunction debug($code, $message) { return trigger_error($message, $code); }
jika Anda ingin data konteks dalam jejak Anda).Saya telah mencari alternatif yang lebih baik, tetapi sejauh ini saya belum menemukan.
sumber