Ensure PHP tmpfile() is removed automatically
For years, I’ve been using a PHP code snippet like this to write to a temporary file:
$tempFilePath = stream_get_meta_data(tmpfile())['uri']; file_put_contents($tempFilePath, 'Hello, world!');
I expected this file to be removed automatically when the script ends, according to the documentation for tmpfile():
The file is automatically removed when closed (for example, by calling fclose(), or when there are no remaining references to the file handle returned by tmpfile()), or when the script ends.
The 7.1 GB tmp directory on my server with 1.8M files begs to differ.
PHP keeps track of the number of references to the handle returned by tmpfile() and immediately removes the file when none remain. In the code snippet above, the script doesn’t keep any reference to this handle. There is just one anonymous reference passed into stream_get_meta_data(), which evaporates when that function returns. By the time we’re writing the file path to $tempFilePath, the file no longer exists!
You can prove this by running this code snippet:
$tempFilePath = stream_get_meta_data(tmpfile())['uri']; file_exists($tempFilePath); // returns false
In the original snippet, file_put_contents() is actually creating a new file with the same name as the original one, but without the promise of automatic removal when the script ends.
In most cases, you can avoid this problem by storing the handle instead of the path, then write to the file using fwrite():
$tempFile = tmpfile(); fwrite($tempFile, 'Hello, world!');
However, if your use case specifically requires a file path, you can just assign the handle to some variable:
$tempFilePath = stream_get_meta_data($tempFile = tmpfile())['uri']; file_exists($tempFilePath); // now returns true!
August 9, 2022 at 10:18 pm
See all posts
Hi, I'm Neil! I'm passionate about building delightful products at scale, creating music, and performing in theatre and comedy shows.