tempnam
Creates a uniquely named empty file in a directory and returns its full path.
tempnam(string $directory, string $prefix): string|false- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$directory | string | The directory in which to create the temporary file. If it does not exist or is not writable, the system temporary directory is used instead. |
$prefix | string | Prefix for the generated filename. Only the first 63 characters are used; Windows uses only the first three. |
Return value
string|falseReturns the new temporary filename including its path, or false on failure.
Errors
Emits an E_NOTICE when it falls back to the system temp directory, and an E_WARNING when open_basedir restrictions block the path. Returns false rather than throwing.
Changelog
- PHP 8.4.0Names generated by tempnam() are 13 bytes longer than before. The total length remains platform-dependent.
- PHP 7.1.0tempnam() now emits a notice when it falls back to the system temporary directory.
tempnam() atomically creates an empty file with a name nothing else is using and returns its path. The file is created with mode 0600 and owned by the process user, which is what makes it safe: there is no window between picking a name and creating the file for an attacker to slip a symlink in.
When to reach for it
- You need a scratch file whose path you must hand to another library, an image tool, or a template writer.
- You are writing a large download or export and want to build it fully before renaming it into place.
- You need a file that outlives the current file handle — otherwise
tmpfile()is simpler.
What trips people up
The file is yours to delete. Unlike tmpfile(), nothing cleans it up — a script that leaves temp files behind on every request will eventually fill the partition. Wrap the work in try/finally and unlink() in the finally block.
If the directory you pass does not exist or is not writable, tempnam() does not fail. It quietly creates the file in the system temp directory instead and returns that path, so always use the returned string rather than rebuilding the path yourself. Relative paths and custom stream wrappers are not reliably supported; pass an absolute local path, or sys_get_temp_dir().
Example
When to use it
- Build a CSV export in a temp file, then rename() it over the live download path so readers never see a half-written file.
- Write an uploaded image to a scratch path before handing it to an image library that only accepts filenames.
- Stage a generated PDF that a queue worker will pick up by path a moment later.
Frequently asked questions
What is the difference between tempnam and tmpfile?
tempnam() returns a path to a file you must delete yourself; tmpfile() returns an open handle to a file that PHP deletes automatically when it is closed. Use tempnam() when something else needs the filename.
Does tempnam delete the file automatically?
No. The file persists until you unlink() it or the operating system cleans the temp directory, which may be never. Deleting it is your responsibility.
Where does tempnam put the file if the directory is not writable?
It falls back to the system temporary directory, the same one sys_get_temp_dir() reports, and emits a notice. The returned path reflects the real location, so always use it instead of reconstructing the path.
More examples
Always clean up with finally
The temp file is removed even though the work threw. Without the finally block the file would survive the request, which is how temp directories quietly fill up.
<?php
$path = tempnam(getcwd(), 'job_');
try {
file_put_contents($path, "row 1\nrow 2\n");
echo 'lines: ', count(file($path)), "\n";
throw new RuntimeException('export failed');
} catch (RuntimeException $e) {
echo 'caught: ', $e->getMessage(), "\n";
} finally {
unlink($path);
}
var_dump(file_exists($path));Write then rename atomically
rename() within the same filesystem is atomic, so a concurrent reader sees either the old export.csv or the complete new one, never a partial file. Note the temp path no longer exists after the rename.
<?php
$tmp = tempnam(getcwd(), 'exp_');
file_put_contents($tmp, "a,b,c\n1,2,3\n");
rename($tmp, 'export.csv');
echo file_get_contents('export.csv');
var_dump(file_exists($tmp));
unlink('export.csv');The path you get back may not be the one you asked for
Because the requested directory does not exist, tempnam() falls back to the system temp directory and emits a notice. The comparison prints false, which is why you must use the returned path rather than assuming your own.
<?php
$asked = getcwd() . '/no_such_dir';
$path = @tempnam($asked, 'fb_');
echo 'asked : ', $asked, "\n";
echo 'got : ', dirname($path), "\n";
var_dump(dirname($path) === $asked);
unlink($path);
Discussion