Ich baue eine ORM-Bibliothek mit Blick auf Wiederverwendung und Einfachheit. Alles geht gut, außer dass ich von einer dummen Erbschaftsbeschränkung festgefahren bin. Bitte beachten Sie den folgenden Code:
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();
Offensichtlich ist dies nicht das Verhalten, das ich erwartet hatte (obwohl das tatsächliche Verhalten auch Sinn macht). Meine Frage ist also, ob ihr ein Mittel kennt, um in der Elternklasse den Namen der Kinderklasse zu erhalten.
quelle
debug_backtrace()
. Eine mögliche Lösung wäre die Verwendung einer späten statischen Bindung aus PHP 5.3, aber das ist in meinem Fall nicht möglich. Danke dir.Sie müssen nicht auf PHP 5.3 warten, wenn Sie sich eine Möglichkeit vorstellen können, dies außerhalb eines statischen Kontexts zu tun. In PHP 5.2.9 können Sie in einer nicht statischen Methode der übergeordneten Klasse Folgendes tun:
und es wird der Name der untergeordneten Klasse als Zeichenfolge zurückgegeben.
dh
Dies wird Folgendes ausgeben:
süß huh?
quelle
$x = new Parent();
sollte sein$x = new Child();
.Ich weiß, dass diese Frage wirklich alt ist, aber für diejenigen, die nach einer praktischeren Lösung suchen, als eine Eigenschaft in jeder Klasse zu definieren, die den Klassennamen enthält:
Sie können hierfür das
static
Schlüsselwort verwenden.Wie in diesem Beitrag in der PHP-Dokumentation erläutert
Beispiel:
quelle
static()
ist der richtige Weg!Ich kenne den alten Beitrag, möchte aber die Lösung teilen, die ich gefunden habe.
Getestet mit PHP 7+ Mit der Funktion
get_class()
LinkDas obige Beispiel gibt Folgendes aus:
quelle
Falls Sie get_called_class () nicht verwenden möchten, können Sie andere Tricks der späten statischen Bindung (PHP 5.3+) verwenden. Der Nachteil in diesem Fall ist jedoch, dass in jedem Modell die Methode getClass () vorhanden sein muss. Welches ist keine große Sache IMO.
quelle
Möglicherweise versuchen Sie, ein Singleton-Muster als Factory-Muster zu verwenden. Ich würde empfehlen, Ihre Entwurfsentscheidungen zu bewerten. Wenn ein Singleton wirklich geeignet ist, würde ich auch empfehlen, nur statische Methoden zu verwenden, bei denen keine Vererbung erwünscht ist.
quelle
Vielleicht beantwortet dies die Frage nicht wirklich, aber Sie könnten einen Parameter hinzufügen, um () den Typ anzugeben. dann kannst du anrufen
anstatt User :: get () aufzurufen. Sie können in BaseModel :: get () Logik hinzufügen, um zu überprüfen, ob eine get-Methode in der Unterklasse vorhanden ist, und diese dann aufrufen, wenn Sie möchten, dass die Unterklasse sie überschreibt.
Ansonsten kann ich mir nur vorstellen, dass ich jeder Unterklasse etwas hinzufüge, was dumm ist:
Dies würde wahrscheinlich brechen , wenn Sie dann auf Benutzer subclassed, aber ich nehme an, Sie ersetzen könnte
get_parent_class(__CLASS__)
mit'BaseModel'
in diesem Fallquelle
Das Problem ist keine Sprachbeschränkung, sondern Ihr Design. Es ist egal, dass Sie Unterricht haben; Die statischen Methoden glauben eher an ein prozedurales als an ein objektorientiertes Design. Sie verwenden auch den globalen Status in irgendeiner Form. (Woher weiß man
get_row_from_db_as_array()
, wo man die Datenbank findet?) Und schließlich sieht es sehr schwierig aus, einen Unit-Test durchzuführen.Versuchen Sie etwas in diese Richtung.
quelle
Zwei Variationen von Prestons Antwort:
1)
2)
Hinweis: Das Starten eines Eigenschaftsnamens mit _ ist eine Konvention, die im Grunde bedeutet: "Ich weiß, dass ich dies öffentlich gemacht habe, aber es hätte wirklich geschützt werden müssen, aber ich konnte das nicht tun und mein Ziel erreichen."
quelle