rmdir() displays a few warnings like the dir does not exist, or permissions did not allow. How can I capture which reason for failure and react to it?
rmdir does not throw Exception so you cannot catch them with try/catch. What you can do is use error_get_last function to do what you need.
Try something like this:
if (!#rmdir('/root')) {
$error = error_get_last();
if (preg_match('/something/', $error['message'])) {
// do something
} elseif (preg_match('/somethingelse/', $error['message'])) {
// do something
}
}
You can check beforehand if you are allowed to do some kind of action like file_exists() and is_ dir() to check if a directory exists and fileperms() or just is_ writable() to check if you can write a directory.
You can also try to "catch" the error like with exceptions. you can specify a custom error handler, but this seems to be a bit overkill.
Related
So I have a code like this:
for($x=1;$x<=3;$x++)
{
try
{
$c = new client($user_id, $ident);
log("Client initialized successfully...");
break;
}
catch (Exception $e)
{
log("Error in attempt($x)to init client");
}
}
My question is, is there any possibility that an exception can be thrown after the line log("Client initialized successfully...");? Because if yes, then it will mean that the log will have both success and error messages for the initialization process. Technically the exception should only rise when the new client object is initialized, but I am not certain...
Well, yes it can if function log throws an exception, and also if I were you I would rename the function name, because there is a function log already:
http://php.net/manual/en/function.log.php
It is only possible if the log function throws an exception.
Alternatively, you could have a $success variable that is initialized to true. You set it to false in the catch. Then check it after the entire try/catch block.
Exception can only be thrown here in lines:
$c = new client($user_id, $ident);
or
log("Client initialized successfully...");
( we don't know what function log does).
It's quite strange, that you try in loop initialize object 3 times - do you expect many errors here?
i need capture the last error on function "include" PHP.
I test with the functions "Exceptions", but unfortunately i have written above the function "include".
If I write after the function "include" does not show the exception.
Example 1:
try{
throw new exception();
require_once( $this->controller['path'] );
}
catch( exception $e )
{
print_r( error_get_last() );
}
This Return: ...(Void)...
Example 2:
try{
require_once( $this->controller['path'] ) OR throw new exception();;
}
catch( exception $e )
{
print_r( error_get_last() );
}
This return: Parse error: syntax error, unexpected T_THROW in...
I purposely created a syntax error in the file to include. The idea is to trap the error so that you can debug them.
Anyone have any idea how to get this?
Guys! I need to catch syntax errors. Greetings!
First, if you use require, it's always going to kill your app if the file cannot be included. There's no control over the outcome, you cannot do anything afterwards. If you want to have control over the success of file inclusions, use include and test its return value.
$success = include "foo.php";
if (!$success) {
// the file could not be included, oh noes!
}
You can have syntactical differences on that like:
if (!(include "foo.php")) ...
This will trigger an E_NOTICE if the file cannot be included, which you cannot catch. But that's OK, since it'll help you debug the issue and the display of errors will be turned off in production anyway (right, right?).
or throw new Exception doesn't work because throw is a statement and cannot be used where an expression is expected.
If you want to catch syntax errors in the included file, use php_check_syntax/it's successor php -l <file>.
require_once is a language construct and not a function and you can't do short circuit with it.
To test if the file exists before you include it, you can use is_file(). If you want to test if the file is readable, you can use is_readable().
You may also want to use include which issues a E_WARNING if the file could not be found, not a E_COMPILE_ERROR.
i agree with alex, try to cath error with check the file_exists() then use an Exception
if(file_exists($this->controller['path'])){
try{
require_once( $this->controller['path'] );
}catch(Exception $e){
// throw error
}
}
or use is_readable()
if(is_readable($this->controller['path'])){
try{
require_once( $this->controller['path'] );
}catch(Exception $e){
// throw error
}
}
Most native PHP functions trigger errors rather than throwing exceptions. To convert PHP errors into exceptions you can set up a custom error handler:
function exceptions_error_handler($severity, $message, $filename, $lineno) {
throw new ErrorException($message, 0, $severity, $filename, $lineno);
}
set_error_handler('exceptions_error_handler');
With this code you'll be able to catch all non-fatal errors as exceptions. Note that require_* functions throws fatal error, thus you'd have to use include instead.
As for handling syntax errors within the code itself, it is quite impossible, if you think about it a bit.
There is a way to check with a "IF" if a function fails in php?
Ex.
If (getimagesize($image) returns and error) {
echo 'Error: function dont work';
}
else
{
// do something
}
Thanks!
I 'm assuming you are interested specifically in a function like getimagesize, which does not return any error codes and makes it hard on us. But not impossible.
The documentation for getimagesize states:
If accessing the filename image is impossible, or if it isn't a valid picture, getimagesize() will generate an error of level E_WARNING. On read error, getimagesize() will generate an error of level E_NOTICE.
Therefore, you need to do two things:
Get notified of the error and act upon it somehow
Have the error not be displayed or otherwise affect the execution of your program at all (after all, your are going to be taking care of any errors with error-handling code yourself)
You can achieve the first one using set_error_handler() and restore_error_handler(). You can achieve the second with the error-control operator #.
So, the code must go something like this:
// Set our own error handler; we will restore the default one afterwards.
// Our new error handler need only handle E_WARNING and E_NOTICE, as per
// the documentation of getimagesize().
set_error_handler("my_error_handler", E_WARNING | E_NOTICE);
// No error has occured yet; it is the responsibility of my_error_handler
// to set $error_occurred to true if an error occurs.
$error_occurred = false;
// Call getimagesize; use operator # to have errors not be generated
// However, your error handler WILL STILL BE CALLED, as the documentation
// for set_error_handler() states.
$size = #getimagesize(...);
// At this point, my_error_handler will have run if an error occurred, and
// $error_occurred will be true. Before doing anything with it, restore the
// previous error handler
restore_error_handler();
if($error_occurred) {
// whatever
}
else {
// no error; $size holds information we can use
}
function my_error_handler($errno, $errstr, $file, $line) {
global $error_occurred;
// If the code is written as above, then we KNOW that an error
// here was caused by getimagesize(). We also know what error it was:
switch($errno) {
case E_WARNING: // Access to image impossible, or not a valid picture
case E_NOTICE: // Read error
}
// We could also check what $file is and maybe do something based on that,
// if this error handler is used from multiple places. However, I would not
// recommend that. If you need more functionality, just package all of this
// into a class and use the objects of that class to store more state.
$error_occurred = true;
return true; // Do not let PHP's default error handler handle this after us
}
Of course, this is not very maintainable (you have a global variable $error_occurred there, and this is not a good practice). So for a solution which not only works but is also nicely engineered, you would package all this in a class. That class would define:
A method which implements the error handler (my_error_handler in the above example). To set an object method as an error handler instead of a global function, you need to call set_error_handler with a suitable first parameter; see the documentation for callback.
A method which lets the class set the error handler, execute some code of your choice, save the "error happened while executing your code" flag, and restore the error handler. This method could e.g. take a callback provided by your calling code and an array of parameters and use call_user_func_array to execute it. If, during execution, the error handler set from #1 above is called, mark this in a variable in your object. Your method would return the return value of call_user_func_array to the calling code.
A method or variable which the calling code can use to access the result from #2 above.
So then, if that class is called ErrorWatcher, your calling code would be something like:
$watcher = new ErrorWatcher;
$size = $watcher->watch("getimagesize",
array( /* params for getimagesize here */ ));
// $size holds your result, if an error did not occur;
// check for errors and we 're done!
switch($watcher->report_last_error()) {
// error handling logic here
}
...which is nice and neat and does not mess with global variables. I hope I explained this well enough to enable you to write class ErrorWatcher yourself. :-)
Take a look at exceptions. You'll have to throw them in your function though.
Edit: By the way, if your function is not supposed to return a boolean, you can always have it return false if something goes wrong and check like:
$result = getimagesize($image);
if ($result === false)
{
//
}
Whatever the condition is on an "if" statement (what's inside the parenthesis) will return "true" or "false".
If the condition returns "true", the first statement will be executed, otherwise the second statement will get executed.
You can put this, error_reporting(E_ALL); at the very top of your script, right after your opening php tag, to see what error you get.
Hope it helps.
Maybe something like this:
<?php
error_reporting(E_ALL);
more stuff here ...
if(your condition here){
echo "condition is true, do something";
}else{
echo "condition is not true, do something else";
}
if the function or statement you run inside the "if" or "else" fails, at least you know which one was it based on the result, and the error_reporting might tell you why it failed.
mkdir() is working correctly this question is more about catching an error. Instead of printing this when the directory exists I would just like to have it write to a message to me in a custom log. How do I create this exception.
Warning: mkdir() [function.mkdir]: File exists
I would just like to have it write to a message to me in a custom log.
the solution is very easy. PHP already have everything for you:
ini_set('display_errors',0);
ini_set('log_errors',1);
ini_set('error_log','/path/to/custom.log');
or same settings in the php.ini or .htaccess
I think it would be better than write each possible error manually
If you don't want this error to be logged (as it may be not error but part of application logic), you can check folder existence first
if (!file_exists($folder)) mkdir($folder);
else {/*take some appropriate action*/}
You can stop the error message from displaying either by suppressing error messages globally (in config or runtime) with the display_errors setting, or case by case by prefixing the function call with an #-character. (E.g. #mkdir('...')).
You can then check with error_get_last when mkdir returns false.
For error logging global rules apply. You can log errors manually with error_log.
For further reading, see the manual section on Error handling.
Edit:
As suggested in the comments, a custom error handler is also a possible, arguably more robust (depending on your implementation) but certainly more elegant, solution.
function err_handler($errno, $errstr) {
// Ignore or log error here
}
set_error_handler('err_handler');
This way, the error message will not display, unless you explicitly echo it. Note, though, when using a custom error handler error_get_last will return NULL.
You can rewrite any system call function with a class like this:
file: system.php
namespace abc;
class System {
const CAN_NOT_MAKE_DIRECTORY = 1;
static public function makeDirectory($path) {
$cmd = "mkdir " . $path;
$output = \shell_exec($cmd . " 2>&1"); // system call
if ($output != "") {
throw new \Exception($output, System::CAN_NOT_MAKE_DIRECTORY);
}
return(\TRUE);
}
}
Then you can call the method and intercept the exception:
file: index.php
namespace abc;
require 'system.php';
try {
System::makeDirectory($directoryName);
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), System::CAN_NOT_MAKE_DIRECTORY);
}
Now you can treat all the system errors with the try {...} catch(...) {...} finally {...} normally.
I've been wondering why would I use Exceptions in my PHP. Let's take a look at a simple example:
class Worker
{
public function goToWork()
{
return $isInThatMood ?
// Okay, I'll do it.
true :
// In your dreams...
false;
}
}
$worker = new Worker;
if (!$worker->goToWork())
{
if (date('l',time()) == 'Sunday')
echo "Fine, you don't have to work on Sundays...";
else
echo "Get your a** back to work!";
}
else
echo "Good.";
Is there a reason for me to use Exceptions for that kind of code? Why? How would the code be built?
And what about code that may produce errors:
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return false;
return file_get_contents($file);
}
}
Why would I use Exceptions in the above case? I have a feeling that Exceptions help you to recognize the type of the problem, which occured, true?
So, am I using Exceptions appropriately in this code:
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return throw new Exception("File not found.",123);
try
{
$contents = file_get_contents($file);
}
catch (Exception $e)
{
return $e;
}
return $contents;
}
}
Or is that poor? Now the underlying code can do this:
$fo = new FileOutputter;
try
{
$fo->outputFile("File.extension");
}
catch (Exception $e)
{
// Something happened, we could either display the error/problem directly
echo $e->getMessage();
// Or use the info to make alternative execution flows
if ($e->getCode() == 123) // The one we specified earlier
// Do something else now, create "an exception"
}
Or am I completely lost here?
When should I use an exception?
You use an exception to indicate an exceptional condition; that is, something which prevents a method from fulfilling its contract, and which shouldn't have occurred at that level.
For example, you might have a method, Record::save(), which saves changes to a record into a database. If, for some reason, this can't be done (e.g. a database error occurs, or a data constraint is broken), then you could throw an exception to indicate failure.
How do I create custom exceptions?
Exceptions are usually named such that they indicate the nature of the error, for example, DatabaseException. You can subclass Exception to create custom-named exceptions in this manner, e.g.
class DatabaseException extends Exception {}
(Of course, you could take advantage of inheritance to give this exception some additional diagnostic information, such as connection details or a database error code, for example.)
When shouldn't I use an exception?
Consider a further example; a method which checks for file existence. This should probably not throw an exception if the file doesn't exist, since the purpose of the method was to perform said check. However, a method which opens a file and performs some processing could throw an exception, since the file was expected to exist, etc.
Initially, it's not always clear when something is and isn't exceptional. Like most things, experience will teach you, over time, when you should and shouldn't throw an exception.
Why use exceptions instead of returning special error codes, etc?
The useful thing about exceptions is that they immediately leap out of the current method and head up the call stack until they're caught and handled, which means you can move error-handling logic higher up, although ideally, not too high.
By using a clear mechanism to deal with failure cases, you automatically kick off the error handling code when something bad happens, which means you can avoid dealing with all sorts of magic sentinel values which have to be checked, or worse, a global error flag to distinguish between a bunch of different possibilities.
I'm not a PHP programmer, but this looks similar to C#.
Typically you'd want to throw errors if it is a point of no return. Then you would be able to log something to show that the impossible happened.
If you can tell that the file doesn't exist then you could just say that. No real need in my mind to also throw an exception.
Now if the file was found and you are processing it, and say only half the file was uploaded and you had no way of telling that without an exception, then it'd be nice to have around.
I would say it's a good design practice to avoid the catch all exceptions "catch (Exception $e)" and design by contract instead, just like you seem to be doing in the prior example. I would at first be more specific with the type of exception being thrown and then work from there if needed. Otherwise, stay away from the try->catch and exceptions.
In no way can you assume that a file exists just because you called file_exists()! The function file_exists doesn't open the file, so the file can potentially be deleted or renamed or moved at any time!
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
return false;
///<--- file may be deleted right here without you knowing it
return file_get_contents($file);//<-- then this will throw an error
//if you don't catch it, you're program may halt.
}
}
I believe this it better:
class FileOutputter
{
public function outputFile($file)
{
try{
if (!file_exists($file))
return false;
return file_get_contents($file);
}catch(Exception e){
check_what_went_wrong_and_go_to_plan_B();
}
}
}
(Edit: And it's probably even better to actually try to open the file from the beginning. If you succeed then you have a 'lock' on the file and it won't just disappear. If not, then catch the exception and see what went wrong.
Then again, you might feel that this level of reduncancy is just silly. In that case I don't think you need to worry about try/catch at all :)
Just a note really, your code for file outputter is invalid, since file_get_contents($file)
does not throw an exception. It will however raise a warning if the file doesn't exist, or can't be accessed for some reason. Additionally, you are returning an exception from outputFile, when you should probably be just letting the error propagate up the call stack.
However, you can register the error handler in php to throw exceptions when an error occurs:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
That way, any standard function calls that cause an error will throw an exception.
So, I would change FileOutputter to this (with that snippet above added):
class FileOutputter
{
public function outputFile($file)
{
if (!file_exists($file))
throw new Exception("File not found.",123);
return file_get_contents($file);
}
}
The calling code is then basically the same.
Basically rule is not to return an Exception when an error occurs - you can catch it if you want, and throw a custom exception, but let the exception go up the call stack until you want to use it.