get instance () dans Codeigniter: pourquoi l'attribuer à une variable?

dans Codeigniter, get_instance() est une fonction globalement disponible qui renvoie le super-objet Controller qui contient toutes les classes actuellement chargées (il renvoie l'instance de la classe Controller). Je vais inclure le code source actuel:

get_instance() est défini dans Codeigniter.php

// Load the base controller class
require BASEPATH.'core/Controller.php';

function &get_instance()
{
    return CI_Controller::get_instance();
}

et CI_Controller est défini dans Controller.php

class CI_Controller {

    private static $instance;

    /**
     * Constructor
     */
    public function __construct()
    {
        self::$instance =& $this;

        // Assign all the class objects that were instantiated by the
        // bootstrap file (CodeIgniter.php) to local class variables
        // so that CI can run as one big super object.
        foreach (is_loaded() as $var => $class)
        {
            $this->$var =& load_class($class);
        }

        $this->load =& load_class('Loader', 'core');

        $this->load->set_base_classes()->ci_autoloader();

        log_message('debug', "Controller Class Initialized");
    }

    public static function &get_instance()
    {
        return self::$instance;
    }
}

Voici comment il est recommandé de l'utiliser dans le guide de l'utilisateur pour la création de bibliothèques :

utiliser des ressources CodeIgniter dans votre bibliothèque

pour accéder aux ressources natives de CodeIgniter dans votre bibliothèque, utilisez le get_instance() de la fonction. Cette fonction renvoie le code super objet.

Normalement à partir de votre contrôleur, vous appeler tout de les fonctions CodeIgniter disponibles en utilisant le $this construire: $this->load->helper('url'); $this->load->library('session'); $this->config->item('base_url'); etc.

$this , cependant, ne fonctionne directement au sein de vos contrôleurs, votre modèles, ou de votre point de vue. Si vous souhaitez utiliser les cours de CodeIgniter à partir de vos propres cours personnalisés, vous pouvez le faire comme suit:

d'abord, assignez l'objet CodeIgniter à une variable:

$IC =& get_instance();

une Fois que vous avez assigné l'objet pour une variable, vous devez utiliser variable au lieu de $this : $IC =& get_instance(); $IC->load->helper('url'); $IC->load->library('session'); $CI - > config - > item ('base_url'); etc.

Note: vous remarquerez que la fonction get_instance() ci-dessus est

$IC =& get_instance();

C'est très important. assigner par référence permet vous d'utiliser le objet CodeIgniter original plutôt que d'en créer une copie.

Related posts: explain $CI =& get_instance(); / Codeigniter: obtenir L'Instance

donc, voici ma question actuelle:

pourquoi le guide de l'utilisateur recommande-t-il d'affecter get_instance() à une variable? Je suis assez certain de comprendre les implications de ne pas assigner par référence, mais pourquoi est-il recommandé de l'affecter à une variable lorsque get_instance()->load->model() fonctionne bien?

je vois beaucoup d'défini par l'utilisateur ou un tiers des classes de CI que de céder à une propriété de l'objet:

class MY_Class {

    private $CI;

    function __construct()
    {
        $this->CI =& get_instance();
    }
    function my_func()
    {
        $this->CI->load->view('some_view');
    }
    function my_other_func()
    {
        $this->CI->load->model('some_model');
    }
}

Mauvais exemple, mais je le vois souvent. Pourquoi s'embêter avec cette méthode, au lieu de simplement appeler get_instance() directement? It semble comme si assigner l'objet contrôleur entier à une variable de classe ne serait pas une grande idée, même si elle est une référence. Peut-être qu'il n'a pas d'importance.

je veux écrire une fonction wrapper pour get_instance() donc c'est plus facile de taper, et je n'ai pas à l'assigner constamment à une variable.

function CI()
{
    return get_instance();
}

Ou:

function CI()
{
    $CI =& get_instance();
    return $CI;
}

alors je pourrais utiliser CI()->class->method() de n'importe où sans la peine de l'assigner à une variable, il est très facile d'écrire et de comprendre ce qu'il fait, et peut entraîner plus court, plus le code élégant.

  • y a-t-il une raison de ne pas adopter cette approche?
  • y a-t-il une différence entre les deux fonctions CI() ci-dessus?
  • Pourquoi est-il recommandé d'attribuer get_instance() à une variable plutôt que de l'appeler directement?
  • que signifie le & dans function &get_instance(){} là où il est défini? Je sais un peu ce que références sont pour et je les utilise quand c'est approprié, mais je n'ai jamais vu une fonction définie de cette façon. Si j'écris une fonction wrapper, devrais-je l'utiliser aussi?

veuillez noter qu'il ne s'agit pas tellement d'une question style , mais d'une question technique. Je veux savoir s'il y a des problèmes, performance ou autrement , avec l'utilisation de la méthode que je suggère.

EDIT : Jusqu'à présent nous ont:

  • L'enchaînement de méthode n'est pas disponible dans php4, donc l'assignation à une variable est une solution de contournement (bien que cela soit assez hors de propos puisque Codeigniter a abandonné le soutien de php4)
  • le petit overhead d'appeler une fonction plus d'une fois pour retourner l'objet, plutôt que de l'appeler une fois et de l'assigner à une variable.

autre chose, ou s'agit-il des seuls problèmes potentiels?

57
demandé sur Community 2011-08-25 22:41:33

7 réponses

autant que je sache, c'est une question de commodité plus que tout. Il y a de fortes Chances que vous utilisiez beaucoup L'objet CI super dans vos bibliothèques, alors pourquoi ne pas l'affecter à une variable pour le rendre un peu plus facile à utiliser?

il y a d'autres choses à considérer...

  1. Si vous mettez cette méthode dans un helper, cette méthode devient une dépendance pour toute la classe que vous l'utilisez. Ce ne serait pas une grosse affaire pour vous, mais si vous voulez partager des bibliothèques avec quelqu'un d'autre, il se peut qu'ils ne soient pas satisfaits de la dépendance, d'autant plus qu'il y a déjà une façon standard de gérer cela dans la communauté CI.
  2. il y a un léger impact sur la performance parce que vous appelez get_instance() chaque fois que vous utilisez l'Assistant plutôt que de stocker son résultat dans une variable.
  3. Puisqu'il s'agit D'une méthode d'aide qui est censée vous faire gagner du temps, pour quiconque travaille principalement dans le noyau MVC fichiers de CI, la mise en place d'un helper comme celui-ci prendrait plus de temps que simplement la mise en place d'une variable dans les quelques endroits où vous en avez besoin.
21
répondu Chris Schmitz 2011-08-25 19:30:33

Pourquoi est-il recommandé d'assigner get_instance() à une variable plutôt que de l'appeler directement?

très probablement, il est recommandé de maintenir une rétrocompatibilité avec php4, où les objets n'ont pas été passés par référence par défaut, mais ont été clonés.

y a-t-il une raison de ne pas adopter cette approche?

seulement si vous voulez que votre application fonctionne sur installations php obsolètes

3
répondu dev-null-dweller 2011-08-25 18:48:11

il est nécessaire d'attribuer par référence parce que la valeur de CI_Controller::$instance est sujette à changement si une autre instance de la classe est créée. Le constructeur attribue à nouveau self::$instance chaque fois qu'il tourne.

en général, cela ressemble à un mauvais dessin et manque la propriété d'un singleton qui limite la classe à une seule instance, http://en.wikipedia.org/wiki/Singleton_pattern .

il semble possible de tapez CI_Controller::get_instance()->$className->$method(); , ce qui semble plus typé que votre CI()->$className->$method demandé .

en fin de compte, il serait logique d'exiger qu'une seule instance de $instance puisse être créée, puis la nécessité d'assigner par référence serait éliminée.

3
répondu Ben 2012-07-26 21:21:31
Le chaînage de méthode

n'est pas supporté dans PHP4 et CI n'est pas supporté pour PHP4 très récemment (de la version 2.0.0 ). Aussi il est facile d'écrire $CI que d'écrire get_instance() à chaque fois.

3
répondu Usman 2014-11-27 06:07:55

je préfère les utilisations de cette façon ,c'est simple

class Test
{
    //magic method __get, whit this can use $this->load
    //instead create a variable ci, then do $this->ci->load, cool :)

    public function __get($var)
    {
        return get_instance()->$var;
    }

    public function showUrl()
    {
        $this->load->helper("url");
        echo base_url();
    }
}
2
répondu user2604283 2015-07-22 09:47:49

il pourrait s'agir d'une combinaison de plusieurs choses, y compris le déjà mentionné:

  • rétrocompatibilité
  • Commodité
  • Guide De Style

de Préférence, j'aime l'idée de cette "recommandation" comme étant une partie d'un guide de style. Peut-être pas le guide de style officiel de CI, mais quand même.

Imaginez que tous les scripts tiers pour CI implémentent ceci recommandation, n'importe quel développeur serait en mesure de déterminer rapidement comment ces scripts sont conçus bien que ce juste une très petite partie du script.

une autre chose que IMO est important est la mécanique de méthode chaînage - et faire CI()->class->method() ne semble pas intuitif pour moi, sachant comment le reste de CI fonctionne.

1
répondu Repox 2011-08-25 19:01:10

obtenir le résultat de get_instance() par référence n'a tout simplement aucun sens depuis PHP5. Malheureusement, cette mauvaise habitude semble profondément enracinée, alors réglons ça.

Pour ceux qui sont intéressés, voici un über rapide exemple de lecture:

function CI()
{
    static $CI;
    isset($CI) || $CI = CI_Controller::get_instance();

    return $CI;
}

noter que la variable statique ne fonctionnerait pas si elle était assignée par référence.

en outre, vous êtes forcé de ne pas obtenir par référence le résultat de ce CI() . De sucre supplémentaire :-)

ah, et évidemment vous avez encore le (léger) coût de l'appel de fonction. Vous pouvez toujours utiliser une variable au lieu d'appeler la fonction dizaines de fois.

0
répondu Gras Double 2013-06-28 23:27:50