Codeigniter 从控制器调用控制器 [英] Codeigniter Call Controller From Controller

查看:39
本文介绍了Codeigniter 从控制器调用控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在最后两条评论之后,我将转储我的真实代码,也许它会有所帮助:

After the last two comments, I'll dump out my real code and maybe it will help out:

这是登陆控制器:

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

class Businessbuilder extends CI_Controller {

    function __construct()
    {
        parent::__construct();
    }
    function index()
    {
        $RTR = $GLOBALS["RTR"];


        // import the necessary libraries
        $this->load->model("site_pages");

        $RTR = $GLOBALS["RTR"];

        // get the current site
        $site = current_site();

        // get the requesting url
        $class = $RTR->uri->rsegments[1];
        $function = $RTR->uri->rsegments[2];

        // get the current function and class
        $current_method = explode("::", __METHOD__);

        // get the real class name that is going to be called
        $site_page = $this->site_pages->get(array("display_name"=>$class, "id"=>$site->id));
        $site_page = $site_page->result();
        if(count($site_page) == 1)
        {
            $site_page = $site_page[0];

            // set the class name to be called
            $class = $site_page->class_name;
        }

        // only execute if the requested url is not the current url
        if(!(strtolower($class) == strtolower($current_method[0]) && strtolower($function) == strtolower($current_method[1])))
        {
            if(!file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$class.EXT))
            {
                show_404($RTR->fetch_directory().$class);
                exit;
            }

            // include the required file. I use require once incase it is a file that I've already included
            require_once(APPPATH.'controllers/'.$RTR->fetch_directory().$class.EXT);

            // create an instance of the class
            $CI = new $class();

            if(method_exists($CI, $function))
                // call the method
                call_user_func_array(array(&$CI, $function), array_slice($RTR->uri->rsegments, 2));
            else
            {
                show_404($RTR->fetch_directory().$class);
                exit;
            }
        }
    }
}

这是一个将被调用的动态控制器的例子:

here is an example of a dynamic controller that will be called:

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

class Public_homepage extends CI_Controller {

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

    function index()
    {
        echo "<br /><br /><br />";
        $this->load->model("sites");

        $style = $this->sites->get(array("id"=>1)); // fail here, sites not defined
        //print_r($style);
        exit;


        $view_params = array();
        $view_params["site_id"] = $this->site_id;

        $this->load->view('public_homepage', $view_params);
    }
}

这是我正在使用的模型:

Here is my model that I am using:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Sites extends CI_Model
{
    function __construct()
    {
        parent::__construct();
    }

    function get($search = array())
    {
        return $this->db->query("SELECT * FROM sites"); // failure on this line, db undefined
        }
}

我得到的错误是这个 (error1):

the error that I am getting is either this (error1):

A PHP Error was encountered

Severity: Notice

Message: Undefined property: Public_homepage::$sites

Filename: controllers/public_homepage.php

Line Number: 15
Fatal error: Call to a member function get() on a non-object in /var/www/businessbuilderapp.com/public_html/application/controllers/public_homepage.php on line 15

或者这个(错误2):

A PHP Error was encountered

Severity: Notice

Message: Undefined property: Businessbuilder::$db

Filename: core/Model.php

Line Number: 50
Fatal error: Call to a member function query() on a non-object in /var/www/businessbuilderapp.com/public_html/application/models/bba_model.php on line 25 

我关于为什么会收到这些错误的理论是因为对象的实例与加载模型和库的实例不同.奇怪的是,数组被结转,而不是对象.所以在codeigniter数组$_ci_models的核心Loader.php中填充了Public_homepage类中未加载的模型

My theory as to why I am getting these errors is because the instance of the object is different than the one that loaded the model and libraries. What's odd about that though is that arrays are carried over, but not objects. So in the core Loader.php of codeigniter array $_ci_models is populated with models that are not loaded in the Public_homepage class

还有一点可能对您有所帮助,从第一次通过 businessbuilder 类开始,我就能够成功加载和使用模块,但是当调用 Public_homepage 时,事情开始失败.

Also what might help you is that from the first pass through the businessbuilder class, I am able to load and use the modules successfully, but when Public_homepage is called, that's when things start to fail.

让我感到困惑的是,我试图用一个问题找出 2 个错误,这可能是我的错误.这是我何时收到错误的说明:

What makes this confusing is that I'm trying to figure out 2 errors with one question which is probably my mistake. Here is a description of when I get the errors:

错误 1:

当我按原样运行代码时,我无法调用站点属性.

When I run the code as is, I cannot call the sites property.

错误 2:

当我改变call_user_func_array(array(&$CI, $function), array_slice($RTR->uri->rsegments, 2));到eval($class ."->".$function);

When I change the call_user_func_array(array(&$CI, $function), array_slice($RTR->uri->rsegments, 2)); to eval($class . "->" . $function);

我知道这真的很令人困惑,尤其是在我解释的时候,但如果您需要更多信息,请告诉我.另请注意,Public_homepage 看起来像那样,因为我正在测试.如果可以用最少的代码产生错误,则无需转储更多无用的行.

I understand that this is really confusing, especially when I explain it, but if you need more info, please let me know. Also note that the Public_homepage looks like that because I am testing. There's no need to dump more useless lines if the error can be produced with minimal code.

看了一些答案后,我发现我没有解释代码.这段代码的作用是它允许我在一个数据库中存储不同的 url,但是存储在那里的所有 url 都可以调用同一个页面,即使它们不同.我想一个确切的例子是更改 wordpress 上的 slug.

After reading some of the answers, I realized that I didn't explain the code. What this code does is that it allows me to store different urls inside a database, but all the urls stored there can call the same page even though they are different. I guess an exact example would be changing the slug on wordpress.

发生的情况是 businessbuilder 类设置为接受对服务器的所有请求.当它访问 businessbuilder 类时,它将访问数据库,找出您正在使用的子 url,找到用户正在寻找的真实控制器,并访问该控制器.

What happens is that the businessbuilder class is set to accept ALL requests to the server. When it hits the businessbuilder class, it will access the database, find out what sub url you are using, find the real controller that the user is looking for, and access that controller.

推荐答案

所以经过大量搜索,我想我有一个解决方法.问题是我对实例的看法.深入研究框架后,我意识到它将实例存储为静态变量,私有静态 $instance.如果已填充该变量,我将构造函数修改为不覆盖.最重要的是,由于加载仍然存在一些奇怪的问题,出于某种原因,对象会被标记为已加载,但实际上并没有,我不得不向控制器添加一个新的 var,protected $ci_instance.最后,我将 CI_Controller 修改为如下所示:

So after lots of searching, I think I have a workaround. The issue what what I thought with the instance. After diving into the framework I realized that it is storing the instance into as static var, private static $instance. I modified the constructor to not overwrite if that var has been populated. On top of that, since there were some oddities still with the loading, for some reason objects would be marked as loaded but in reality were not, I had to add a new var to the controller, protected $ci_instance. In the end, I modified the CI_Controller to look like the following:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 5.1.6 or newer
 *
 * @package     CodeIgniter
 * @author      ExpressionEngine Dev Team
 * @copyright   Copyright (c) 2008 - 2011, EllisLab, Inc.
 * @license     http://codeigniter.com/user_guide/license.html
 * @link        http://codeigniter.com
 * @since       Version 1.0
 * @filesource
 */

// ------------------------------------------------------------------------

/**
 * CodeIgniter Application Controller Class
 *
 * This class object is the super class that every library in
 * CodeIgniter will be assigned to.
 *
 * @package     CodeIgniter
 * @subpackage  Libraries
 * @category    Libraries
 * @author      ExpressionEngine Dev Team
 * @link        http://codeigniter.com/user_guide/general/controllers.html
 */
class CI_Controller {

    private static $instance;
    protected $ci_instance; // line added

    /**
     * Constructor
     */
    public function __construct()
    {

        if(self::$instance == null) // line added
            self::$instance =& $this;

        $this->ci_instance =& get_instance(); // line added

        // 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->_base_classes =& is_loaded();

        $this->load->_ci_autoloader();

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

    public static function &get_instance()
    {
        return self::$instance;
    }
}
// END Controller class

/* End of file Controller.php */
/* Location: ./system/core/Controller.php */

目前唯一的问题是我不能做 $this->load->model("some_model");.相反,我必须使用 $this->ci_instance->load->model("some_model");一切都将从那里开始.我并不真正关心额外的变量,但我不喜欢修改开箱即用的解决方案,因为它增加了升级的复杂性.

The only issue so far is that I cannot do $this->load->model("some_model");. Instead I have to use $this->ci_instance->load->model("some_model"); and everything will stem from there. I don't really care about the extra var, but what I don't like is modifying out of box solutions because it increases the complexity to do an upgrade.

目前我已将此标记为答案,因为我"选择将其用作我的解决方案,但我仍然愿意接受比我正在使用的解决方案更好的解决方案.需要解决的问题的确切描述如下:

for now I've marked this as an answer because it is what "I" have chosen to use as my solution, but I am still opened to a better solution than the one I am using. An exact description of what needs to be solved is as follows:

将所有加载的属性从一个实例复制到另一个实例.如果可能的话,基本上做两个实例的合并.

Copy all loaded properties from one instance to another. Basically do a merger of two instances if possible.

如果有人能用比我更好的解决方案来回答这个问题,最好不修改 codeigniter 核心,我很乐意更改我的答案,因为我对我的解决方案不满意,因为我不知道我以后可能会遇到什么影响在开发过程中.

If someone can answer that with a better solution than mine, preferably without modifying the codeigniter core, I'd gladly change my answer because I am not happy with my solution because I don't know what effects I might encounter later on during development.

这篇关于Codeigniter 从控制器调用控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆