控制器的代码调用控制器 [英] Codeigniter Call Controller From Controller

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

问题描述



这里是着陆控制器:

$

b
$ b

 <?php if(!defined('BASEPATH'))exit('不允许直接脚本访问); 

class Businessbuilder extends CI_Controller {

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


//导入必要的库
$ this-> load-> model(site_pages);

$ RTR = $ GLOBALS [RTR];

//获取当前站点
$ site = current_site();

//获取请求的url
$ class = $ RTR-> uri-> rsegments [1];
$ function = $ RTR-> uri-> rsegments [2];

//获取当前函数和类
$ current_method = explode(::,__METHOD__);

//获取要调用的真实类名称
$ 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];

//设置要调用的类名
$ class = $ site_page-> class_name;
}

//仅当请求的url不是当前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;
}

//包含所需的文件。我使用require一次incase它是一个文件,我已经包括
require_once(APPPATH.'controllers /'.$ RTR-> fetch_directory()。$ class.EXT);

//创建类的实例
$ CI = new $ class();

if(method_exists($ CI,$ function))
//调用方法
call_user_func_array(array(& $ CI,$ function),array_slice($ RTR- > uri> rsegments,2));
else
{
show_404($ RTR-> fetch_directory()。$ class);
exit;
}
}
}
}



是将被调用的动态控制器的示例:

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

类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);
}
}

这里是我使用的我的模型: p>

 <?php if(!defined('BASEPATH'))exit('不允许直接脚本访问); 
class Sites extends CI_Model
{
function __construct()
{
parent :: __ construct();
}

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

我得到的是这是(错误1):

 遇到PHP错误

严重性:通知

消息:未定义属性:Public_homepage :: $ sites

文件名:controllers / public_homepage.php

行号:15
致命错误:在第15行的/var/www/businessbuilderapp.com/public_html/application/controllers/public_homepage.php中的非对象上调用成员函数get()

或此(错误2):

 遇到

严重性:注意

消息:未定义属性:Businessbuilder :: $ db

文件名:core / Model.php

行号:50
致命错误:调用成员函数query()on一个非对象在/var/www/businessbuilderapp.com/public_html/application/models/bba_model.php on line 25

我的理由是为什么我得到这些错误是因为对象的实例不同于一个加载模型和库。奇怪的是,虽然数组是结转,但不是对象。因此,在codeigniter数组的核心Loader.php $ _ci_models中填充了未加载在Public_homepage类中的模型



还有什么可能会帮助你从第一次通过通过businessbuilder类,我可以成功加载和使用模块,但是当Public_homepage被调用时,这是事情开始失败。



令人困惑的是,我试图找出两个错误与一个问题,这可能是我的错误。以下是我何时收到错误的说明:



错误1:



,我不能调用sites属性。



错误2:



当我更改
call_user_func_array array(& $ CI,$ function),array_slice($ RTR-> uri-> rsegments,2));
to
eval($ class。 - >。$ function);



我知道这真的很混乱,它,但如果你需要更多的信息,请让我知道。还要注意,Public_homepage看起来像,因为我测试。没有必要转储更多的无用的行,如果错误可以产生最小的代码。



更新



在阅读了一些答案后,我意识到我没有解释代码。这个代码的作用是它允许我在数据库中存储不同的url,但是存储在那里的所有url可以调用相同的页面,即使他们是不同的。我想一个确切的例子是改变wordpress上的slug。



会发生什么是businessbuilder类设置为接受对服务器的所有请求。当它碰到businessbuilder类时,它将访问数据库,找出您正在使用的子URL,找到用户正在查找的真实控制器,并访问该控制器。

解决方案

所以经过大量的搜索,我想我有一个解决方法。问题什么我认为与实例。在进入框架后,我意识到它将实例存储为静态var,private static $ instance。我修改了构造函数,如果该var已经被填充,则不覆盖。最重要的是,因为有一些怪异仍然与加载,由于某些原因对象将被标记为加载,但实际上不是,我不得不添加一个新的控制器,保护$ ci_instance。最后,我修改了CI_Controller如下:

 <?php if(!defined('BASEPATH' ))exit('不允许直接脚本访问'); 
/ **
* CodeIgniter
*
*用于PHP 5.1.6或更高版本的开源应用程序开发框架
*
* @package CodeIgniter
* @author ExpressionEngine Dev Team
* @copyright版权所有(c)2008-2011,EllisLab,Inc.
* @license http://codeigniter.com/user_guide/license.html
* @link http://codeigniter.com
* @since版本1.0
* @filesource
* /

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

/ **
* CodeIgniter应用程序控制器类
*
*此类对象
* CodeIgniter中的每个库都将被分配给的超类。
*
* @package CodeIgniter
* @subpackage库
* @category库
* @author ExpressionEngine Dev Team
* @link http:// codeigniter.com/user_guide/general/controllers.html
* /
class CI_Controller {

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

/ **
*构造函数
* /
public function __construct()
{

(self :: $ instance == null)//行添加
self :: $ instance =& $ this;

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

//将由
// bootstrap文件(CodeIgniter.php)实例化的所有类对象分配给本地类变量
//,以使CI可以作为一个大的超级对象运行。
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.php * /
/ *位置:./system/core /Controller.php * /

到目前为止唯一的问题是我不能做$ this-> load - > model(some_model);.相反,我必须使用$ this-> ci_instance-> load-> model(some_model);和一切都会从那里。我真的不在乎额外的var,但我不喜欢的是修改现成的解决方案,因为它增加了复杂性,做升级。



现在我已经标记为答案,因为它是我选择使用作为我的解决方案,但我仍然打开一个更好的解决方案,比我使用的。对需要解决的问题的准确描述如下:



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



如果有人能用一个比我更好的解决方案,最好不修改codeigniter核心,我会很乐意改变我的答案,因为我不满意我的解决方案,因为我不知道在开发过程中可能会遇到什么样的影响。


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

Here is the landing Controller:

 <?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
        }
}

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

or this (error2):

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 

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

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.

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:

Error1:

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

Error2:

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

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.

Update

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.

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.

解决方案

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 */

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.

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.

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

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