I would like to ask can I require/include a file that has syntax errors and if I cant, the require/include returns a value so that I know that the required/included file has syntax errors and cannot be required/included ?
file.php has syntax error
include('file.php')
if (not file.php included because of syntax)
this
else
that
If you really wanted this type of functionality.
You could try using nikics php parser to see if you can successfully parse the file or not.
$code = file_get_contents('yourFile.php');
$parser = new PhpParser\Parser(new PhpParser\Lexer\Emulative);
try {
$stmts = $parser->parse($code);
// $stmts is an array of statement nodes
// file can be successfully included!
} catch (PhpParser\Error $e) {
// cannot parse file!
echo 'Parse Error: ', $e->getMessage();
}
In PHP 7, Parsing errors can be caught, which makes this probably the most robust, elegant, built-in solution:
<?php
function safe_require_once(string $fname) {
try {
require_once($fname);
} catch( Throwable $e ) {
//will throw a warning, continuing execution...
trigger_error("safe_require_once() error '$e'", E_USER_WARNING);
}
}
safe_require_once("./test1.php"); //file with parse or runtime errors
echo "COMPLETED SUCCESSFULLY THO";
you can use something ike this:
if((#include $filename) === false)
{
// handle error
} else { //....}
the # is used to hide the error message
Related
I am playing with try - catch block:
<?php
try {
$str = "http://rejstrik-firem.kurzy.cz/73631604";
$domOb = new DOMDocument();
$html = $domOb->loadHTMLFile($str);
$domOb->preserveWhiteSpace = false;
$container = $domOb->getElementById('ormaininfotab');
echo $container; // <========= this is intended error which I want catch
}
catch (Exception $e) {
echo "Exception" . $e->getMessage() . ". File: " . $e->getFile() . ", line: " . $e->getLine();
}
catch (Error $e) {
echo "Error" . $e->getMessage() . ". File: " . $e->getFile() . ", line: " . $e->getLine();
}
?>
My result is this:
Catchable fatal error: Object of class DOMElement could not be
converted to string in /var/www/html/cirkve_ares/test.php on line 8
Why is not this error catched by second catch?
As user2782001 mentioned this is not a bug in the eyes of PHP dev's. They even noted that these type of errors should be referenced as 'recoverable':
we should get rid of any references to "catchable" fatal errors (if they still exist) in favor of "recoverable" fatal errors. Using "catchable" here is confusing as they cannot be caught using catch blocks.
On the ErrorException manual page there is a neat workaround converting those "catchable/recoverable" errors to ErrorException.
<?php
function exception_error_handler($severity, $message, $file, $line) {
if (!(error_reporting() & $severity)) {
// This error code is not included in error_reporting
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("exception_error_handler");
?>
now you will be able to catch those errors with:
<?php
try {
// Error code
} catch (Error $e) { // this will catch only Errors
echo $e->getMessage();
}
?>
or
try {
// Error code
} catch (Throwable $t) { // this will catch both Errors and Exceptions
echo $t->getMessage();
}
?>
Someone reported this as a bug to PHP's devs, who promptly decided it was not a bug. https://bugs.php.net/bug.php?id=72948&edit=3
This case has been intentionally omitted ...(in practice you can simply convert the recoverable fatal to an exception using an error handler...)
So you still have to use the
set_error_handler()
function, which we were all hoping to leave behind. PHP's devs are so good at never letting your day be too sunny...
There might be some fatal errors which are not even caught by set_error_handler() or \Throwable.
The below implementation will catch the errors which are not even caught by \Throwable as tested in php 7.1. It should only be implemented in your development environment(by just adding it in your development config file) and shouldn't be done in production.
Implementation
register_shutdown_function(function () {
$err = error_get_last();
if (! is_null($err)) {
print 'Error#'.$err['message'].'<br>';
print 'Line#'.$err['line'].'<br>';
print 'File#'.$err['file'].'<br>';
}
});
Example Error
Error# Class Path/To/MyService contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Path/To/MyServiceInterface::add)
Line# 12
File# Path/To/MyService.php
It has been "fixed" as of PHP 7.4 according with Manual PHP, now it throws exception:
Existing recoverable fatal errors in string conversions have been converted to Error exceptions.
I want to receive the error message in php before it gets executed. Basicly what i mean is that if I would have a bad code:
// This code is incorrect, I want to receive the error before it gets handled!
$some_var = new this_class_is_not_made;
Now that class does not exist, so it would be handles by the default error handler in php. But I want to disable the normal error handler and create my own.
Another example:
somefunction( string some_var ); // some_var misses the variable prefix. ( $ )
Example error message:
Fatal error: function 'some_var' is not defined in line: $x!
And this error would be: somefunction( string some_var );
But how would I receive the messages but also disable the normal error system?
EDIT: Making the error system execute a user-defined function
// I would want the error system to execute a function like this:
function(string $errorMessage, int $error_code){
if($error_code < 253){ return "Fatal error"; }
if($error_code < 528 && $error_code > 253){ return "Warning"; }
}
Answer found: By: ShiraNai7
try
{
// Code that may throw an Exception or Error.
}
catch (Throwable $t)
{
// Executed only in PHP 7, will not match in PHP 5
}
catch (Exception $e)
{
// Executed only in PHP 5, will not be reached in PHP 7
}
In PHP 7.0.0 or newer the code will throw Error exception if this_class_is_not_made doesn't exist.
try {
$some_var = new this_class_is_not_made;
} catch (Error $e) {
echo $e->getMessage();
}
Note that that this will also catch any other Error exceptions in case this_class_is_not_made does exist and causes some other error along the way.
In PHP versions prior to 7.0.0 you're out of luck - fatal errors always terminate the main script.
It might be a better idea to use class_exists() instead:
if (class_exists('this_class_is_not_made')) {
$some_var = new this_class_is_not_made;
}
This works in all PHP versions that support classes.
If I include a file in to php. If there is any fatal error in that php then is there any way to skip that .
<?php
include "somefile.php";
echo "OK"; // Is there any way to print this OK If there is any fatal error on somefile.php
?>
I need to include this somefile.php file. It may return fatal error
for some host. I want to skip this file for those host.
Please Advice me.
With this, you can define your own continuation function that will take over in case of a fatal error. This uses register_shutdown_function() to intercept the fatal error.
Usage:
function my_continuation_func($filename, $arg2) {
// On fatal error during include, continue script execution from here.
// When this function ends, or if another fatal error occurs,
// the execution will stop.
}
include_try('my_continuation_func', array($filename, $arg2));
$data = include($filename);
$error = include_catch();
If a fatal error occurs (like a parse error), script execution will continue from my_continuation_func(). Otherwise, include_catch() returns true if there was an error during parsing.
Any output (like echo 'something';) from the include() is treated as an error. Unless you enabled output by passing true as the third argument to include_try().
This code automatically takes care of possible working directory changes in the shutdown function.
You can use this for any number of includes, but the second fatal error that occurs cannot be intercepted: the execution will stop.
Functions to be included:
function include_try($cont_func, $cont_param_arr, $output = false) {
// Setup shutdown function:
static $run = 0;
if($run++ === 0) register_shutdown_function('include_shutdown_handler');
// If output is not allowed, capture it:
if(!$output) ob_start();
// Reset error_get_last():
#user_error('error_get_last mark');
// Enable shutdown handler and store parameters:
$params = array($cont_func, $cont_param_arr, $output, getcwd())
$GLOBALS['_include_shutdown_handler'] = $params;
}
function include_catch() {
$error_get_last = error_get_last();
$output = $GLOBALS['_include_shutdown_handler'][2];
// Disable shutdown handler:
$GLOBALS['_include_shutdown_handler'] = NULL;
// Check unauthorized outputs or if an error occured:
return ($output ? false : ob_get_clean() !== '')
|| $error_get_last['message'] !== 'error_get_last mark';
}
function include_shutdown_handler() {
$func = $GLOBALS['_include_shutdown_handler'];
if($func !== NULL) {
// Cleanup:
include_catch();
// Fix potentially wrong working directory:
chdir($func[3]);
// Call continuation function:
call_user_func_array($func[0], $func[1]);
}
}
Fatal means fatal ...
There is no way to recover from a fatal error.
You can use register_shutdown_function.
<?php
function echoOk()
{
echo "OK";
}
register_shutdown_function(function ()
{
$error = error_get_last();
// to make sure that there is any fatal error
if (isset($error) &&
($error['type'] == E_ERROR
|| $error['type'] == E_PARSE
|| $error['type'] == E_COMPILE_ERROR
|| $error['type'] == E_CORE_ERROR))
{
echoOk();
}
});
include "somefile.php";
echoOk();
But you can do it only once. Any further fatal error will stop execution.
PHP won't tolerate with Fatal Errors. Best to check the included file and solve it.
Actually, you can try looking at register-shutdown-function, but it's not recommended to run away from your problems.
Yes, there is. It can be done through a simple if statement
You Have:
<?php
include "somefile.php";
echo "OK"; // Is there any way to print this OK If there is any fatal error on
?>
Try This:
<?php
if(include "somefile.php"){
// echo do something if success
}else{
echo "OK";
}
edit: I missed the word fatal. As stated, you can't recover from a fatal error. If it is just an exception the hastly writen response below will work.
Including another php module is the same as that code being inserted inline, so a simple try-catch statement should work:
<?php
try {
include "somefile.php";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
echo "OK";
?>
Try to set 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.
See this LINK
Fatal Error means there is something seriously wrong with the including code. As #Orangepill said there is no way to stop this fatal error message popping up. Please go through your coding and find the error.
I'm using try-catch for years, but I never learned how and when to use finally, because I never understood the point of finally (I've read bad books)?
I want to ask you about use of finally in my case.
My code example should explain everything:
$s = "";
$c = MyClassForFileHandling::getInstance();
try
{
$s = $c->get_file_content($path);
}
catch FileNotFoundExeption
{
$c->create_file($path, "text for new file");
}
finally
{
$s = $c->get_file_content($path);
}
Is this correct use of finally?
More precise question:
Shall I use finally (in future PHP versions or other languages) for handling "create something if it not exists" operations?
Finally will always be executed, so in this case, it is not its intended purpose, since normal execution would reopen the file a second time. What you intend to do would be achieved in the same (cleaner) way if you do
$s = "";
$c = MyClassForFileHandling::getInstance();
try
{
$s = $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
$c->create_file($path, "text for new file");
$s = $c->get_file_content($path);
}
Then the manual says:
For the benefit of someone anyone who hasn't come across finally blocks before, the key difference between them and normal code following a try/catch block is that they will be executed even the try/catch block would return control to the calling function.
It might do this if:
code if your try block contains an exception type that you don't catch
you throw another exception in your catch block
your try or catch block calls return
Finally would then be useful in this kind of scenario:
function my_get_file_content($path)
{
try
{
return $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
$c->create_file($path, "text for new file");
return $c->get_file_content($path);
}
finally
{
$c->close_file_handler();
}
}
=> if you need to make sure you close your file handler in this case, or some resource in general.
finally wasn't introduced into PHP until version 5.5 which has not been released yet so that why you haven't seen any examples with it yet. So unless you're running and alpha version of PHP 5.5 you can't use finally yet.
From the manual (exceptions)
In PHP 5.5 and later, a finally block may also be specified after the catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.
Example from the manual of using finally
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
else return 1/$x;
}
try {
echo inverse(5) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "First finally.\n";
}
try {
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "Second finally.\n";
}
// Continue execution
echo 'Hello World';
?>
Finally means what do you want to DO Finally.
try
{
$s = $c->get_file_content($path);
}
catch FileNotFoundExeption
{
$c->create_file($path, "text for new file");
}
finally
{
//Create a pdf with my file
//or, Rename my file
//or, store my file into Database
}
No matter what happens(regardless of whether an exception has been thrown) inside try or catch, 'Finally code' will execute.
So, no point of using same code over 'try' and 'finally'.
Does this simply answer your question?
I just want to appoint that if an Exception occurs in the try block, the exception will be correctly raised even if the finally block is present.
The usefulness of the finally block is for clean and free resources.
I think it's best use is when, for example, you upload a file but then an error happens:
$tmp_name = null;
try {
$tmp_name = tempnam(UPLOAD_DIR, 'prefix');
move_uploaded_file($file['tmp_name'], $tmp_name);
ImageManager::resize($tmp_name, $real_path, $width, $height); // this will rise some exception
}
finally {
if($tmp_name)
unlink($tmp_name); // this will ensure the temp file is ALWAYS deleted
}
As you can see, in this way no matter what happen, the temp file will be correctly deleted.
If we would emulate the finally clause in older version of PHP, we should write something like this:
// start finally
catch(Exception $ex) {
}
if($tmp_name)
unlink($tmp_name);
if( isset($ex) )
throw $ex;
// end finally
Note that the exception has been re-thrown in case the catch block caught something. It isn't clear as the finally version, but works the same.
Which would you recommend?
Return an error code, such as E_USER_ERROR from a function, and determine proper message higher up:
function currentScriptFilename()
{
if(!isset($_SERVER['SCRIPT_FILENAME']))
{
//This?
return E_USER_ERROR;
}
else
{
$url = $_SERVER['SCRIPT_FILENAME'];
$exploded = explode('/', $url);
return end($exploded);
}
}
Execute trigger_error() from the function, with a specific error message:
function currentScriptFilename()
{
if(!isset($_SERVER['SCRIPT_FILENAME']))
{
//Or this?
trigger_error('$_SERVER[\'SCRIPT_FILENAME\'] is not set.', E_USER_ERROR);
}
else
{
$url = $_SERVER['SCRIPT_FILENAME'];
$exploded = explode('/', $url);
return end($exploded);
}
}
I am not sure if I will regret having put a bunch of error messages in my functions further down the line, since I would like to use them for other projects.
Or, would you recommend something totally different?
Do not mix the matters.
Error notification and error handling are different tasks.
You have to use both methods simultaneously.
If you think that $_SERVER['SCRIPT_FILENAME'] availability is worth an error message, you can use trigger error. However PHP itself will throw a notice if you won't check it.
If you want to handle this error, just check this function's return value.
But I would not create a special function for this task.
So,
if (!$filename = basename($_SERVER['SCRIPT_FILENAME']) {
// do whatever you want to handle this error.
}
would be enough
Exceptions could be useful to handle errors, to know if we had any errors occurred.
A simple example:
try {
$filename = basename($_SERVER['SCRIPT_FILENAME'])
if (!$filename) throw new Exception("no filename");
$data = get_some_data_from_db() or throw new Exception("no data");
$template = new Template();
//Exception could be thrown inside of Template class as well.
}
catch (Exception $e) {
//if we had any errors
show_error_page();
}
$template->show();
3.Use exceptions.
If this is the route you are going, I'd rather recommend throwing Exceptions rather then returing an E_ERROR (E_USER_ERROR should be used), as this is just an integer, and possibly a totally valid return for your function.
Advantages:
- Throwing of an Exception cannot be interpreted as anything else then an error by mistake.
- You keep the possibility to add a descriptive error message, even though you don't handle the error at that point/
- You keep a backtrace in your Exception.
- You can catch specific exceptions at specific points, making the decision where in your project a specific type of error should be handled a lot easier.
If not using exceptions which you should be, use trigger_error().
If it is an error you'd like to deal with, try returning FALSE like a lot of the in built functions do.
If you do use exceptions, catch them like this
try {
whatever()
} catch (Exception $e) {
// handle however
}