【问题标题】:CodeIgniter: Load controller within controllerCodeIgniter:在控制器中加载控制器
【发布时间】:2011-08-30 18:30:18
【问题描述】:

我有一个带有index 操作的home 控制器,它显示一组特色产品。但是,产品是通过 product 控制器管理的,包括专有模型和视图。

如何从home 控制器的index 操作中访问product 信息?实例化product 将不起作用,因为在运行时未加载该类,并且 CodeIgniter 不提供动态加载控制器的方法。将product 类放入库文件中也不起作用。

确切地说,我需要将产品视图(填充由product 控制器处理的数据)插入到索引视图中。我正在运行 CodeIgniter 2.0.2。

【问题讨论】:

  • 看起来您正在使用控制器来详细说明数据。我建议你为此使用模型,这样你就必须独立于你所在的控制器调用模型的方法(MVC'skinny controller,fat model')
  • 我更愿意谈论小部件或部分——我希望有一致的模块可以放入站点模板中。这或多或少需要实例化控制器。

标签: php codeigniter


【解决方案1】:

像这样加载它

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

并调用以下方法:

$this->instructor->functioname()

这适用于 CodeIgniter 2.x

【讨论】:

  • 谢谢。请注意,CodeIgniter 将控制器视为单例,因此我发现一旦加载另一个控制器,您的原始控制器将不再正常工作。加载其他控制器后,请确保不要尝试使用$this->load或原始控制器中的任何已加载模型;而是使用$ci = get_instance() 并仅通过$ci 访问模型(例如$ci->user_model)。
  • 即使在您的评论旁边,原始控制器也可以正常工作。
  • 加 1 虽然我不知道教练实际上是控制器
  • 这个只能调用一次。如果你尝试调用另一个控制器,你会得到一个Undefined property
  • 这对我来说是最好的答案
【解决方案2】:

如果您有兴趣,可以将一个完善的包添加到您的 Codeigniter 项目中来处理这个问题:

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

模块化扩展 使 CodeIgniter PHP 框架模块化。模块是一组独立的组件,通常是模型、控制器和视图,排列在应用程序模块子目录中,可以放入其他 CodeIgniter 应用程序中。

好的,所以最大的变化是现在您将使用模块化结构 - 但对我来说这是可取的。我已经使用 CI 大约 3 年了,无法想象没有模块化扩展的生活。

现在,这是处理直接调用控制器以呈现视图部分的部分:

// 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); ?>

仅此而已。我通常使用它来加载小“小部件”,例如:

  • 活动日历
  • 最新新闻文章列表
  • 时事通讯注册表单
  • 投票

通常我为每个模块构建一个“小部件”控制器,并仅将其用于此目的。

【讨论】:

    【解决方案3】:

    在这种情况下,您可以尝试一些老式的 php。

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

    然后,你会得到类似的东西:

    Class Home extends CI_Controller
    {
     public function __construct()
     {
      parent::__construct();
      $this->product = new Product();
      ...
     }
    
     ...
     // usage example
     public function addProduct($data)
     {
      $this->product->add($data);
     }
    }
    

    然后随意使用控制器的方法。

    【讨论】:

      【解决方案4】:

      只是想为 Zain Abbas 所说的话添加更多信息:

      以这种方式加载控制器,然后像他说的那样使用它:

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

      或者您可以创建一个对象并以这种方式使用它:

      $this->load->library('../controllers/your_controller');
      
      $obj = new $this->your_controller();
      
      $obj->your_function();
      

      【讨论】:

      【解决方案5】:

      根据@Joaquin Astelarra 的回复,我设法编写了这个名为 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();
          }
      }
      

      你可以像这样使用/调用它:

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

      注意:第二个参数不是强制性的,因为它将运行名为 index 的方法,就像 CodeIgniter 一样。

      现在您将能够在不使用 HMVC 的情况下将控制器加载到另一个控制器中。

      稍后编辑:请注意,此方法可能会产生意想不到的结果。总是测试它!

      【讨论】:

        【解决方案6】:

        使用以下代码,您可以加载控制器类并执行方法。

        此代码是为 codeigniter 2.1 编写的

        首先在您的应用程序/核心目录中添加一个新文件MY_Loader.php。将以下代码添加到新创建的MY_Loader.php 文件中:

        <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
        
        // written by AJ  sirderno@yahoo.com
        
        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);
            }
        
        }
        

        现在您可以加载应用程序/控制器目录中的所有控制器。 例如:

        加载控制器类Invoice并执行函数test()

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

        或者当类在目录中时

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

        它就像加载模型一样工作

        【讨论】:

          【解决方案7】:

          根据这篇博文,您可以在 codeigniter 的另一个控制器中加载控制器。

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

          首先你需要扩展 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);
                  }
              }
          }
          

          然后在另一个控制器中加载控制器。

          【讨论】:

            【解决方案8】:

            对于在控制器中加载控制器,这里给出了很多很好的答案,但对我来说,这与 mvc 模式相矛盾。

            让我担心的一句话是;

            (填充产品控制者处理的数据)

            模型用于处理和返回数据。如果您将此逻辑放入您的产品模型中,那么您可以从您喜欢的任何控制器调用它,而无需尝试破坏框架。

            我读到的最有帮助的一句话是,控制器就像“交通警察”,负责在模型和视图之间路由请求和响应。

            【讨论】:

              【解决方案9】:

              我知道这是旧的,但如果最近有人发现它,我建议在控制器文件夹中创建一个单独的类文件。将现有的控制器对象传入类构造函数中,然后您可以从任何地方访问这些函数,并且不会与 CI 的设置和处理冲突。

              【讨论】:

                【解决方案10】:

                你可以用这个:

                self::index();
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-12-19
                  • 1970-01-01
                  • 2012-12-05
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多