web-dev-qa-db-fra.com

CodeIgniter: contrôleur de charge dans le contrôleur

J'ai un contrôleur home avec une action index qui affiche un ensemble de produits en vedette. Toutefois, les produits sont gérés via un contrôleur product, comprenant un modèle et des vues propriétaires.

Comment accéder aux informations product à partir de l'action index dans le contrôleur home? L'instanciation product ne fonctionnera pas car la classe n'est pas chargée au moment de l'exécution et CodeIgniter ne fournit pas un moyen de charger dynamiquement des contrôleurs. Mettre la classe product dans un fichier de bibliothèque ne fonctionne pas non plus.

Pour être précis, j'ai besoin que les vues du produit (contenant les données traitées par le contrôleur product) soient insérées dans la vue d'index. J'exécute CodeIgniter 2.0.2.

43
Daniel

Si cela vous intéresse, il existe un paquet bien établi que vous pouvez ajouter à votre projet Codeigniter pour gérer cela:

https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/

Modular Extensions rend le framework CodeIgniter PHP modulaire. Les modules sont des groupes de composants indépendants, généralement des modèles, des contrôleurs et des vues, disposés dans un sous-répertoire de modules d'application, pouvant être déposés dans d'autres applications CodeIgniter.

OK, donc le gros changement est que vous utiliseriez maintenant une structure modulaire - mais pour moi, c'est souhaitable. J'utilise CI depuis environ 3 ans maintenant et je ne peux pas imaginer une vie sans extensions modulaires.

Maintenant, voici la partie qui traite des appels directs aux contrôleurs pour le rendu des vues partielles:

// Using a Module as a view partial from within a view is as easy as writing:
<?php echo modules::run('module/controller/method', $param1, $params2); ?>

C'est tout ce qu'on peut en dire. J'utilise généralement cela pour charger de petits "widgets" comme:

  • Calendriers d'événements
  • Liste des derniers articles de presse
  • Formulaires d'inscription à la newsletter
  • Les sondages

En règle générale, je construis un contrôleur "widget" pour chaque module et ne l'utilise qu'à cette fin.

Votre question était également l'une de mes premières questions lorsque j'ai commencé avec Codeigniter. J'espère que cela vous aidera, même si c'est peut-être un peu plus que ce que vous recherchiez. J'utilise MX depuis et je n'ai pas regardé en arrière.

Assurez-vous de lire la documentation et de consulter la multitude d'informations concernant ce paquet sur les forums de Codeigniter. Prendre plaisir!

30
Wesley Murch

Charger comme ça

$this->load->library('../controllers/instructor');

et appelez la méthode suivante:

$this->instructor->functioname()

Cela fonctionne pour CodeIgniter 2.x .

63
Zulqurnain abbas

Juste pour ajouter plus d'informations à ce que Zain Abbas a dit:

Chargez le contrôleur de cette façon et utilisez-le comme il a dit:

$this->load->library('../controllers/instructor');

$this->instructor->functioname();

Ou vous pouvez créer un objet et l'utiliser de la façon suivante:

$this->load->library('../controllers/your_controller');

$obj = new $this->your_controller();

$obj->your_function();

J'espère que cela peut aider.

8
Salvador P.

Dans ce cas, vous pouvez essayer une vieille école php.

// insert at the beggining of home.php controller require_once(dirname(__FILE__)."/product.php"); // the controller route.

Ensuite, vous aurez quelque chose comme:

Class Home extends CI_Controller
{
 public function __construct()
 {
  parent::__construct();
  $this->product = new Product();
  ...
 }

 ...
 // usage example
 public function addProduct($data)
 {
  $this->product->add($data);
 }
}

Et ensuite, utilisez les méthodes du contrôleur à votre guise.

7
Joaquin Astelarra

Sur la base de la réponse de @Joaquin Astelarra, j'ai réussi à écrire ce petit assistant nommé load_controller_helper.php :

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if (!function_exists('load_controller'))
{
    function load_controller($controller, $method = 'index')
    {
        require_once(FCPATH . APPPATH . 'controllers/' . $controller . '.php');

        $controller = new $controller();

        return $controller->$method();
    }
}

Vous pouvez utiliser/appeler comme ça:

$this->load->helper('load_controller');
load_controller('homepage', 'not_found');

Remarque: Le deuxième argument n'est pas obligatoire car il exécutera la méthode nommée index , comme le ferait CodeIgniter.

Vous pourrez maintenant charger un contrôleur dans un autre contrôleur sans utiliser HMVC.

Éditer plus tard: Soyez conscient que cette méthode peut avoir des résultats inattendus. Toujours le tester!

6
machineaddict

Il y a beaucoup de bonnes réponses données ici pour charger les contrôleurs dans les contrôleurs, mais pour moi, cela contredit le modèle MVC.

La phrase qui m'inquiète est;

(rempli de données traitées par le contrôleur de produit)  

Les modèles sont là pour traiter et renvoyer des données. Si vous mettez cette logique dans votre modèle de produit, vous pouvez l'appeler à partir de n'importe quel contrôleur sans avoir à essayer de pervertir le framework.

L'une des citations les plus utiles que j'ai lues était que le contrôleur était comme un «agent de la circulation», là pour acheminer les demandes et les réponses entre les modèles et les vues.

1
charliefortune

Avec le code suivant, vous pouvez charger les classes du contrôleur et exécuter les méthodes.

Ce code a été écrit pour codeigniter 2.1

Commencez par ajouter un nouveau fichier MY_Loader.php dans votre répertoire application/core. Ajoutez le code suivant à votre nouveau fichier MY_Loader.php:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

// written by AJ  [email protected]

class MY_Loader extends CI_Loader 
{
    protected $_my_controller_paths     = array();  

    protected $_my_controllers          = array();


    public function __construct()
    {
        parent::__construct();

        $this->_my_controller_paths = array(APPPATH);
    }

    public function controller($controller, $name = '', $db_conn = FALSE)
    {
        if (is_array($controller))
        {
            foreach ($controller as $babe)
            {
                $this->controller($babe);
            }
            return;
        }

        if ($controller == '')
        {
            return;
        }

        $path = '';

        // Is the controller in a sub-folder? If so, parse out the filename and path.
        if (($last_slash = strrpos($controller, '/')) !== FALSE)
        {
            // The path is in front of the last slash
            $path = substr($controller, 0, $last_slash + 1);

            // And the controller name behind it
            $controller = substr($controller, $last_slash + 1);
        }

        if ($name == '')
        {
            $name = $controller;
        }

        if (in_array($name, $this->_my_controllers, TRUE))
        {
            return;
        }

        $CI =& get_instance();
        if (isset($CI->$name))
        {
            show_error('The controller name you are loading is the name of a resource that is already being used: '.$name);
        }

        $controller = strtolower($controller);

        foreach ($this->_my_controller_paths as $mod_path)
        {
            if ( ! file_exists($mod_path.'controllers/'.$path.$controller.'.php'))
            {
                continue;
            }

            if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
            {
                if ($db_conn === TRUE)
                {
                    $db_conn = '';
                }

                $CI->load->database($db_conn, FALSE, TRUE);
            }

            if ( ! class_exists('CI_Controller'))
            {
                load_class('Controller', 'core');
            }

            require_once($mod_path.'controllers/'.$path.$controller.'.php');

            $controller = ucfirst($controller);

            $CI->$name = new $controller();

            $this->_my_controllers[] = $name;
            return;
        }

        // couldn't find the controller
        show_error('Unable to locate the controller you have specified: '.$controller);
    }

}

Vous pouvez maintenant charger tous les contrôleurs de votre répertoire application/controllers . Par exemple:

charge la classe de contrôleur Invoice et exécute la fonction test ()

$this->load->controller('invoice','invoice_controller');

$this->invoice_controller->test();

ou quand la classe est dans un répertoire

$this->load->controller('/dir/invoice','invoice_controller');

$this->invoice_controller->test();

Cela fonctionne comme si vous chargiez un modèle

0
user1881928

Je sais que c'est vieux, mais si quelqu'un le trouvait plus récemment, je suggérerais de créer un fichier de classe séparé dans le dossier controllers. Transmettez l'objet contrôleur existant dans le constructeur de classe. Vous pourrez alors accéder aux fonctions de n'importe où et cela n'entrera pas en conflit avec la configuration et la gestion de CI.

0
Ukuser32

Selon ce billet de blog, vous pouvez charger le contrôleur dans un autre contrôleur dans Codeigniter.

http://www.techsirius.com/2013/01/load-controller-within-another.html

Tout d'abord, vous devez étendre CI_Loader 

<?php

class MY_Loader extends CI_Loader {

    public function __construct() {
        parent::__construct();
    }

    public function controller($file_name) {
        $CI = & get_instance();
        $file_path = APPPATH.'controllers/' . $file_name . '.php';
        $object_name = $file_name;
        $class_name = ucfirst($file_name);

        if (file_exists($file_path)) {
            require $file_path;

            $CI->$object_name = new $class_name();
        }
        else {
            show_error('Unable to load the requested controller class: ' . $class_name);
        }
    }
}

puis chargez le contrôleur dans un autre contrôleur.

0
Webby