Je construis une bibliothèque ORM avec la réutilisation et la simplicité à l'esprit; tout va bien sauf que je suis coincé par une stupide limitation d'héritage. Veuillez considérer le code ci-dessous:
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();
Évidemment, ce n'est pas le comportement auquel je m'attendais (bien que le comportement réel ait également du sens). Ma question est donc de savoir si vous connaissez un moyen d'obtenir, dans la classe parent, le nom de la classe enfant.
la source
debug_backtrace()
.. Une solution possible serait d'utiliser la liaison statique tardive de PHP 5.3 mais ce n'est pas une possibilité dans mon cas. Je vous remercie.Vous n'avez pas besoin d'attendre PHP 5.3 si vous êtes capable de concevoir un moyen de le faire en dehors d'un contexte statique. En php 5.2.9, dans une méthode non statique de la classe parente, vous pouvez faire:
et il renverra le nom de la classe enfant sous forme de chaîne.
c'est à dire
cela produira:
doux hein?
la source
$x = new Parent();
devrait être$x = new Child();
.Je sais que cette question est vraiment ancienne, mais pour ceux qui recherchent une solution plus pratique que de définir une propriété dans chaque classe contenant le nom de la classe:
Vous pouvez utiliser le
static
mot - clé pour cela.Comme expliqué dans cette note du contributeur dans la documentation php
Exemple:
la source
static()
est la voie à suivre!Je connais son ancien poste mais je souhaite partager la solution que j'ai trouvée.
Testé avec PHP 7+ Utiliser le lien de fonction
get_class()
L'exemple ci-dessus affichera:
la source
Si vous ne souhaitez pas utiliser get_called_class (), vous pouvez utiliser d'autres astuces de liaison statique tardive (PHP 5.3+). Mais l'inconvénient dans ce cas, vous devez avoir la méthode getClass () dans chaque modèle. Ce n'est pas un gros problème IMO.
la source
Il semble que vous essayez d'utiliser un modèle singleton comme modèle d'usine. Je recommanderais d'évaluer vos décisions de conception. Si un singleton est vraiment approprié, je recommanderais également d'utiliser uniquement des méthodes statiques où l'héritage n'est pas souhaité.
la source
Peut-être que cela ne répond pas réellement à la question, mais vous pouvez ajouter un paramètre pour get () spécifiant le type. alors tu peux appeler
au lieu d'appeler User :: get (). Vous pouvez ajouter une logique dans BaseModel :: get () pour vérifier si une méthode get existe dans la sous-classe, puis l'appeler si vous souhaitez autoriser la sous-classe à la remplacer.
Sinon, la seule façon dont je peux penser est évidemment d'ajouter des éléments à chaque sous-classe, ce qui est stupide:
Cela se casserait probablement si vous sous-classiez l'utilisateur, mais je suppose que vous pourriez remplacer
get_parent_class(__CLASS__)
par'BaseModel'
dans ce casla source
Le problème n'est pas une limitation de la langue, c'est votre conception. Peu importe que vous ayez des cours; les méthodes statiques démentent une conception procédurale plutôt qu'orientée objet. Vous utilisez également l'état global sous une forme ou une autre. (Comment
get_row_from_db_as_array()
savoir où trouver la base de données?) Et enfin, il semble très difficile de tester unitaire.Essayez quelque chose de ce genre.
la source
Deux variantes de la réponse de Preston:
1)
2)
Remarque: commencer un nom de propriété par _ est une convention qui signifie essentiellement "Je sais que j'ai rendu ce contenu public, mais il aurait vraiment dû être protégé, mais je n'ai pas pu le faire et atteindre mon objectif"
la source