38 votes

Accéder aux modèles CodeIgniter dans d'autres modèles

Avant, il était impossible d'accéder à un autre modèle dans un modèle CodeIgniter.

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

Est-ce que c'est toujours valable, ou est-ce qu'ils l'ont changé ?

69voto

Phil Sturgeon Points 19227

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

Réponse courte : Ceci est maintenant entièrement pris en charge. Faites des téléchargements croisés si vous en avez envie !

39voto

oribani Points 281

Je ne suis pas du tout d'accord avec l'idée qu'un "modèle" devrait seulement encapsuler une table de base de données avec des opérations CRUD simples. Comme indiqué dans l'article de Wikipedia :

http://en.wikipedia.org/wiki/Model-view-controller#As_a_design_pattern

...cette couche d'application est destinée à faire plus que simplement agir comme une abstraction de table de base de données unique. Réfléchissez à la signification du mot "contrôleur" : il devrait agir davantage comme un directeur plutôt que d'être l'application entière en soi. Un "modèle" es un endroit pour la logique commerciale. La plupart des applications à grande échelle contiennent 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 causée par le même battage médiatique (excessif) de "MVC", sans que cela n'entraîne une grande compréhension des concepts eux-mêmes. Un peu comme la vacuité d'"AJAX" ou, plus facilement encore, de "Web 2.0". Pour le meilleur ou pour le pire, de nombreux script ont sauté sur le wagon MVC, et puisque les simples howtos et scénarios d'exemple ne font pas beaucoup plus que vous dire de mettre votre code de base de données dans le "modèle", l'utilisation abusive de cette couche comme une simple abstraction de base de données est devenue monnaie courante. Aujourd'hui, vous lisez des articles sur tout l'Internet qui qualifient d'"impur", de "sale", de "bidouilleur" le fait de placer une logique métier dans un modèle. C'est FAUX. C'est mal informé.

L'exemple le plus simple est de penser aux clés étrangères : même si vous voulez que votre "modèle" soit seulement un base de données Si vous voulez être "pur", "correct" ou autre, vous devriez vraiment faire respecter l'intégrité référentielle dans votre modèle. Grâce à l'absence de véritable support des clés étrangères dans MySQL pendant de nombreuses années, les applications web ont grandi sans que personne ne se soucie de l'intégrité référentielle. Cela correspond au style de vie des petits script, je suppose. Quoi qu'il en soit, pour que même cette vue simplifiée d'un modèle soit capable de maintenir la validité des clés étrangères, un modèle doit alors travailler avec d'autres (ou, surtout si un framework comme CodeIgniter ne vous permet pas de le faire, vous devez écrire des requêtes vers d'autres tables, parfois en dupliquant des requêtes ailleurs - C'est du mauvais style).

Par conséquent, je pense que c'est un défaut de CodeIgniter. Je comprends que ce n'est peut-être pas facile à corriger, mais c'est certainement un oubli décevant.

J'ai donc pris le code d'exemple ci-dessus et je l'ai transformé en une aide, de sorte que j'ai maintenant une fonction qui fonctionne de manière presque identique à la fonctionnalité normale $this->load->model(). Le voici (mettez-le dans un helper qui est auto-chargé et vous pouvez 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;
   }

8voto

MECU Points 374

C'est possible, mais pas idéal et considéré comme mauvais et plus pour une "solution rapide" que pour une mise en œuvre 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 principal de CI comme cela est probablement une mauvaise idée. Essayez de repenser votre disposition et de faire passer les données de/vers votre contrôleur aux modèles.

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

6voto

Dave Meybohm Points 206

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 le modèle B utilise le modèle A, lorsque vous essayez de charger l'un ou l'autre, vous allez entrer dans une boucle infinie.

1voto

Zbyszek Points 11

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

1) Avoir l'attribut et le setter du modèle 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 ensuite, utilisez ce setter avant les autres méthodes pour donner une instance de l'autre modèle afin qu'il puisse être utilisé par les méthodes.

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

2) Pour avoir un paramètre dans la méthode par laquelle je vais donner une autre instance de modèle à partir du contrôleur.

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

Et utilise-le comme ça :

  $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 qui doivent accéder à un autre modèle. S'il n'y en a qu'un ou deux, il peut être préférable de le donner comme paramètre de méthode. S'il y en a 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 donner un modèle ou un autre en fonction de certaines conditions - si les deux implémentent partiellement la même interface avec le même type de données retournées (c'est rarement utile, mais ça peut l'être parfois).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X