CodeIgniter:在控制器中加载控制器

Posted

技术标签:

【中文标题】CodeIgniter:在控制器中加载控制器【英文标题】:CodeIgniter: Load controller within controller 【发布时间】: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') 我更愿意谈论小部件或部分——我希望有一致的模块可以放入站点模板中。这或多或少需要实例化控制器。 【参考方案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();

【讨论】:

您好,此解决方案适用于 CI 2.x。似乎 CI 3.x 不再允许这样做,现在我不使用 CI 3.x,所以我帮不了你太多。检查这个论坛forum.codeigniter.com/thread-744-page-2.html也许你可以在那里得到一些信息。这是一个github问题,可能与您的问题github.com/bcit-ci/CodeIgniter/issues/3480有关。【参考方案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();

【讨论】:

以上是关于CodeIgniter:在控制器中加载控制器的主要内容,如果未能解决你的问题,请参考以下文章

我如何在控制器函数中加载目录作为视图:Codeigniter

在 codeigniter 的控制器中加载模型时出错消息:未定义的属性:Cart::$load

如何在每个页面中加载 CodeIgniter 助手?

如何在 codeigniter 4 中加载 css 或 js 文件?

codeigniter 无法加载库

为啥这个构造函数无法在 Codeigniter 中加载?