Log core error messages in database |
[eluser]ilumos[/eluser]
Hi Guys, What's the best way for me to log the error messages generated internally by CodeIgniter? I plan to log them in a database, and fall back to a file if the database is unreachable, but without hacking the core I'm not sure how to best capture the messages. Any help appreciated, thanks in advance!
[eluser]Aken[/eluser]
You can extend the Log library and add your own code to the write_log() method.
[eluser]ilumos[/eluser]
So I've extended the log library and I'm met with this error: Code: Fatal error: Class 'CI_Controller' not found in /Users/ilumos/Sites/lanager/system/core/CodeIgniter.php on line 233 I'm using modular extensions. Here's my /application/libraries/MY_Log.php Code: class MY_Log extends CI_Log (I've commented all references to $CI as this seems to be the culprit. I seem to be having the same problem as this guy: http://stackoverflow.com/questions/88788...-not-found Any help appreciated Thanks
[eluser]Aken[/eluser]
The problem is happening because the log_message() function - which utilizes the Log library - is being used before the CI_Controller singleton is available. You'll likely need to add a check to see if the CI_Controller class is available yet, and if it is, then use the get_instance() function. Then, when using $CI, you'll have to make sure it's set appropriately first (or just do it inside the first check's if statement if you aren't utilizing the constructor to assign $CI). Chances are you're trying to log errors that occur in your controllers, which would mean the DB functions would be available by then. You'll just be without DB logging for those earlier debug messages that occur when some Core files initialize. Look through the order that system/core/CodeIgniter.php goes through, and you'll get a gist of when CI_Controller first becomes available.
[eluser]ilumos[/eluser]
[quote author="Aken" date="1343020941"]Then, when using $CI, you'll have to make sure it's set appropriately first (or just do it inside the first check's if statement if you aren't utilizing the constructor to assign $CI).[/quote] I'm using isset($CI), is that correct? I've hit upon another problem when trying to load a helper: Code: Fatal error: Call to a member function helper() on a non-object What further checks do I need to do to make sure I can load the required helper? New code: Code: function log($category, $severity, $message, $data = NULL, $file = '', $line = '')
[eluser]Aken[/eluser]
The load property doesn't exist until a controller (which extends CI_Controller) is actually instantiated - you'll need to make sure it exists also before using it.
[eluser]PhilTem[/eluser]
I'm not sure that your new code is good, because - according to the PHP docu on class_exists(), second parameter: If the class cannot be found, then it will use the autoloader. And I'm not sure the CI-autoloader is registered at that time. So you might eventually screw up the whole business logic of CI. A workaround would be to look at the CI files starting in index.php and follow the source code. You will see that you can access every core class also via something like Code: global $IN which also refers to the input class but not via $this so it's not assigned to a property of CI_Controller. That should fix your problem: Having a look at ./system/core/CodeIgniter.php ![]()
[eluser]Aken[/eluser]
Phil brings a good point with the __autoload parameter for class_exists(), however: 1) CI doesn't have any __autoload or related functionality. 2) Even if it did happen to include the system/core/Controller.php file, it wouldn't instantiate it, so it shouldn't alter the original logic (at least to the best of my knowledge). Also, I don't think the global variables inside CodeIgniter.php would be of any use to his goal, since he wishes to use the session and database libraries. You can always load helper files manually using include/require, but you'd have to make a note to whether or not they use get_instance(). If they did, you'd run into the same issues.
[eluser]PhilTem[/eluser]
Just looked at the CI source code. Could have sworn I saw the 'spl_autoload_register()' there once. But it's no longer there. So you can kinda forget half my post above. But anyway one should be cautious with using 'class_exists()' due to the call of __autoload of the class in question if it's not yet instantiated ![]() ilumos might however use Code: load_class() to load the classes while there's no $this->load available. Maybe somebody with more insight on the CI core can shed some light? I could only guess what would be best to solving this problem ![]()
[eluser]Aken[/eluser]
Okay, I came up with what I think is a pretty good solution for this: use the post_controller_constructor hook to tell the log class when it can use DB resources. The hook fires after the controller class is instantiated, but before the controller method itself is called. So you won't be able to use any DB logging before this point, but anytime after. If you use the MY_Log.php file I include below and log the debug messages, you'll see when it first becomes available. If you want to be able to log to the DB prior to this point, you'd have to do a lot more hacking. 1) Enable hooks in your /application/config/config.php file. 2) In /application/config/hooks.php, add the post_controller_constructor hook: Code: $hook['post_controller_constructor'] = array( 3) Create the hook file itself at /application/hooks/LogHook.php Code: <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 4) Create your extended log library at /application/libraries/MY_Log.php - See some notes in the comments regarding this file. Chances are you'll check it to add your own functionality anyway, this is just the base necessity Code: <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 5) Use log_message() like normal in your controllers, models, libraries, etc. Give that a shot, modify it to your needs, let me know if anything doesn't work or if you have questions. |
Welcome Guest, Not a member yet? Register Sign In |