Codeigniter Call Controller с контроллера - PullRequest
8 голосов
/ 17 февраля 2011

После двух последних комментариев я выложу свой реальный код и, возможно, он поможет:

Вот контроллер посадки:

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

Вот пример динамического контроллера, который будет называться:

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

Вот моя модель, которую я использую:

<?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):

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

или это (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 

Моя теория относительно того, почему я получаю эти ошибки, заключается в том, что экземпляр объекта отличается от экземпляра, который загружал модель и библиотеки. Что в этом странного, так это то, что массивы переносятся, а не объекты. Таким образом, в ядре Loader.php массива codeigniter $ _ci_models заполняется моделями, которые не загружены в классе Public_homepage

Также, что может вам помочь, это то, что с первого прохода через класс businessbuilder я могу загружать и использовать модули успешно, но когда вызывается Public_homepage, именно тогда все начинает давать сбой.

Что сбивает с толку то, что я пытаюсь выяснить 2 ошибки с одним вопросом, который, вероятно, является моей ошибкой. Вот описание того, когда я получаю ошибки:

Error1:

Когда я запускаю код как есть, я не могу вызвать свойство sites.

Error2:

Когда я меняю call_user_func_array (массив (& $ CI, $ function), array_slice ($ RTR-> uri-> rsegments, 2)); в eval ($ class. "->". $ function);

Я понимаю, что это действительно сбивает с толку, особенно когда я объясняю это, но если вам нужна дополнительная информация, пожалуйста, дайте мне знать. Также обратите внимание, что Public_homepage выглядит так, потому что я тестирую. Нет необходимости сбрасывать больше бесполезных строк, если ошибка может быть вызвана минимальным кодом.

Обновление

Прочитав некоторые ответы, я понял, что не объяснил код. Этот код делает то, что он позволяет мне хранить разные URL в базе данных, но все сохраненные там URL могут вызывать одну и ту же страницу, даже если они разные. Я предполагаю, что точным примером будет изменение пули на WordPress.

В результате получается, что класс businessbuilder настроен на прием ВСЕХ запросов к серверу. Когда он попадает в класс businessbuilder, он получает доступ к базе данных, выясняет, какой под URL вы используете, находит реальный контроллер, который ищет пользователь, и получает доступ к этому контроллеру.

Ответы [ 3 ]

6 голосов
/ 18 февраля 2011

Так что после долгих поисков, я думаю, у меня есть обходной путь. Вопрос в том, что я думал с экземпляром. Окунувшись во фреймворк, я понял, что он хранит экземпляр как static var, private static $ instance. Я изменил конструктор, чтобы не перезаписывать, если эта переменная была заполнена. Вдобавок ко всему, поскольку при загрузке были некоторые странности, по какой-то причине объекты были бы помечены как загруженные, но на самом деле это не так, мне пришлось добавить новый контроллер в контроллер, защищенный $ ci_instance. В конце я изменил CI_Controller, чтобы он выглядел следующим образом:

<?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"); и все будет происходить оттуда. Меня не особо волнует дополнительный вариант, но мне не нравится модифицировать готовые решения, потому что это усложняет обновление.

на данный момент я пометил это как ответ, потому что именно это «я» выбрал для использования в качестве своего решения, но я все еще открыт для лучшего решения, чем то, которое я использую. Точное описание того, что необходимо решить, выглядит следующим образом:

Скопируйте все загруженные свойства из одного экземпляра в другой. В основном сделайте слияние двух экземпляров, если это возможно.

Если кто-то может ответить на это лучшим решением, чем мое, желательно без изменения ядра codeigniter, я с радостью изменил бы свой ответ, потому что я не доволен своим решением, потому что я не знаю, с какими эффектами я мог бы столкнуться позже во время разработки.

1 голос
/ 01 сентября 2011

В вашем приложении / autoload.php установите codeigniter для загрузки класса базы данных.

$autoload['libraries'] = array('database', 'otherlibrary', 'otherlibrary2');

Это должно быть все, что вам нужно для решения вашей проблемы.

0 голосов
/ 21 апреля 2013

если вы используете HMVC, просто используете

Class Models extends MX_Loader{

   function getUser($username){
       $sql="SELECT
                   *
              FROM
                   user
              WHERE username = ? "
       return $this->db->query($sql,array($username))->row();
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...