Changing PHP error_log behaviour possible? - php

I'm wondering if it's possible to change the default behaviour of PHP's error_log() functionality to include the source and originating line number by default.
I am guessing this could be potentially be done either with a PHP ini setting or by configuring apache in some specific way, though not being an apache guru I'm not sure how this would be made possible.
In my default environment, finding the source of the errors in a log generally doesn't pose too much of a problem where the error is legitimately spawned by a PHP warning or notice, as it will report automatically where the line originates... however, calls made manually by programmers to PHP error_log() don't do this, and I can't find a way to make this behavior default.
I am aware that generally speaking you can achieve the line reporting manually with the magic constant like this:
error_log("Failed to login to MySQL ".__LINE__);
However, I am curious and open to suggestions about if there are any ways to perhaps configure the way errors are reported universally in the log or anything else to get around changing every single call in code to include the magic constant.

You can define your own error handler using the set_error_handler function. This allows you to do with the errors whatever you like, as long as it is within the scope of PHP language (including printing the file and line where the error occured). Most common course of action in this case is to convert the error into a ErrorException.
Also you can use tools like xDebug, which, when activated in php.ini, display the errors in more readable form.

Related

Slim error handling

The Slim Framework is good - seriously good. One of the issues I have run into is with the way it handles errors. In vanilla PHP code I occasionally use trigger_error statements as a debug aid. In vanilla PHP this has no untoward consequences since by default trigger_errors are E_USER_NOTICE type errors that do not stop the script dead in its tracks. However, in Slim things appear to work differently. A benign trigger_error causes it to throw a wobbly and an HTTP 500 is returned.
I thought this could be corrected by
Changing the mode to development or something but the docs state that this makes no difference whatsoever to the way Slim works internally.
Next port of call - changing the slim error logging level
$app = new \Slim\Slim(array('log.level' => \Slim\Log::ERROR);
does not quite have the same effect as PHP's error_reporting. Setting it stops the error from floating up to the error.log file (the default error logger used by Slim) but crucially it does not stop the HTTP 500.
I have come across forum posts that suggest replacing the default Slim::handleErrors method. That would be easy but I wonder if that is not incorrect. What is the right way to stop Slim coming to a dead halt when it runs into a wholly innocuous trigger_error? I can well avoid this but I may rely on other code that may have such statements. I would much appreciate any help
The answer turns out to be quite simple. I figured it out by checking out the handleErrors function in slim.php. Just issue a
error_reporting(E_ALL & ~E_USER_WARNING);
prior to where the trigger_error is called and you are in business. Somewhere down the line Slim is changing the default PHP error_reporting to include E_USER_WARNING.

Is there any way around the "parse error of death"?

I'm pretty sure I'm not only one who has noticed that simple parse errors on PHP, if present in very nested scenarios (eg, an object instance which references another object instance which references another object instance that has a very tiny parse error, all of them being auto loaded) can make PHP hang forever instead of reporting the parse error and halting the execution like it would normally do — I've seen this many times and in very different code bases, always with the proper error_reporting setting set.
Is there any way around it? i.e., can it be forced to display the parse error report as it should somehow?
For the record, I'm 100% sure these hangs were caused as a result of PHP not handling the parse error correctly, as I have debugged this behaviour many times; the reason I ask is because when these hangs happen one is basically left in the dark, not even being able to tell whether PHP is acting funny or there really is an malfunctioning loop in the code somewhere — this takes time to debug, time that could be saved if, you know, PHP reported the parse error like it should.
As partially mentioned in the comments, error_reporting(E_ALL) can help display all errors. You might also have to use ini_set and make display_errors have a value of on.
Personally, I think your question is not very clear, and you should improve formatting and make it more understandable.
UPDATE: Your server / computer you're running the code on seems to be very slow. No 'hanging-around' should really occur. Or could you describe it with further detail?
Also, you might be stuck in an infinite or near-infinite loop. Check closely in your code, because unless you post all your code, this is the limit to which we can help you.
UPDATE 2: It seems that you may have mistyped the name of an object when you are trying to call it. Otherwise, it may be that you have not declared your object correctly.
Most likely one or the other.
Turns out the culprit was xdebug.collect_params, which the documentation very correctly suggests to keep disabled. Certain errors were simply generating a very large amount of data in the arguments of the call stack trace which exhausted xdebug with collect_params set to 4 and made xdebug and by extension PHP to hang, even though I have a custom exception handler in place which never actually retrieves the stack trace from xdebug, but apparently xdebug collects this data anyway.
This was hard to debug because: a) it was not straightforward to replicate b) profiling with xdebug did not help c) stepping through the code with xdebug + dbgp was not helping either d) almost no trace (no pun intended) was left other than very ocasionally logging the errors to the php error_log file and e) with a custom exception handler it was not obvious to suspect of xdebug, since I didn't involve it in the process of handling the exception, or so I thought.
So there is no such thing as the parse error of death, and I learned to never assume it's not my fault :) Hopefully this answer will help others in the future at least.

White page even with full error_reporting and display_errors

I have a really, really weird situation here. I'm working on a local development server with Zend Server installed. I have full error reporting and display errors, but I'm still getting a white page. Of course, I understand that i've done something wrong, but i want to have an idea WHAT it is i've done wrong.
The system i'm currently working on depends heavily on classes, includes and so on, therefore i can't simply "check" a page (i.e. run it standalone, outside the system, call it directly and stuff). That just won't work.
I've checked the syntax, that's not the problem. I'm stuck, and want to see my errors. If you have any ideas, please tell me!
Just to make clear, I'm already using the following:
ini_set('display_errors', true); error_reporting(-1);
After using an own error handler (php.net/set_error_handler) and some hard debugging (echo's, exits and so on), i found out that i was overruling a variable that was used later on. The variable used to be an object, but was now an int. Weird though that there wasn't any error about the fact that i was calling a function on non-object...
Very weird, but i'm glad that i've found the bug in my application.
You should be able to set the error log in your php.ini. Everything should be properly listed there. We use that approach for some of our sites, since we do not want customers to be able to see error messages on production servers.
try logging what key variables are in several of the classes. Worst case scenario, throw in some echo statements here and there just to stay sane.
error_log(print_r($var, true));

PHP - Is there a way to ignore fatal errors in php.ini/ini_settings only without modifying the code?

I inherited some PHP source code, and I have to maintain it. It has been built from scratch using no framework, just the former developer's own creation.
Now, I ask this:
Is there a way to ignore fatal errors in php.ini/ini_settings only without modifying the code?
Scenario:
SomeClass.php:
<?php class SomeClass {
...)?>
index.php:
include("SomeClass.php");
...
include("SomeClass.php");
In my development box, this throws a Fatal Error exception (because SomeClass has been declared twice), which is the obvious and expected behavior.
Here is the kicker: This source is hosted somewhere, and it works. I just don't ANY access to that server.
So I see here two scenarios:
1.) There is a way to silence this Fatal Error via 2 includes by an ini setting. This I have to know.
2.) The former developer did NOT give me the exact, updated source code that is currently up and running. I then have to insist that he give me the latest source code, but I can only do this if I am 100% sure that there is no way #1 can happen.
What do you guys think?
I tried setting a set_error_handler() function that doesn't die on fatal errors, but instead Apache crashed. In other words, PHP needs to die so that the system doesn't.
So, sorry, I really don't think there is a solution for that.
Fatal errors don't come from the include function - only warnings. You'd get fatals from require, though. Use #include and it won't even generate the warning.
Error reporting is mostly discouraged on production servers. Why let the user see if your script didn't find a file. Have a look at this http://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors and http://www.php.net/manual/en/function.set-error-handler.php. The latter could be helpful, go through the page for examples. I suggest to log errors instead of displaying it. But that will involve some sort of workaround with code.
inform your developer that he should use __autoload or spl_autoload to avoid such errors…

PHP: Code checker since PHP is a loose type / dynamic language?

I have a small PHP web-based application that is beginning to grow moderately in size.
I'm starting to become concerned with managing my PHP code base, given PHP is a loosely/weak typed, dynamic language.
How do others manage their code based for loosely/weak typed, dynamic languages?
Do pre-parsers exist for PHP that allow me to runs checks on my code base to identity such things like below?
$var1 = 'data';
// vr1 doesn't exist, it's a typo of $var1, but PHP would allow for this and not complain
echo $vr1;
UPDATE:
The example above might not be the best example but essentially, what I'm trying to convey is that certain errors in a dynamically weak typed language would only be found when the code is run in production at RUN TIME; whereas, some of these issues would typically be found in strongly typed static languages at COMPILE time.
How can I also find these non-algorithm type of errors in PHP prior to moving my code into production without having to create an insane number of Unit Tests?
As such, does anything exist where I can run my PHP code through it, prior to moving into production, and this pre-processor parses my code to ensure I'm only using defined variables, etc. Essentially, check my code for validation for non-algorithmic type of uses. E.g. not trying perform algebra on a string, etc.
UPDATE 2
Please note, this question is still not answered because I'm looking for a way to identity these type of non-algorithmic errors in PHP at "compile" type, not RUN TIME.
You can lint your PHP with php -l filename.php. This would show any syntax errors.
There is IDEs out there that will lint while you write the code. Those usually can also detect issues like shown in your question in addition to linting.
Apart from this, consider writing UnitTests for your code to ensure functionality and have a look at http://phpqatools.org for a number of other tools that can assist you in increasing code quality.
Make sure you have error_reporting(-1); set during development to enable all errors, in addition to enable display_errors and display_startup_errors in php.ini. Disable the latter two on your production system to prevent exposure of server information.
Edit after update: PHP source code is compiled on-the-fly. PHP's compile time is effectively at run time. If you want compiled PHP, you have to use Facebook's HipHop.
PHP will definitely complain about that with either a warning or a notice if you set your error_reporting config directive appropriately.
See:
http://us2.php.net/manual/en/errorfunc.configuration.php#ini.error-reporting
Runtime Errors
Uninitialized variables are runtime errors (of level E_NOTICE) in PHP, so you can only see them at runtime. The example you gave may or may not end up erroring, depending on how the code is executed. For instance, it could be that $vr1 is defined in a conditional include() that is sometimes included and sometimes not.
Additionally, it's possible to dynamically create variables at runtime using variable variables ($$var), so again that $vr1 may actually be defined somewhere. If the PHP interpreter failed to run valid syntax, or gave compiler errors on valid syntax, that would be a different sort of problem.
You might compare the uninitialized variable circumstance to a divide by zero error. It's not an error unless it actually happens.
Compiletime errors are E_PARSE, E_COMPILE_ERROR, or E_COMPILE_WARNING (not fatal) in PHP. These include things like missing files, functions, or classes, i.e. trying to execute code that isn't there—something PHP can't possibly do. If PHP may be able to, it will try.
Detection and Prevention
At the very least, you should make sure that your development and testing environments have all of the PHP error junk turned on in the ini:
error_reporting = E_ALL|E_STRICT
display_errors = On
Or at runtime:
error_reporting(-1);
Self Discipline
A few tips for working with PHP that might help:
Use functional programming
Establish code smells and write clean syntax
Do your own type checking (OOP and functional programming can make this easier)
Avoid the global scope and include()-based control structures
Use an IDE with code awareness aids, like Netbeans.
For instance, in your example above, if you have to pass your variable into a function or method that checks that the parameter isset() or !== nullbefore using it, you can avoid or mitigate the problem of uninitialized variables.
Resources
Comparison operators (see Identity, specifically)
Type comparison tables
is_int(), is_float(), etc.
That type of error would be caught if you set error reporting to the max. It would give a Notice indicating that $vr1 wasn't set.
You can set error reporting in your php.ini file, or on individual pages using the ini_set() function.
The closest thing is php's lint checker, but that's more of a syntax checker. You can run lint from a command line:
php -l path/to/file.php
You could build this into your file repository system by setting up a pre-commit check.
As PHP is not usually considered to go through a separate COMPILE process perhaps you could explain at what point you consider your code to be COMPILED?
Here's another SO question that focuses on PHP code analysis tools.
Hack is a statically typed language created by Facebook which is essentially PHP with many features added and removed.
PhpStorm is an IDE which provides "inspections" which catch many things that would be caught by a static type checker, such as the undefined variable in your example.
I started writing a static type checker for PHP here based on PHP7 type hints and PHPDoc annotations. I never finished it but there are some passing tests and the design so far seems to be sound.

Categories