Reputation: 3323
When I use file_get_contents
, is_file
, realpath
, file_exists
with a string that isn't a path I get the following warning.
"function_name()" expects parameter 1 to be a valid path, string given in [...]
So how to determine whether the string could be a valid path or not.
What the hell do you want to do? You may ask...
Well, I want to create a function like this.
funtion my_smart_function( string $path_or_content )
{
$content = is_file_without_warning_if_not_a_valid_path( $path_or_content )
? file_get_contents( $path_or_content )
: $path_or_content;
// do nice stuff with my $content
}
Sometimes $path_or_content
will be a valid path to a file and sometimes $path_or_content
will be the content of a file by itself (eg the binary data of an image created on the fly that doesn't even have a path (at least not yet)). In the latter case all these string related functions I mentioned above (eg file_exists()
) will throw a warning (see quote above).
Something I'm wondering about.
realpath('xyz')
doesn't throw a warning but
realpath( file_get_contents('path/to/actual/image.jpg') )
does...
So realpath
and the other functions mentioned above distinguish between a string or a string that is a valid path. So how can we do either beforehand?
Upvotes: 7
Views: 9325
Reputation: 4658
file_exists
does not check that path is a valid path and has undocumented behavior. In the meantime there is no function to check whether path is valid or not. Minimal check could be as suggested by Barmar: return strpos($path, "\0") === false
However usually you don't want unprintable characters in your filenames neither, so it would be quite fair assumption to just use ctype_print
function before passing the path to file_exists
(as suggested by Daan).
A bit of background
Even though everyone uses file_exists
to check... that file exists, this function (and some others) does more than that.
To be precise, it returns null
if path is not a valid path (i.e. contains \0
). It's a PHP bug.
This is very confusing behavior. Even though documentation says that file_exists
"Returns TRUE if the file or directory specified by filename exists; FALSE otherwise.", this is not the current implementation behavior.
As per someone's from PHP community:
No, file_exists does not test valid paths. It tests if a "file" exists. The presumption is that the path you are giving is valid, because if not then it couldn't possibly exist.
Upvotes: 0
Reputation: 780673
This may be a reasonable time to use the @
modifier to suppress errors.
funtion my_smart_function( string $path_or_content )
{
$content = @file_exists( $path_or_content )
? file_get_contents( $path_or_content )
: $path_or_content;
}
If it's not a valid path, file_exists()
will return a falsey value, and the @
will keep it from complaining about the bad string.
On Linux, the only character that's not allowed in a path is the null byte. So you could just check for this:
if (strpos($path_or_contents, "\0") === false) {
return file_get_contents($path_or_contents);
} else {
return $path_or_contents;
}
Upvotes: 6
Reputation: 12236
I believe this is exactly what you want. ctype_print
checks if all of the characters in the provided string, are printable. If so pass it to file_exists
.
function my_smart_function( $path_or_content )
{
$content = ctype_print($path_or_content) && file_exists( $path_or_content )
? file_get_contents( $path_or_content )
: $path_or_content;
// do nice stuff with my $content
}
Upvotes: 4
Reputation: 28834
I think you missed file_exists function. From documentation:
file_exists — Checks whether a file or directory exists
bool file_exists ( string $filename )
Returns TRUE if the file or directory specified by filename exists; FALSE otherwise.
Upvotes: 0