file_put_contents
Writes a string, array or stream to a file in one call, creating the file if needed.
file_put_contents(string $filename, mixed $data, int $flags = 0, ?resource $context = null): int|false- Added in PHP 5.0.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$filename | string | Path to the file to write. It is created if it does not exist. |
$data | mixed | The data to write: a string, a one-dimensional array (joined with no glue), or a stream resource whose remaining contents are copied. |
$flagsoptional | int= 0 | Bitmask of FILE_USE_INCLUDE_PATH, FILE_APPEND and LOCK_EX. |
$contextoptional | ?resource= null | A stream context from stream_context_create(), or null for none. |
Return value
int|falseThe number of bytes written, or false on failure.
Errors
Emits an E_WARNING and returns false if the file cannot be opened or written; throws a ValueError if filename contains a null byte or if data is an unsupported type.
file_put_contents is the write-side twin of file_get_contents: it opens, writes, and closes in one statement. By default it truncates the file, so the contents are replaced, not added to. Pass FILE_APPEND when you want to add to the end instead.
When to reach for it
- Dumping a rendered string, a serialized array or JSON to disk.
- Appending a single line to a log file.
- Copying a stream to a file —
$dataaccepts a resource, and PHP will drain it for you.
What trips people up
Two processes appending at once will interleave garbage unless you add LOCK_EX. Combine flags with |: FILE_APPEND | LOCK_EX. Note that even with LOCK_EX, a reader using plain file_get_contents takes no lock and can still read a half-written file — for real atomicity, write to a temporary file and rename() it into place.
The return value is a byte count, and writing an empty string returns 0, which is falsy. As with the read side, compare with === false. Only one-dimensional arrays are supported: the call is equivalent to implode('', $array), so a nested array does not throw — each inner array is converted to the literal string Array and PHP emits an “Array to string conversion” warning.
Example
When to use it
- Cache a rendered HTML fragment to disk so the next request can serve it directly.
- Append a timestamped audit line to a log file with FILE_APPEND | LOCK_EX.
- Write json_encode output to a data file that another job picks up.
Frequently asked questions
How do I append to a file instead of overwriting it with file_put_contents?
Pass `FILE_APPEND` as the third argument: `file_put_contents($f, $data, FILE_APPEND)`. Without it the file is truncated to zero bytes before writing.
Does file_put_contents create the file if it does not exist?
Yes, it creates the file, but not the directories above it. If the parent directory is missing you get an E_WARNING and `false` — call `mkdir($dir, 0777, true)` first.
Is file_put_contents with LOCK_EX safe for concurrent writes?
It stops two writers from interleaving, but it does not stop a concurrent reader from seeing a partial file. For a guaranteed all-or-nothing update, write to a temp file and `rename()` it over the target.
More examples
Truncate versus append
The second write prints `beta` only — `alpha` is gone, because the default behaviour truncates. The FILE_APPEND write prints `beta|gamma|`, showing the flag is what keeps existing content.
<?php
file_put_contents('notes.txt', "alpha\n");
file_put_contents('notes.txt', "beta\n"); // replaces
echo "after second write: ", trim(file_get_contents('notes.txt')), "\n";
file_put_contents('notes.txt', "gamma\n", FILE_APPEND); // adds
echo "after append: ", str_replace("\n", '|', file_get_contents('notes.txt')), "\n";
unlink('notes.txt');Writing an array of lines properly
The naive write produces `redgreenblue` on one line. Joining with `PHP_EOL` first gives `red/green/blue/` after the separators are made visible — the array form concatenates without any glue.
<?php
$lines = ['red', 'green', 'blue'];
file_put_contents('bad.txt', $lines);
echo "naive: ", file_get_contents('bad.txt'), "\n";
file_put_contents('good.txt', implode(PHP_EOL, $lines) . PHP_EOL);
echo "joined: ", str_replace(PHP_EOL, '/', file_get_contents('good.txt')), "\n";
unlink('bad.txt');
unlink('good.txt');Atomic write via a temp file and rename
Readers only ever see the complete file, because `rename()` swaps it into place in a single filesystem operation. The final line prints `false`, confirming the temp file is gone.
<?php
$target = 'settings.json';
$tmp = $target . '.tmp';
file_put_contents($tmp, json_encode(['theme' => 'dark'], JSON_PRETTY_PRINT));
rename($tmp, $target); // atomic on the same filesystem
echo file_get_contents($target), "\n";
echo "temp file left behind: ", var_export(file_exists($tmp), true), "\n";
unlink($target);
Discussion