How to catch the error of file_get_contents() in php - php

How i can catch the error of the file_get_contents()?
I tried this :
if(!$contenido = file_get_contents($url))
{
$save=false;
}
It did not work

file_get_contents() returns FALSE on failure. You must check for that value with the === operator. If you wish to suppress the warning, you can use the # operator in front of file_get_contents().
$contenido = #file_get_contents($url);
if (contenido === FALSE) {
$save=FALSE;
}
From the file_get_contents() docs:
Warning
This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE. Please read the section on Booleans for more information. Use the === operator for testing the return value of this function.

In PHP 5.x you really can't. The best you can do is suppress the error using the dreaded # symbol. This is not considered good coding practice because you're turning off notices, but in this case there's no other option.
if(!$contenido = #file_get_contents($url))
You'll still get your return of false but no Warnings, etc.
As of php-7 you will be able to catch errors like that

On failure, file_get_contents() will return FALSE, but it will be accompanied by an error message. You can hide that error message, but still get returns FALSE, you need to use the '#' symbol before the function name.
Try this:
$url = "path/to/file";
$contents = #file_get_contents($url);
if ($contents !== FALSE) {
// TODO
}

Related

File_get_contents not evaluating to false when file does not exist

I'm trying to test an exception in my code.
public function testGetFileThrowsException(){
$this->expectException(FileNotFoundException::class);
$file = "db.json";
$this->review->getData($file);
}
The "db.json" file doesn't exist. My goal is tp have the getData() file to throw the FileNotFoundException. Here is the getData() code:
public function getData($path){
if(file_get_contents($path) === false){
throw new FileNotFoundException;
}
return $file;
}
The problem is that instead of evaluating to False and throw the exception, the file_get_contents function returns:
1) CompanyReviewTest::testGetFileThrowsException
file_get_contents(db.json): failed to open stream: No such file or directory
So the test doesn't run successfully. Any ideas on why does this happen?
file_get_contents() generates an E_WARNING level error (failed to open stream) which is what you'll want to suppress as you're already handling it with your exception class.
You can suppress this warning by adding PHP's error control operator # in front of file_get_contents(), example:
<?php
$path = 'test.php';
if (#file_get_contents($path) === false) {
echo 'false';
die();
}
echo 'true';
?>
The above echoes false, without the # operator it returns both the E_WARNING and the echoed false. It may be the case that the warning error is interfering with your throw function, but without seeing the code for that it's hard to say.
You have 2 solution the poor one is to hide the error like that
public function getData($path){
if(#file_get_contents($path) === false){
throw new FileNotFoundException;
}
return $file;
}
Or check maybe if the file exist (better solution i guess)
public function getData($path){
if(file_exists($path) === false){
throw new FileNotFoundException;
}
return $file;
}

how to catch hex2bin() warning

Came across this today, not sure how to solve it.
I want to catch an E_WARNING level error issued by hex2bin().
I thought I might be able to use a try()catch() exception method but it did not work.
try {
$foo = hex2bin($bar);
}
catch (Exception $e) {
die('Custom message');
}
The standard E_WARNING that is issued is, of course:
Warning: hex2bin(): Input string must be hexadecimal string
In this particular situation I do not want to use the standard methods to disable errors, such as:
error_reporting(-1);
error_reporting(E_ALL);
ini_set("display_errors", 1);
Nor do I want to suppress the error using a #hex2bin method.
I actually want to have a custom error displayed, but I just do not seem to be able to find a way to catch when hex2bin throws an error.
You can check the input value to verify that it is hex before passing it to the hex2bin method.
if (ctype_xdigit($bar) && strlen($bar) % 2 == 0) {
$foo = hex2bin($bar);
} else {
//display error here
}
Per the documentation, hex2bin returns:
the binary representation of the given data or FALSE on failure.
That means you can do something like this if you want to use it in a try/catch block:
try {
$foo = #hex2bin($bar);
if(false === $foo) {
throw new Exception("Invalid hexedecimal value.");
}
} catch(Exception $e) {
echo $e;
}
Yes, hex2bin is suppressed. You can remove the # if you set error_reporting to suppress warnings.
Alternatively, you can check the type of $foo with ctype_xdigit() prior to using hex2bin().

Try except in PHP

How could I perform the equivalent to an open try:this except:pass in Python?
I have the following code:
$banana = true;
unserialize($banana);
And it returns the error:
Warning: array_keys() expects parameter 1 to be array, boolean given
Which is expected, as I fed it a boolean.
This is just an example; I am using unserialize(), but I'm not purposely feeding it booleans. I need it to work this way.
Since unserialize doesn't throw an exception, there is nothing to catch.
One of the workarounds is using the silence operator (#) and check whether the
outcome of the unserialize method equals false.
$foo = #unserialize($bar);
if ($foo === false && $bar !== 'b:0;') {
// Unserialize went wrong
}
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr, 0);
}, E_NOTICE);
try {
$result = unserialize($banana); // correct
} catch (Exception $e) {
$result = array(); // default value
}
restore_error_handler();
print_r($result);

Mkdir throws a warning, when it should be a bool?

so the popular mkdir() function in php throws me a warning in the following code:
public function check_dir($dir, $create_dir = false) {
if (is_dir ( $dir )) {
return true;
} elseif ($create_dir == true) {
return mkdir ( $dir );
}
return false;
}
Its simple to know whats going on. So I won't explain. But on the mkdir() line I get:
Warning: mkdir(): Permission denied in /var/www/wordpress/wp-content/themes/Aisis-Framework/AisisCore/FileHandling/File.php on line 70
So while its a warning and nothing more, you should never turn of warnings in live, or any kind of error for that fact. So how do I deal with this when its clearly states it returns true or false and not a warning or fatal?
You can establish a custom error handler, which is a good practice in general: http://www.php.net/set-error-handler
You can use this to handle any PHP errors in any way you find appropriate. Short of that, you would have to either turn off error/warning logging (as you say, not a good practice), or use # suppression (which should be avoided in general, but might be suitable in this case.)
Personally I would agree that a function that returns true/false to indicate failure already doesn't need to issue a warning if it fails. But, that's PHP for you.
You should turn warning off in production servers ... But better still .. you can check for permission in your code ...
function checkDir($dir, $createDir = false) {
if ($createDir === true) {
if (is_dir($dir))
return true;
$baseDir = dirname($dir);
if (! is_dir($baseDir) || ! is_writable($baseDir)) {
return false;
}
return mkdir($dir);
} else {
return is_dir($dir);
}
return false;
}

Test if a regular expression is a valid one in PHP

I am writing a form validation class and wish to include regular expressions in the validation. Therefore, the regex provided isn't guaranteed to be valid.
How can I (efficiently) check that the regex is valid?
Use the pattern in your preg_* calls. If the function returns false there is likely a problem with your pattern. As far as I know this is the easiest way to check if a regex pattern is valid in PHP.
Here's an example specifying the right kind of boolean check:
$invalidPattern = 'i am not valid regex';
$subject = 'This is some text I am searching in';
if (#preg_match($invalidPattern, $subject) === false) {
// the regex failed and is likely invalid
}
When you have error reporting on, you can't get away with simply testing the boolean result. If the regex fails warnings are thrown (i.e. 'Warning: No ending delimiter xxx found'.)
What I find odd, is that the PHP documentation tells nothing about these thrown warnings.
Below is my solution for this problem, using try, catch.
//Enable all errors to be reported. E_WARNING is what we must catch, but I like to have all errors reported, always.
error_reporting(E_ALL);
ini_set('display_errors', 1);
//My error handler for handling exceptions.
set_error_handler(function($severity, $message, $file, $line)
{
if(!(error_reporting() & $severity))
{
return;
}
throw new ErrorException($message, $severity, $severity, $file, $line);
});
//Very long function name for example purpose.
function checkRegexOkWithoutNoticesOrExceptions($test)
{
try
{
preg_match($test, '');
return true;
}
catch(Exception $e)
{
return false;
}
}
You shouldn't be using # to silence all errors because it also silences fatal errors.
function isRegularExpression($string) {
set_error_handler(function() {}, E_WARNING);
$isRegularExpression = preg_match($string, "") !== FALSE;
restore_error_handler();
return isRegularExpression;
}
This only silences warnings for the preg_match call.
Anyone still looking at this question anno 2018, and is using php 7, should be using try/catch.
try {
preg_match($mypattern, '');
} catch (\Throwable $exception) {
// regex was invalid and more info is in $exception->getMessage()
}
PHP has progressed quite a bit since this question was first asked (and answered). You can now (PHP 5.2+) simply write the following to, not only test if the regular expression is valid, but to get the detailed error message if it's not:
if(#preg_match($pattern, '') === false){
echo error_get_last()["message"];
}
Placed in a function
/**
* Return an error message if the given pattern argument or its underlying regular expression
* are not syntactically valid. Otherwise (if they are valid), NULL is returned.
*
* #param $pattern
*
* #return string|null
*/
function regexHasErrors($pattern): ?string
{
if(#preg_match($pattern, '') === false){
//Silence the error by using a #
return str_replace("preg_match(): ", "", error_get_last()["message"]);
//Make it prettier by removing the function name prefix
}
return NULL;
}
Demo
This is my solution using the upcoming warning if something is wrong with the expression:
function isRegEx($test)
{
$notThisLine = error_get_last();
$notThisLine = isset($notThisLine['line']) ? $notThisLine['line'] + 0 : 0;
while (($lines = rand(1, 100)) == $notThisLine);
eval(
str_repeat("\n", $lines) .
'#preg_match(\'' . addslashes($test) . '\', \'\');'
);
$check = error_get_last();
$check = isset($check['line']) ? $check['line'] + 0 : 0;
return $check == $notThisLine;
}

Categories