Reputation: 13
I want to extend the /system/core/Log.php
library with a couple of functions. One function should send a mail in case of an error via the custom function sendMail()
which is part of the Custom_library.php
.
Thus, I created the file /application/core/MY_Log.php
class MY_Log extends CI_Log {
public function __construct()
{
parent::__construct();
}
public function write_log($level, $msg)
{
$result = parent::write_log($level, $msg);
return $result;
}
}
The problem: I'm not able to load the Custom_library.php
. None of these approaches worked:
//approach 1
$this->load->library('Custom_library');
//approach 2
$CI =& get_instance();
$CI->load->library('Custom_library');
Error message of the approach 2:
Fatal error: Uncaught Error: Class 'CI_Controller' not found in /home/gp/public_html/system/core/CodeIgniter.php:366 Stack trace: #0 /home/gp/public_html/application/core/MY_Log.php(13): get_instance() #1 /home/gp/public_html/system/core/Common.php(478): MY_Log->write_log('error', 'Severity: error...') #2 /home/gp/public_html/system/core/Exceptions.php(105): log_message('error', 'Severity: error...') #3 /home/gp/public_html/system/core/Common.php(662): CI_Exceptions->log_exception('error', 'Exception: Clas...', '/home/gp/public...', 366) #4 [internal function]: _exception_handler(Object(Error)) #5 {main} thrown in /home/gp/public_html/system/core/CodeIgniter.php on line 366
The question: Is it possible to load and utilize a Library in a Core Class?
I tried the approach via the function &load_class
.
function &load_class($class, $directory = 'libraries', $param = NULL)
{
static $_classes = array();
// Does the class exist? If so, we're done...
if (isset($_classes[$class]))
{
return $_classes[$class];
}
$name = FALSE;
// Look for the class first in the local application/libraries folder
// then in the native system/libraries folder
foreach (array(APPPATH, BASEPATH) as $path)
{
if (file_exists($path.$directory.'/'.$class.'.php'))
{
$name = 'CI_'.$class;
if (class_exists($name, FALSE) === FALSE)
{
require_once($path.$directory.'/'.$class.'.php');
}
break;
}
}
// Is the request a class extension? If so we load it too
if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))
{
$name = config_item('subclass_prefix').$class;
if (class_exists($name, FALSE) === FALSE)
{
require_once(APPPATH.$directory.'/'.$name.'.php');
}
}
// Did we find the class?
if ($name === FALSE)
{
// Note: We use exit() rather than show_error() in order to avoid a
// self-referencing loop with the Exceptions class
set_status_header(503);
echo 'Unable to locate the specified class: '.$class.'.php';
exit(5); // EXIT_UNK_CLASS
}
// Keep track of what we just loaded
is_loaded($class);
$_classes[$class] = isset($param)
? new $name($param)
: new $name();
return $_classes[$class];
}
If I run the function $CI =& load_class('Custom_library');
it finds the right file but than is looking for the Class with a prefix "CI_" and thus throws and error message:
Fatal error: Uncaught Error: Class 'CI_Custom_library' not found in /home/gp/public_html/system/core/Common.php:196 Stack trace: #0 /home/gp/public_html/application/core/MY_Log.php(14): load_class('Custom_library') #1 /home/gp/public_html/system/core/Common.php(478): MY_Log->write_log('error', 'Severity: error...') #2 /home/gp/public_html/system/core/Exceptions.php(105): log_message('error', 'Severity: error...') #3 /home/gp/public_html/system/core/Common.php(662): CI_Exceptions->log_exception('error', 'Exception: Clas...', '/home/gp/public...', 196) #4 [internal function]: _exception_handler(Object(Error)) #5 {main} thrown in /home/gp/public_html/system/core/Common.php on line 196
Upvotes: 1
Views: 5067
Reputation: 8964
Extending CI_Log
is not going to work if you need to access other libraries. The reason is CI_Log
is created long before $CI
is created so no "instance" is available for &get_instance()
to return.
$this->load
doesn't work because $this
is not a controller ($this
and $CI
point to the same object) and the class load
('CI_Loader') hasn't been created yet either.
There might be more than one way around this. Seems to me the least hacked way is to make your logger class utilize CI_Log
instead of extend
it.
application/libraries/Logger.php
class Logger
{
protected $CI;
public function __construct()
{
$this->CI = & get_instance();
$this->CI->load->library('custom_library');
}
public function write_log($level, $msg)
{
//do stuff with "custom_library"
$this->CI->custom_library->some_function();
//use the built-in logging mechanism, a.k.a. CI_Log
return log_message($level, $msg);
}
}
Your `logger' will need to be loaded in a Controller the same as any other library.
$this->load->library('logger');
A usage example might be something like this
$this->logger->write_log('error', "This is FUBAR");
By the time you call $this->load->library('logger');
the log
class has been created and is part of $CI
(a.k.a. $this
). So this line
//use the built-in logging mechanism, a.k.a. CI_Log
return log_message($level, $msg);
could be done this way instead
//use the built-in logging mechanism, a.k.a. CI_Log
return $this->CI->log->write_log($level, $msg);
That would be marginally more efficient since all log_message
does is call log->write_log
anyway. I don't see any problem doing this instead of using log_message
.
Interesting question and I learned a bunch by looking into it. Thanks.
Upvotes: 3