$someClass sc=new SomeClass();
What I want to know is what will be in the variable sc if the constructor fails for some reason (like maybe not enough memory). I can' t find a straight answer?
With your example of memory issue, You get a fatal error and php ceases execution. You never get to the assignment of the varible $sc.
A constructor can fail for mainly two reasons:
Out of memory; not unique to objects, this causes a fatal error and your script won't continue.
An exception is thrown; your script will stop unless the exception is caught using a 'try-catch' clause.
try {
$sc = new SomeClass(); // exception is thrown inside the constructor
} catch (Exception $e) {
echo "Yikes, object didn't get created; error = {$e->getMessage()}\n";
}
first of all, the syntax for object initiation is incorrect, needs to be $sc = new SomeClass(); And you would get an memory exhaustion error, and variable $sc wouldn't be created.
The same thing that happens when any other type of code fails for some reason like not enough memory and such: the PHP runtime issues a fatal error and that's it. Object constructors are not special.
Related
This is more just for documentation, since I've already solved the issue, but it was subtle and difficult enough to debug that I thought it would be useful in the public sphere.
The issue was that I had a try/catch block in an object method that just wasn't working. The reduced example is in two files, which look like this:
TestClass.php:
<?php
//TestClass.php
namespace MyTest;
class TestClass {
public function __construct() {
\e("Initializing object");
try {
\e("Trying object exception");
\throwTestException("Failing gracefully in object");
\e("After exception");
} catch (Exception $e) {
\e($e->getMessage());
}
\e("After object init exception");
}
}
?>
Main.php:
<?php
//Main.php
function e($str) { echo "\n$str"; }
function throwTestException($msg) {
throw new RuntimeException($msg);
}
require "TestClass.php";
e("Beginning");
try {
e("First try");
throwTestException("Failing gracefully first");
e("After exception");
} catch (Exception $e) {
e($e->getMessage());
}
e("Ending");
e('');
e('Beginning object test');
new \MyTest\TestClass();
e('Ending object test');
?>
The expected result on loading Main.php was this:
Beginning
First try
Failing gracefully first
Ending
Beginning object test
Initializing object
Trying object exception
Failing gracefully in object
After object init exception
Ending object test
What I actually got was something like this:
Beginning
First try
Failing gracefully first
Ending
Beginning object test
Initializing object
Trying object exception
Fatal Error: Uncaught Exception: Failing gracefully in object......
As you can see, the exception was not being caught. I tried all sorts of things and just couldn't figure out why it wasn't being caught. And then.... (See answer below)
I realized it was a namespace issue. Because I had declared TestClass within the namespace MyTest, and throwTestException in the global namespace, my reference to Exception within the class method was tacitly resolving to \MyTest\Exception and thus NOT matching the actual exception being thrown, \RuntimeException. And since I wasn't actually trying to instantiate the exception from within the namespace, no "Unknown Class" errors emerged to reveal what was happening.
The solution, then, was simply to properly resolve the exception class I was trying to catch:
catch(\Exception $e) { .... }
To be fair, this became obvious as I built my highly reduced example. It wasn't obvious initially because the exception I was expecting to catch was being generated by the class's superclass (which was the SQLite3 class). Thus, I didn't have to worry about the namespace when generating the exception, and all I was thinking about when catching it was to use the most general form of exception, Exception. And again, since I wasn't instantiating that exception -- only matching against it in a catch block --, I didn't get any notices that it was unresolved.
i have the following logic in my model:
if ( $switch_obj->connect() ) {
if ( $data = $switch_obj->showIntAll() ) {
$switch_obj->disconnect();
return $data;
}
else {
$switch_obj->disconnect();
throw new Exception('Empty Data Set');
}
}
else {
throw new Exception('Connection');
}
This switch_obj that's being called has logic in it's constructor and destructor to increment / decrement counters respectively. (saved in a class called testclass).
So each time an object of type testclass is instantiated, a counter is increased. And then when destroyed, it's decremented.
However, I've just discovered a scenario that I'm not handling.
Fatal error: Call to undefined method testclass::showIntAll() in
/var/www/myapp/application/models/test_model.php on line 215
It's clear that I'm calling a method that doesn't exist, which I will resolve. But my question is this: in creating this error, i can see that the counter has already been incremented ... but not decremented because once this error is thrown, it never returns to the destructor method in my class.
How would I program for these types of scenarios? Obviously, in production, I won't get getting errors because of missing methods in testclass... but in case I do get an unexpected error where the testclass constructor is called and then it bombs, I'm just wondering what the best way is to handle this.
You might achieve something with register_shutdown_function. Your constructor could register a clean-up function which would get called if an error would occur. You'd have to be careful not to call the clean-up code twice though (once from the destructor and once from this registered function.
Not a pretty solution, but it could work :)
As far as i can remember destructors are not called on fatal errors
I've written error handling class which divided all errors into the normal ones (notices, warnings, ...), and the critical ones.
Now I've found out that it's a good practice to convert all errors into exceptions. It would also shorten my code.
However, I'm not sure how to handle this...
Are there exceptions that don't stop scripts execution, and exceptions that do? If there aren't...how to differ converted errors?
Converting errors into exception is done by calling set_error_handler() and throw new ErrorException() in there...What's next? set_exception_handler() is called automagically?
Caught exceptions do not stop your script, all uncaught ones do.
No, set_exception_handler() is not called automatically, you can do that if you like.
The exception handler you set with set_exception_handler() gets called after an exception has gone uncaught, it is the last piece of code that gets called before the script terminates. Make sure it doesn't cause an error/exception, or it will end badly.
Are there exceptions that don't stop scripts execution, and exceptions that do? If there aren't...how to differ converted errors?
Exceptions don't stop script execution if they're caught. To recognize a converted error:
try {
// ...
} catch (ErrorException $e) {
// converted error (probably)
} catch (Exception $e) {
// another kind of exception; this basically catches all
}
Or:
function handle_exception(Exception $e)
{
if ($e instanceof ErrorException) {
// converted error (probably)
} else {
// another kind of exception
}
}
set_exception_handler('handle_exception');
Note that ErrorException can be thrown by any piece of code, but it was meant to convert regular errors in set_error_handler() registered functions only.
Converting errors into exception is done by calling set_error_handler() and throw new ErrorException() in there...What's next? set_exception_handler() is called automagically?
If the thrown ErrorException from your error handler function is not caught anywhere else in your code, the registered exception handler (set using set_exception_handler()) will be called.
Any uncaught exception will stop execution of your script.
When an exception is thrown, code following the statement will not be
executed, and PHP will attempt to find the first matching catch block.
If an exception is not caught, a PHP Fatal Error will be issued with
an "Uncaught Exception ..." message, unless a handler has been defined
with set_exception_handler().
See docs about this
As for set_exception_handler() - it is not called automatically, but it is your last resort to react to the problem that occured
Sets the default exception handler if an exception is not caught
within a try/catch block. Execution will stop after the
exception_handler is called.
Keep in mind that you can only convert Warnings into Exceptions, errors cannot be converted to Exceptions because the error handler doesn't run.
set_error_handler(function ($severity, $message, $file, $line) {
echo 'You will never see this.'
});
// Provoke an error
function_that_does_not_exist();
It is possible to "catch" them using a shutdown function, but that is out of the scope of the question.
In PHP, is there any way that I can ignore functions that are undefined instead of throwing a fatal error that is visible in the browser?—i.e., Fatal error: Call to undefined function
I know that there is the practice of wrapping all custom functions in a conditional as below, but is there a programmatic way to get this effect?
if (function_exists('my_function')) {
// use my_function() here;
}
No. Fatal errors are fatal. Even if you were to write your own error handler or use the # error suppression operator, E_FATAL errors will still cause the script to halt execution.
The only way to handle this is to use function_exists() (and possibly is_callable() for good measure) as in your example above.
It's always a better idea to code defensively around a potential (probable?) error than it is to just let the error happen and deal with it later anyway.
EDIT - php7 has changed this behavior, and undefined functions/methods are catchable exceptions.
In php 7, this is now possible.
Example codez:
try {
some_undefined_function_or_method();
} catch (\Error $ex) { // Error is the base class for all internal PHP error exceptions.
var_dump($ex);
}
demo
http://php.net/manual/en/migration70.incompatible.php
Many fatal and recoverable fatal errors have been converted to exceptions in PHP 7. These error exceptions inherit from the Error class, which itself implements the Throwable interface (the new base interface all exceptions inherit).
What you are asking for seems a little goofy, but you can get a similar effect by declaring all your functions as methods of a class and then implement __call as a method of that class to handle any undefined method calls. You can then handle calls to undefined methods however you like. Check out the documentation here.
If you would like to suppress this error while working with objects use this function:
function OM($object, $method_to_run, $param){ //Object method
if(method_exists(get_class($object), $method_to_run)){
$object->$method_to_run($param);
}
}
Regards
we can hide errors but this will log in apache error log
//Set display error true.
ini_set('display_errors', "0");
//Report all error except notice
ini_set('error_reporting', E_ALL ^ E_NOTICE ^ E_STRICT);
//We can use try catch method
try {
my_method();
} catch (\Error $ex) { // Error is the base class for all internal PHP error exceptions.
var_dump($ex);
}
//Check method existance
function_exists()
Prevent no. But catch and log yes, using register_shutdown_function()
See PHP manual
function shutDown_handler()
{
$last_error = error_get_last();
//verify if shutwown is caused by an error
if (isset ($last_error['type']) && $last_error['type'] == E_ERROR)
{
/*
my activity for log or messaging
you can use info:
$last_error['type'], $last_error['message'],
$last_error['file'], $last_error['line']
see about on the manual PHP at error_get_last()
*/
}
}
register_shutdown_function ('shutDown_handler');
I found in PHP 7 that try/catch works for the "Call to undefined function" error. The Exception object that is caught is not of class Throwable and not ErrorException but Error.
The exception object received by catch contains the error message, the file and line nr, and stack trace, but does not contain the severity code.
This catch allows the program to do its own logging or analysis, and hides the error message from the user-visible output (but will log the error in the PHP error log), just what is wanted on production websites. It also allows execution to continue, which can be dangerous, but you can simply place "exit;" at the end of the catch code block to prevent the program from continuing.
In PHP, is it possible to get the file name of the script that instantiated an object?
For example I have a script called file.php that creates a new instance of class Class. The class has an Error object that, when triggered, returns some error information. I would like to show that file.php triggered the error.
The function debug_backtrace() may be of use? It shows the execution flow from bottom to top.
As Kai Sellgren said, the debug_backtrace() function can be used.
You can also throw and catch an exception to get a backtrace.
try
{
throw new Exception();
}
catch( Exception $e )
{
print_r( $e->getTrace() );
}
As getting a backtrace can take some time, you should benchmark both solutions to see which is the fastest.
And by the way, shoudn't your error object be a subclass of Exception? That's the reason why exceptions exists...
Any chance that error_get_last's returned array satisfies your need? The function 'returns an associative array describing the last error with keys "type", "message", "file" and "line". Returns NULL if there hasn't been an error yet. '
http://www.php.net/manual/en/function.error-get-last.php