Calling CI models from outside script

Derek Jones edited this page Jul 5, 2012 · 20 revisions
Clone this wiki locally

Warning: nobody on the forums (with more experience) wanted to comment on this so use at own risk.

Sometimes you need to access ci models from other PHP scripts. The problem is that a ci model relies on the presence of a ci controller and inherits from the Model base class which relies on part of the code igniter system being active. The solution was to strip code igniter down to the essentials and include that prior to instantiating a model. Then you include the "de-activation" part in order to clean up. Note that the whole shebang(see example at bottom) could probably have been prettied up in a function instead of polluting the global namespace but I did not have time. It should not be hard to do. A potential use for this is making amfphp use your models for services. Especially with the new amfphp, this is really neat since you don't need a table describing each function so it's all automatic.

[QUOTE] EDIT: (added by Hickeroar) If you are using $this->load->database() (or loading any other library for that matter) in your model and it's not working, try putting that library into the autoload.php file in the system/application/config folder.

I encountered a problem where commands such as $this->db->query() were giving me: "Fatal error: Call to a member function on a non-object" and through playing around I noticed that this ceased when the library was autoloaded.

Associated Forum Thread: http://codeigniter.com/forums/viewthread/54430/

UPDATE: It was pointed out in the forum thread that I wasn't using $this->load->database(); inside the constructor of my model (I used it in the method I was calling directly). No one's officially tested it trying both ways specifically, but it's possible it works properly when that line is put right into the constructor. For my use, autoloading works just fine and the problem is solved.

Also, there's a good example of how to integrate CI and AMFPHP in the previously linked forum thread, FYI. ( This Post: http://codeigniter.com/forums/viewthread/54430/#269161 ) That example can also be applied to a great many other things, not just AMFPHP. [/QUOTE]

The system consists of 3 files.

config_constants.php:


<?php
/**
 * This file is pretty much index.php with a few modifications
 * which are:
 *    - the loading of the front controller is removed from the bottom since
 *      this file is now included from ci_model_remote_open.php
 *    - when setting $system_folder and $application_folder we check for previous
 *    existence of those variables so we can set them previous to including
 *    ci_model_remote_open.php. This way it's more flexible.
 *    - error reporting control has been removed
 */

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

/*
|---------------------------------------------------------------
| SYSTEM FOLDER NAME
|---------------------------------------------------------------
|
| This variable must contain the name of your "system" folder.
| Include the path if the folder is not in the same  directory
| as this file.
|
| NO TRAILING SLASH!
|
*/
if( ! $system_folder)
    $system_folder = "system";

/*
|---------------------------------------------------------------
| APPLICATION FOLDER NAME
|---------------------------------------------------------------
|
| If you want this front controller to use a different "application"
| folder then the default one you can set its name here. The folder 
| can also be renamed or relocated anywhere on your server.
| For more info please see the user guide:
| http://www.codeigniter.com/user_guide/general/managing_apps.html
|
|
| NO TRAILING SLASH!
|
*/
if( ! $application_folder)
    $application_folder = "application";


/*
|===============================================================
| END OF USER CONFIGURABLE SETTINGS
|===============================================================
*/


/*
|---------------------------------------------------------------
| SET THE SERVER PATH
|---------------------------------------------------------------
|
| Let's attempt to determine the full-server path to the "system"
| folder in order to reduce the possibility of path problems.
|
*/
if (function_exists('realpath') AND @realpath(dirname(__FILE__)) !== FALSE)
{
    $system_folder = str_replace("\\", "/", realpath(dirname(__FILE__))).'/'.$system_folder;
}

/*
|---------------------------------------------------------------
| DEFINE APPLICATION CONSTANTS
|---------------------------------------------------------------
|
| EXT        - The file extension.  Typically ".php"
| FCPATH    - The full server path to THIS file
| SELF        - The name of THIS file (typically "index.php)
| BASEPATH    - The full server path to the "system" folder
| APPPATH    - The full server path to the "application" folder
|
*/
define('EXT', '.'.pathinfo(__FILE__, PATHINFO_EXTENSION));
define('FCPATH', __FILE__);
define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));
define('BASEPATH', $system_folder.'/');

if (is_dir($application_folder))
{
    define('APPPATH', $application_folder.'/');
}
else
{
    if ($application_folder == '')
    {
        $application_folder = 'application';
    }

    define('APPPATH', BASEPATH.$application_folder.'/');
}

/*
|---------------------------------------------------------------
| DEFINE E_STRICT
|---------------------------------------------------------------
|
| Some older versions of PHP don't support the E_STRICT constant
| so we need to explicitly define it otherwise the Exception class 
| will generate errors.
|
*/
if ( ! defined('E_STRICT'))
{
    define('E_STRICT', 2048);
}

?>

ci_model_remote_open.php:


<?php
/**
 * This file is just a cannibalization of "system/codeigniter/CodeIgniter.php"
 * where everything that is non-essential to model loading has been removed (I hope)
 * Instead of loading a controller and letting it take control, we instantiate the
 * base Controller class and then include the base Model class.
 * This way, we should be ready for an external program instantiating a ci model class
 * after including this.
 */

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

/*
 * ------------------------------------------------------
 *  Load constants
 * ------------------------------------------------------
 */
require_once('config_constants.php');

/*
 * ------------------------------------------------------
 *  Load the global functions
 * ------------------------------------------------------
 */
require(BASEPATH.'codeigniter/Common'.EXT);

/*
 * ------------------------------------------------------
 *  Define a custom error handler so we can log PHP errors
 * ------------------------------------------------------
 */
set_error_handler('_exception_handler');
set_magic_quotes_runtime(0); // Kill magic quotes

/*
 * ------------------------------------------------------
 *  Instantiate the base classes
 * ------------------------------------------------------
 */

$CFG     =& load_class('Config');
$LANG    =& load_class('Language');

/*
 * ------------------------------------------------------
 *  Load controller
 * ------------------------------------------------------
 *
 *  Note: Due to the poor object handling in PHP 4 we'll
 *  conditionally load different versions of the base
 *  class.  Retaining PHP 4 compatibility requires a bit of a hack.
 *
 *  Note: The Loader class needs to be included first
 *
 */
if (floor(phpversion()) < 5)
{
    load_class('Loader', FALSE);
    require(BASEPATH.'codeigniter/Base4'.EXT);
}
else
{
    require(BASEPATH.'codeigniter/Base5'.EXT);
}

// instantiate a "fake" controller
$CI = load_class('Controller');

/*
 * ------------------------------------------------------
 *  Prepare for model instantiation
 * ------------------------------------------------------
 */

// load Model parent class
require_once(BASEPATH.'libraries/Model'.EXT);

?&gt;

ci_model_remote_close.php


&lt;?php
/**
 * Again, cannibalized from the end of "system/codeigniter/CodeIgniter.php",
 * this takes care of cleaning up after a model
 */

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


/*
 * ------------------------------------------------------
 *  Close the DB connection if one exists
 * ------------------------------------------------------
 */
if (class_exists('CI_DB') AND isset($CI->db))
{
    $CI->db->close();
}

?&gt;

And the following is a sample usage inside a script (although it's kind of raw):


&lt;?php

// open the model remote
$system_folder = "CodeIgniter/system";
require_once('ci_model_remote_open.php');

// load my foo model (note you have access to ci constants)
require_once(APPPATH . "/models/foo_model.php");

// instantiate model
$foo = new Foo_model();
$foo->_assign_libraries(); /* you need this, it assigns all the "controller" libraries to the model's $this so stuff like $this->db works as expected */

// hmm, just thought of something, instead of the above 3 commands, you can just do $CI->load->model("foo_model"); but it's a bit more restrictive
// call function
print "<pre>";
print_r($foo->getFooDataset(47, 'bobo'));
print "</pre>";

// close the model remote
require_once('ci_model_remote_close.php');

?&gt;

Notice that you are not restricted even in loading a model from the application/models folder. You can even create models somewhere outside that inherit from Model in the standard CI way and they will know how to use the database defined in CI and do the usual stuff.

Category:Help::Tutorials