4 ms·
> Can I now get EEXISTS and such out of fopen()? Looking at the docs it still just returns false and emits an uncatchable E_WARNING that can't be examined prog
by some_furry 2y ago
> Can I now get EEXISTS and such out of fopen()? Looking at the docs it still just returns false and emits an uncatchable E_WARNING that can't be examined programmatically.
Sure, the most straightforward way is to first use the "x" flag for write-only, and "x+" for read/write access.
$fp = fopen('file.txt', 'x+');
From the PHP docs:
"If the file already exists, the fopen() call will fail by returning false and generating an error of level E_WARNING. If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call."
And finally to convert E_WARNING errors to exceptions, use you can use set_error_handler() to throw an exception (and even write business logic to filter them): https://www.php.net/manual/en/language.exceptions.php https://www.php.net/manual/en/language.exceptions.php
They're not unhandleable.
But if you want a single function that throws a specific exception when a file exists, specific to the behavior you want, I got you:
<?php
declare(strict_types=1);
namespace Argp242;
use function fopen as php_fopen;
function fopen(
string $filename,
string $mode,
bool $use_include_path = false,
$context = null
) {
if (file_exists($filename)) {
throw new \RuntimeException('E_EXISTS');
}
return php_fopen($filename, $mode, $use_include_path, $context);
}
To run this code from outside a namespace, simply:
try {
$fp = Argp242\fopen($filename, $mode);
} catch (RuntimeException $ex) {
// Handle $ex
}
Throw it in a library somewhere, having written it once, and now you can just use that whenever you want that behavior in your PHP code.
- asddubs 2y agothis code will run into problems with race conditions if the file is created after file_exists is called but before fopen is called
- some_furry 2y agoIf you expect PHP to ever win a race against another process, I don't know what to tell you. Trying to make PHP work for a job it's not suited for and failing is not a reason to hate PHP. It's a reason to ask yourself "why".
- asddubs 2y agoThis absolutely will happen, and most likely the other process is also PHP. The most obvious example is caching anything to a file. I don't hate PHP though, I just don't feel the need to convince myself it couldn't be improved.
- arp242 2y agoA lot of PHP usage is inherently multi-process; 100 users accessing your PHP app are essentially 100 processes, often with a few of them running in parallel. Doing any sort of file i/o really does require thinking about these sort of things, and it's something I've run into. And this is not exactly a huge ask, or a very obscure function call. You can kind of work around all of this if you're careful, but it's not exactly brilliant is it? Literally every other mainstream language can do this. This is really a "only in PHP" type of thing. Just say "yeah, this is still a downside of PHP; hopefully it will get improve one day!" Fine. Fair enough. No language is perfect and I'm not here to bash PHP. I consider this to be a major pain point, but other people do other things and maybe it's less of an issue for them. Also fine. What I don't get are these contortionist tricks – I already knew how this would go when I posted it: first there would be the "but you can do this", and then when mentioned that's not really sufficient the "yes but you don't need that anyway".
- some_furry 2y agoIf it's a pain point, write an RFC. Make the language better. Don't just shrug and say "it sucks"
- arp242 2y agoEh, you can constructively critique things without spending tons of effort on fixing it. What a painful and unpleasant conversation this is turning out to be.
- some_furry 2y ago> What a painful and unpleasant conversation this is turning out to be. Finally, something we both agree on
- arp242 2y agoThere are tons of reasons an fopen() call can fail and sometimes you really want to know why; these pokemon exceptions don't give me that. And your code is racy as files can be created in-between the file_exists() and fopen() calls. Yes, this happens, and in some cases it's a security problem (which is why you need to use mkstemp and not mktemp in C).
- nolok 2y agoThe core of PHP is very close to the libc function it offers, and so you will do that in a similar way that you do that in C : call error_get_last(), which gives you the details of the last error.
- panzi 2y agoIf you change the behavior of fopen() by installing an error handler that throws an exception, won't that mess up library code that doesn't expect that behavior? Seems hacky and error prone to me. (Also the race condition others already mentioned!)