1

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?

UPDATE

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
2
  • Looking closer at the error message of "approach 2" leads me to ask; Is Custom_library a controller i.e. class Custom_library extends CI_Controller??? Commented Nov 1, 2016 at 11:43
  • Custom_library is a library stored at application/libraries not extending CI_Controller but -> class Custom_library { ... Commented Nov 1, 2016 at 11:54

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your input. I updated my question - not sure if I applied your suggestion the right way.
See my much revised answer.
Thank for vital insights about codeigniter which headed me to a workaround. I'll post it in a couple of days.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.