Error reporting in a CodeIgniter application - php

Shorter explanation:
I've realised I posted this as a really long-winded explanation - I've left the previous explanation below but added a shorter summary.
In my CodeIgniter application, the error reporting level is set to 0. If I try to reference an undefined index (for example) in a controller or view, no error is outputted which is as expected.
However, I have a library, which loads in a third party class (NuSoap).
If the NuSoap class experiences an error - it will still output the error in my application.
Errors will also be outputted if the error is encountered in the library file itself.
Why is this? If it's being loaded in through CodeIgniter, through a library surely it should inherit the error reporting level?
Previous (long-winded) explanation:
I'm having some trouble understanding how the error reporting is working throughout my CodeIgniter application.
In index.php my error reporting is set up as follows:
if (defined('ENVIRONMENT'))
{
switch (ENVIRONMENT)
{
case 'development':
error_reporting(E_ALL);
break;
case 'testing':
case 'production':
error_reporting(0);
break;
default:
exit('The application environment is not set correctly.');
}
}
I'm using the production environment, so my expected output when an error/warning/notice is due would be that nothing is displayed, but this isn't the case.
It's taken a while to get this far but I've made a couple of discoveries.
The reason I've picked up on this is during testing. My aim was to catch any errors connecting to an API we use which we connect to using a NuSoap client.
When I changed the username/password to make them deliberately incorrect, I found that PHP notices were being outputted from the NuSoap class - however my error reporting level is set to 0.
The error is a PHP Notice (Undefined index)
I have a library which included the main NuSoap class:
<?php
if(!defined('BASEPATH')) {
exit('No direct script access allowed');
}
class NuSoap {
var $nusoap_client;
public function __construct() {
/* Load the NuSoap class */
require_once('../httpdocs/application/libraries/nusoap/nusoap.php');
/* Initialise the NuSoap client */
$this->nusoap_client = new nusoap_client(NUSOAP_WSDL_FILE, 'wsdl', '', '', '', '', 120, 120);
/* Set the credentials */
$this->nusoap_client->set_credentials(USERNAME, PASSWORD);
$this->nusoap_client = $this->nusoap_client->getProxy();
}
}
?>
And the error is coming from the included file /application/libraries/nusoap/nusoap.php
In a seperate controller, which doesn't use the NuSoap library, I placed the following code in the index function:
$arr = array(); $arr['exists'] = true;
echo 'deliberate error - ' . $arr['not_exists'];
die(phpinfo());
Now going on the fact that the NuSoap class is outputting a notice for an undefined error, I would also expect the above to, but it doesn't.
Also - in the PHP Info output the following doesn't make sense to me:
Directive Local Value Master Value
display_errors On On
If display_errors is on - why are they not being outputted here?
To suppress the errors being generated in nusoap.php, I've found that putting error_reporting(0) at the top of the file will do this. What I can't understand is why the error reporting configuration in CodeIgniter isn't affecting this file even though it is loaded in by a CodeIgniter library?

It seems that it was only happening in a library when another library was loaded before the library in question.
The library causing the issue was PHPGrid, which was setting display_errors to 1.

Related

Set minimum PHP error reporting in Monolog ErrorHandler

Just started using Monolog to log errors in my PHP project but I want to set the minimum error reporting setting to NOTICE and above. The code Im using right now
use Monolog\ErrorHandler;
$handler = new ErrorHandler($logger);
$handler->registerErrorHandler([], false);
$handler->registerExceptionHandler();
$handler->registerFatalHandler();
Which generates all errors including NOTICES. How can I set the equvalent to
error_reporting(E_ALL & ~E_NOTICE);
using Monolog
The ErrorHandler will catch all levels of trigger_error unless you silence them by using the # operator or actually setting your error_reporting by error_reporting(E_ALL & ~E_NOTICE);
If for some reason you want to keep error reporting but at the same time filter out which of those errors are caught by the monolog error handler, I'd go with extending the error handler and registering that instead. Something like this:
class MyErrorHandler extends Monolog\ErrorHandler{
public function handleError($code, $message, $file = '', $line = 0, $context = [])
{
if($code === E_NOTICE){
return;
}
parent::handleError($code, $message, $file, $line, $context);
}
}
use MyErrorHandler as ErrorHandler;
$handler = new ErrorHandler($logger);
$handler->registerErrorHandler([], false);
$handler->registerExceptionHandler();
$handler->registerFatalHandler();
Please note that I haven't actually tested this, but I find no reason it won't work
Monolog logging levels are unrelated to PHP logging levels. PHP logging levels as set by error_reporting() control what types of things the PHP engine itself reports inside its own output. Monolog logging levels emulate unix syslog levels and are intended to be driven by the application, not by PHP. I.e., error_reporting() handles messages generated by PHP, while Monolog handles messages generated by your app. For example, within your application, when you issue a log, you indicate its severity:
if ($some_not_important_condition) {
$logger->info('foo');
}
if ($some_important_condition) {
$logger->error('bar');
}
Thus, your app is always creating info level log entries, and it's up to the run-time configuration to decide which to ingore and/or where they go. For example, you might print to the screen in development or log to Nagios in production.

MAMP throwing error on Yii application - "Use of undefined constant home - assumed 'home'"

I have a Yii app that I know the app has been working on a live environment. When I come to running it on a local environment I get the following error:
"Use of undefined constant home - assumed 'home'"
This is the code that is runnning before the error is thrown:
if(isset($pageID)){
$page = Page::model()->findByPk($pageID);
} else {
$url = Yii::app()->getRequest()->getQuery('action');
if(isset($url)){
$page = Page::model()->findByAttributes(array('url'=>$url));
} else {
$page = Page::model()->findByPk(2);
}
}
The line:
$page = Page::model()->findByPk(2);
... is highlighted in the stack trace. After commenting out everything aside from this line, the notice is still served. I suspect this means the problem is with model code Page.php.
It's a straight-forward bit of code that works on the live server no problem.
Yii is good at detailing it's errors and highlights the actual area that breaks:
/yii/framework/db/ar/CActiveRecord.php(386)
* }
* </pre>
*
* #param string $className active record class name.
* #return CActiveRecord active record model instance.
*/
public static function model($className=__CLASS__)
{
if(isset(self::$_models[$className]))
return self::$_models[$className];
else
{
$model=self::$_models[$className]=new $className(null);
$model->_md=new CActiveRecordMetaData($model);
$model->attachBehaviors($model->behaviors());
return $model;
}
}
I don't in all honesty understand what this error means or what's causing it. I've tried all sorts of things to rectify or further understand what's going wrong and I'm drawing a blank. It doesn't appear to be connectivity to the database (which has been correctly amended to local settings). .htaccess seems fine, mod-rewrite it turned on. The config.php file calls in the necessary models etc. Not sure where to go from here.
Why is this error being thrown and how do I go about fixing it?
Update
I've isolated the problem within model Page.php
The notice doesn't load after omit some contants such as:
const HOME=home;
const ABOUT=about;
I assume that this didn't occur before because I was using an older version of MAMP or different php.ini setup.
Setting
error_reporting = E_ALL & ~E_NOTICE
within php.ini cleared the error.
Still left wondering why PHP doesn't like these constants defined in this way and what the correct way is.
This kind of error (or, to be precise: this kind of notice) is most often the result of omitting $ before a variable name. If there's home where $home should be, the interpreter treats it like a constant, but since such constant hasn't been previously defined, notice is thrown and string value assumed ('home' in this case).
The reason you're not getting the notice on your other machine is most likely due to notices being suppressed there.
The snipped you pasted doesn't look like it could be responsible for this (especially since it's from one of Yii classes); are you sure you're not pasting code from somewhere higher in the entire stack trace?

error handling in codeigniter

In my project to catch all the PHP errors I have set up my error handling mechanism as follows:
I have set error_reporting() in index.php file which overrides
anything in the php.ini file
An error handler is set in system/codeigniter/CodeIgniter.php using
set_error_handler - this error handler, _exception_handler, is
found in system/codeigniter/Common.php
The _exception_handler function ignores E_STRICT errors, calls the
show_php_error function From the Exceptions system library if the
severity is that specified by your error_reporting() function in
index.php and logs the error according to whatever you have set up in your config.php file
The handler returns FALSE so after this PHP goes on to handle the
error however it normally would according your error_reporting level
and display_errors setting.
The thing that is puzzling me is that E_ERROR errors i.e. fatal errors don’t seem to be being caught by _exception_handler at all. It’s not just that show_php_error isn’t being called, it looks like the function just isn’t being called for them. This is obviously a problem as it means that they aren’t get handled by show_php_error or logged. For example if I deliberately mistype $this->load->views('foo'); in a controller, the handler doesn’t get called.
Any suggestion about error handling would be much appreciated, thanks!
Now this is a rather big debate:
Whether you should catch the fatal errors or not.
Some say that they are FATAL so you dont know in which condition is the system but I will go with the "try to do the cleanup if the error occured".
In order to catch ALL fatal errors you will need to setup a pre_system hook.
go to application/config/hooks.php and enter
$hook['pre_system'][] = array(
'class' => 'PHPFatalError',
'function' => 'setHandler',
'filename' => 'PHPFatalError.php',
'filepath' => 'hooks'
);
after that go to hooks directory and add your handling of the error:
<?php
class PHPFatalError {
public function setHandler() {
register_shutdown_function('handleShutdown');
}
}
function handleShutdown() {
if (($error = error_get_last())) {
ob_start();
echo "<pre>";
var_dump($error);
echo "</pre>";
$message = ob_get_clean();
sendEmail($message);
ob_start();
echo '{"status":"error","message":"Internal application error!"}';
ob_flush();
exit();
}
}
as you can see we are using the register_shutdown_function to run a function that checks if an error had occured and if it had send it via email to the developer.
This setup is working flawlessly for over 2 years in several CI projects that I have been working with.
I've found this answer under an other question (https://stackoverflow.com/a/3675357), and i think it is also useful for anyone reading this question.
"For codeigniter specific error handling, you can override its 'Exception' library class by creating My_Exception class in your application/libraries folder. Copy original library function signatures into it and put in your code. It will surely work."
Simply you can handle all type of error in one file which is display
your client because of php error or any other error is not good to
display client.
Simply place file Common_Exceptions.php in core folder . Common is my because in config file I have declare $config['subclass_prefix'] = 'Common_';
Copy system\core\Exceptions.php file and paste in core\Common_Excepions file (class Common_Exceptions extends CI_Exceptions) and do your change in this file and call view for your want and display to client when error come.
NOTE: $config['log_threshold'] = 1; enable in config file for errorlog write and after you see what error come.
One more suggestion on view file which is display when error is come there place time so when you see in log then match this time and find which error is come that time

Zend Framework 2 not displaying errors when instantiating classes which don't exist

I'm having problems debugging my code whilst trying to learn Zend Framework 2.
Intially I have been trying to implement Zend\Captcha\ReCaptcha and kept receiving black pages. However I have worked it back to the fact that when I attempt to instantiate an object from a non-existent class I do not get any errors. Just a blank page.
E.g:
public function indexAction()
{
new Zend\Captcha\ReCaptcha();
//or
new Some_Class_Which_Doesnt_Exist();
}
The result is a blank page. If I comment the instantiations out I get my standard layout page.
My PHP error reporting is set as:
error_reporting = E_ALL | E_STRICT
I'm guessing this is something to do with Zend Framework. Can I force it to display errors to help me with debugging?
Check display_errors option in php.ini, maybe it is set to 0.

Can I get PHP to throw an error when I try to define a function that has already been defined?

I run into this problem periodically, and I'm trying to figure out if it's a configuration issue or a peculiarity with PHP.
Basically, there will be a function foo() defined somewhere in my code, and then elsewhere I will accidentally define a function again with the same name foo(). I would expect an error of some kind to be thrown, e.g. "Fatal Error: Function already defined line 234, bar.php blah blah".
But I get nothing. I just get a blank screen. Debugging can take an eternity as I try to pinpoint exactly where the function is being accidentally redefined, without help from an error message.
My config settings for reporting errors are set to E_ALL, and I see all other kinds of errors without a hitch.
Any insights? Is there anything I can do to cause PHP to report these errors (so that I can either rename the offending function or wrap it in an if function_exists() clause)?
Edit: To be clear, I understand the many strategies to avoid namespace collisions in PHP. I'm talking about instances where for whatever reason I accidentally name a function a name that already exists during development (or for example I import a file where a function has already been defined). I would expect an error message when this occurs, which would help me debug, but I do not get one.
You can wrap function definitions in a conditional function_exists():
if (!function_exists("file_get_contents"))
{
function file_get_contents(....)
....
}
works for me.
You could wrap a function_exists check around each function and have it throw an error message if it already exists. The better way however would be finding out why fatal errors don't appear on screen. Can you check phpinfo() for the error_reporting and related settings?
This is what you should be getting when trying to redefine a function:
Fatal error: Cannot redeclare file_get_contents() in D:\xyz\htdocs\test.php on line 5
From my phpinfo():
display_errors On
error_reporting 22519 (equals... well, I don't know but it shows errors :)
In some hosting environments when error reporting was turned off completely, I have found defining a custom error handler very helpful: set_error_handler()
Are you hosting the script on your local server? I know a UK based hosting company that prevent any PHP errors from being returned at all, even if you've set E_ALL.
If this is the case consider testing the app locally with error reporting turned on.
As an alternative, you can actually check whether a function is already there by using function_exists.
if (function_exists('foo'))
{
echo 'foo function exists !!';
}
else
{
echo 'foo function does not exists !!';
}
Some suggestions to make your life easier:
I typically will create a generic functions file, where I store all my global functions that I'll be using throughout my app.
I'll also try and remain as object-oriented as possible. PHP will give errors if you're creating an object that already exists, and by encapsulating your functions into logical objects you'll have an easier time maintaining it.
It seems you're not organizing your code properly, try using a common library that you include in your files, and define functions there. Perhaps you just need to start uses classes, then you won't have collisions when you have two functions with the same name.

Categories