Saya sedang membangun perpustakaan ORM dengan menggunakan kembali dan kesederhanaan; semuanya berjalan baik-baik saja kecuali bahwa saya terjebak oleh batasan warisan yang bodoh. Harap pertimbangkan kode di bawah ini:
class BaseModel {
/*
* Return an instance of a Model from the database.
*/
static public function get (/* varargs */) {
// 1. Notice we want an instance of User
$class = get_class(parent); // value: bool(false)
$class = get_class(self); // value: bool(false)
$class = get_class(); // value: string(9) "BaseModel"
$class = __CLASS__; // value: string(9) "BaseModel"
// 2. Query the database with id
$row = get_row_from_db_as_array(func_get_args());
// 3. Return the filled instance
$obj = new $class();
$obj->data = $row;
return $obj;
}
}
class User extends BaseModel {
protected $table = 'users';
protected $fields = array('id', 'name');
protected $primary_keys = array('id');
}
class Section extends BaseModel {
// [...]
}
$my_user = User::get(3);
$my_user->name = 'Jean';
$other_user = User::get(24);
$other_user->name = 'Paul';
$my_user->save();
$other_user->save();
$my_section = Section::get('apropos');
$my_section->delete();
Jelas, ini bukan perilaku yang saya harapkan (meskipun perilaku sebenarnya juga masuk akal) .. Jadi pertanyaan saya adalah jika kalian tahu maksud untuk mendapatkan, di kelas orang tua, nama kelas anak.
php
inheritance
static-methods
saalaa
sumber
sumber
debug_backtrace()
.. Solusi yang mungkin adalah menggunakan pengikatan statis terlambat dari PHP 5.3 tetapi itu bukan kemungkinan dalam kasus saya. Terima kasih.Anda tidak perlu menunggu PHP 5.3 jika Anda dapat membayangkan cara untuk melakukan ini di luar konteks statis. Di php 5.2.9, dalam metode non-statis kelas induk, Anda dapat melakukan:
dan itu akan mengembalikan nama kelas anak sebagai string.
yaitu
ini akan menghasilkan:
manis ya?
sumber
$x = new Parent();
harus$x = new Child();
.Saya tahu pertanyaan ini benar-benar kuno, tetapi bagi mereka yang mencari solusi yang lebih praktis daripada menentukan properti di setiap kelas yang berisi nama kelas:
Anda dapat menggunakan
static
kata kunci untuk ini.Seperti yang dijelaskan dalam catatan kontributor ini di dokumentasi php
Contoh:
sumber
static()
adalah cara terbaik!Saya tahu postingan lamanya tetapi ingin membagikan solusi yang saya temukan.
Diuji dengan PHP 7+ Gunakan tautan fungsi
get_class()
Contoh di atas akan menampilkan:
sumber
Jika Anda tidak ingin menggunakan get_called_class (), Anda dapat menggunakan trik lain dari pengikatan statis terbaru (PHP 5.3+). Tetapi sisi negatifnya dalam hal ini Anda perlu memiliki metode getClass () di setiap model. Yang bukan masalah besar IMO.
sumber
Tampaknya Anda mungkin mencoba menggunakan pola tunggal sebagai pola pabrik. Saya akan merekomendasikan mengevaluasi keputusan desain Anda. Jika singleton benar-benar sesuai, saya juga akan merekomendasikan hanya menggunakan metode statis di mana warisan tidak diinginkan.
sumber
Mungkin ini tidak benar-benar menjawab pertanyaan, tetapi Anda bisa menambahkan parameter untuk get () menentukan tipe. maka Anda dapat menelepon
alih-alih memanggil User :: get (). Anda bisa menambahkan logika di BaseModel :: get () untuk memeriksa apakah metode get ada di subkelas dan kemudian memanggilnya jika Anda ingin mengizinkan subkelas untuk menimpanya.
Kalau tidak, satu-satunya cara yang bisa saya pikirkan dengan jelas adalah dengan menambahkan barang ke setiap subclass, yang bodoh:
Ini mungkin akan pecah jika Anda kemudian subclassed Pengguna, tapi saya kira Anda bisa mengganti
get_parent_class(__CLASS__)
dengan'BaseModel'
dalam kasus itusumber
Masalahnya bukan pada batasan bahasa, ini adalah desain Anda. Tidak peduli Anda memiliki kelas; metode statis lebih percaya pada desain prosedural daripada berorientasi objek. Anda juga menggunakan status global dalam beberapa bentuk. (Bagaimana cara
get_row_from_db_as_array()
mengetahui di mana menemukan database?) Dan akhirnya terlihat sangat sulit untuk menguji unit.Cobalah sesuatu di sepanjang garis ini.
sumber
Dua variasi jawaban Preston:
1)
2)
Catatan: memulai nama properti dengan _ adalah konvensi yang pada dasarnya berarti "saya tahu saya telah membuat ini publik, tetapi seharusnya benar-benar dilindungi, tetapi saya tidak dapat melakukannya dan mencapai tujuan saya"
sumber