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;
}
Related
Having written a custom error handler for a PHP system I'm trying to figure out how to determine if the error reporting level (which can be obtained via error_reporting()) has been globally set to Off (0) or has been disabled for that line only using the # prefix
The issue at current is that for both circumstances the error_reporting() function returns 0
Update #1
This example unfortunately does not work for PHP 5.3.3 on CentOS 6.8 as the ini_get() function returns the same value as error_reporting()
function errhandle($errno, $errstr, $errfile, $errline) {
if (error_reporting() === 0 && error_reporting() === (int)ini_get('error_reporting')) {
echo 'error_reporting(0) was used';
} else if (error_reporting() === 0 && error_reporting() !== (int)ini_get('error_reporting')) {
echo '# was used';
}
}
set_error_handler('errhandle');
echo error_reporting()."\n";
echo #$arr['name'];
// Prints
22527
error_reporting(0) was used
In addition to error_reporting(), you can also check the error reporting level with ini_get('error_reporting'). Theoretically this is similar, but it has a subtle difference that makes it valuable for what you're trying to do.
If the error reporting has been disabled globally with error_reporting(0) then ini_get('error_reporting') will return the string 0. But if error reporting was left alone and the line was prefixed with #, it will return a non-zero value (the value of the existing INI directive).
So you can compare the 2 values and determine exactly what happened:
if (error_reporting() === 0 && error_reporting() === (int)ini_get('error_reporting')) {
echo 'error_reporting(0) was used';
} else if (error_reporting() === 0 && error_reporting() !== (int)ini_get('error_reporting')) {
echo '# was used';
}
This is just an example of the kind of condition you can do in your custom error handler. If it's not quite what you want, let me know and I'll try tweaking it.
Tested locally on my PHP 7.1.2 (CLI on Windows).
Update #1
After a bit more thought I came up with this idea. Just a warning, this seems very hacky and inefficient, but I'm starting to think it might be the only way to do it.
If you're following the example from the PHP docs for set_error_handler, then the function signature for your custom error handler probably looks like this:
function myErrorHandler($errno, $errstr, $errfile, $errline)
In other words, you have the file and line number where the error occurred. You can use this info to open the file itself, look at that line number, parse the tokens and look for the # character. The code would look like this:
function myErrorHandler($errno, $errstr, $errfile, $errline) {
$errfileContents = file($errfile);
$errlineContents = $errfileContents[$errline - 1];
$tokens = token_get_all('<?php ' . $errlineContents . ' ?>');
if (error_reporting() === 0) {
if (in_array('#', $tokens)){
echo '# was used';
} else {
echo 'error_reporting(0) was used';
}
}
}
Obviously you could expand that condition by checking to see if both or neither of the techniques were used.
Anyway, it's ugly, but it's working for me on my PHP 5.6.6 (CLI on Windows).
I have a block of code in some inherited work. It appears to be running ok, but I suspect that's just because it hasn't needed to call this specific function yet.
function has($key)
{
if (isset($this) && get_class($this)) {
$obj = $key;
}
if (isset($this) && get_class($this)) {
$obj = &JSW_Request::getInstance();
}
return isset(isset($this) && get_class($this)[$key]);
}
Running it through a syntax checker it reported the following error
Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead)
This is related to the code line
return isset(isset($this) && get_class($this)[$key]);
I can't relate what the suggested fix is to the code line to be honest, so I'm a bit lost. Any suggestions?
Try to use null check instead of isset as follows:
if($var !== null){
// your block of code
}
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 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
}
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;
}