web-dev-qa-db-fra.com

Accès aux modèles CodeIgniter dans d'autres modèles

Auparavant, dans un modèle CodeIgniter, vous ne pouviez pas accéder à un autre modèle.

$this->load->model('bar');
$this->bar->something();

Est-ce toujours valable ou l'ont-ils changé?

38
Click Upvote

Ce sont des réponses TRÈS longues pour une question simple.

Réponse courte: Ceci est maintenant entièrement supporté. Cross-load away si vous en avez envie!

69
Phil Sturgeon

Je suis fermement en désaccord avec l'idée qu'un "modèle" ne devrait encapsuler qu'une table de base de données avec de simples opérations CRUD. Comme indiqué dans l'article de Wikipedia:

http://fr.wikipedia.org/wiki/contrôleur_du_modèle #As_a_design_pattern

... cette couche d'application est censée faire plus que simplement agir comme une seule abstraction de table de base de données. Pensez à la signification du mot "contrôleur" - il devrait agir davantage en tant que réalisateur plutôt que d'être l'application entière en soi. Un "modèle" est un lieu de logique métier. La plupart des applications à grande échelle conservent en fait une grande partie de leur logique métier dans la base de données elle-même (sous la forme de déclencheurs, de procédures stockées, de clés étrangères, etc.).

Je pense que l'incompréhension de ce qu'est un "modèle" est en partie due au même (trop) battage médiatique de "MVC", sans que cela entraîne une grande compréhension des concepts eux-mêmes. Un peu comme "AJAX" est vide, ou encore plus facile, "Web 2.0". Pour le meilleur ou pour le pire, beaucoup d’enfants de scripts ont sauté dans le wagon MVC, et comme les exemples simples et les scénarios ne font pas beaucoup plus que de vous demander de mettre votre code de base de données dans le "modèle", la mauvaise utilisation de cette couche seule une abstraction de base de données est devenue courante. Maintenant, vous lisez sur Internet des publications appelant "impure", "sale", "hack" pour mettre n'importe quelle logique métier dans un modèle. C'est faux. Mal informé.

L’exemple le plus simple est de penser aux clés étrangères: même si vous voulez seulement que votre "modèle" soit un modèle database, si vous voulez être "pur", "correct" ou ce que vous avez, vous devriez vraiment l'être. appliquer l'intégrité référentielle dans celle-ci. En raison du manque de prise en charge réelle des clés étrangères dans MySQL depuis de nombreuses années, les applications Web ont évolué sans que personne se soucie de l'intégrité référentielle. Convient au style de vie script kiddie, je suppose. Quoi qu'il en soit, même pour avoir une vue simplifiée du modèle afin de conserver la validité de la clé étrangère, un modèle doit alors fonctionner avec les autres (ou, surtout si un cadre tel que CodeIgniter ne vous permet pas de le faire, vous devez écrire des requêtes à d'autres tables, parfois en dupliquant des requêtes ailleurs - C’est mauvais style).

Par conséquent, j'estime qu'il s'agit d'une lacune de CodeIgniter. Je comprends que ce n’est peut-être pas une solution facile, mais c’est certainement un oubli décevant.

Donc, ce que j'ai fait était de prendre l'exemple de code ci-dessus et de le résumer en une aide, de sorte que je dispose maintenant d'une fonction qui fonctionne presque à l'identique de la fonctionnalité normale $ this-> load-> model (). La voici (placez-la dans un assistant automatiquement chargé et vous pourrez l'utiliser dans n'importe quel modèle):


   /**
    *
    * Allow models to use other models
    *
    * This is a substitute for the inability to load models
    * inside of other models in CodeIgniter.  Call it like
    * this:
    *
    * $salaries = model_load_model('salary');
    * ...
    * $salary = $salaries->get_salary($employee_id);
    *
    * @param string $model_name The name of the model that is to be loaded
    *
    * @return object The requested model object
    *
    */
   function model_load_model($model_name)
   {
      $CI =& get_instance();
      $CI->load->model($model_name);
      return $CI->$model_name;
   }
39
oribani

C'est possible, mais pas idéal et considéré comme mauvais et plus pour une "solution rapide" que pour une implémentation idéale ou pure.

class Location extends Model{
      public function get($ID){
                // Get main CI object handle and load model
                $CI =& get_instance();
                $CI->load->model('LocationType');
                // Call new model functions using handle to main CI object
                $CI->LocationType->setID($result->LocationTypeID);
                $CI->LocationType->setTitle($result->TypeTitle);
                $this->_locationType = $CI->LocationType;
                //Other Stuff
    }
}

Chaque fois que vous utilisez l'objet CI principal comme celui-ci, c'est probablement une mauvaise idée. Essayez de repenser votre mise en page et transmettez simplement les données de/vers votre contrôleur aux modèles.

http://codeigniter.com/forums/viewthread/69833/

8
MECU

Vous pouvez charger des modèles à partir de modèles comme le dit Phil Sturgeon, mais vous devez faire attention aux dépendances si vous chargez les modèles dans le constructeur du modèle: si le modèle A utilise le modèle B et que le modèle B utilise le modèle A, lorsque vous essayez de charger un ou les modèles. autre, vous allez dans une boucle infinie.

6
Dave Meybohm

Dans des situations comme celle-ci dans Code Igniter, je préfère l'une des deux possibilités suivantes:

1) Avoir l'attribut du modèle et le setter comme ceci:

class X extends Model {
  var $Y_model;
  public function setY($Y) {
    $this->Y_model = $Y;
  }

  public function doItRightNow($a,$b) {
    $list = $this->Y_model->getSomeList($a,$b);
    // ...
  }
  // ...
}


Et utilisez ensuite ce programme de configuration avant les autres méthodes pour donner une instance d’un autre modèle afin qu’il puisse être utilisé par des méthodes.

$this->load->model('X');
$this->load->model('Y');
$this->X->setY($this->Y);
$this->X->doItRightNow($something,$somethingElse);



2) Avoir un paramètre dans la méthode par lequel je donnerai une autre instance de modèle du contrôleur.

class X extends Model {
  public function doItRightNow($a,$b,$Y_model) {
    $list = $Y_model->getSomeList($a,$b);
    // ...
  }
  // ...
}

Et utilisez-le comme ceci:

  $this->load->model('X');
  $this->load->model('Y');
  $this->X->doItRightNow($something,$somethingElse,$this->Y);



Je pense que ce sont des possibilités plus propres.
La méthode à utiliser dépend du nombre de méthodes nécessaires pour accéder à un autre modèle. S'il y en a un ou deux, il serait peut-être préférable de le définir comme paramètre de méthode. Si plus - je pense qu'il est préférable d'avoir un attribut de classe et un setter.
Et de manière élégante, vous pouvez attribuer un modèle ou un autre en fonction de certaines conditions - s’ils implémentent partiellement la même interface avec le même type de données renvoyées (c’est rarement utile, mais cela peut parfois être le cas).

1
Zbyszek

Je pense qu'il est généralement préférable que les bibliothèques d'écriture accèdent aux modèles, puis les incluent dans votre modèle si besoin est. 

Par exemple, si vous devez vérifier si une personne est autorisée à exécuter une action CRUD donnée, vous pouvez inclure n'importe quelle bibliothèque d'authentification que vous utilisez (elle est probablement incluse automatiquement dans la plupart des cas). Vous ne voudriez pas nécessairement accéder directement au modèle - il semble simplement sale et inapproprié.

Je pense que la méthode préférée consiste à effectuer ce que vous devez faire dans votre contrôleur et à transférer les résultats des méthodes d'un modèle, le cas échéant, aux méthodes de votre autre modèle.

Quoi qu’il en soit, je ne vois pas pourquoi il ne serait pas possible d’inclure un modèle dans un autre. Je ne pense pas que vous puissiez le faire avec la syntaxe que vous montrez, cependant. Vous auriez à le faire d'une autre manière alambiquée. Dans tous les cas, OMI, il est déconseillé d’inclure un modèle directement dans un autre modèle. 

0
KyleFarris

Dans CI 2.0, vous pouvez simplement appeler un modèle directement depuis un autre.

0
phirschybar