Jump to content

tmpfile() or tempnam()?


NotionCommotion

Recommended Posts

I will be using exec() to execute an external program which requires a file output path and will create a file located at that path, and the file is only needed during the execution of the PHP script and should be deleted after the script ends.

Good or bad idea?  If bad, why?  Thanks

    public function tmpFile():string
    {
        return stream_get_meta_data(tmpfile())['uri'];
    }


EDIT - Does "when the script ends" happen about the same time as the class's destructor?

Quote

 

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.

Caution

If the script terminates unexpectedly, the temporary file may not be deleted.

 

 

Edited by NotionCommotion
Link to comment
Share on other sites

Why do it that way since all you're doing is reinventing tempnam?

1 hour ago, NotionCommotion said:

Does "when the script ends" happen about the same time as the class's destructor?

Yes, but you missed the important part: "when there are no remaining references to the file handle". Which is exactly the case when you use the handle, call stream_get_meta_data on it, and then forget the handle existed.

Link to comment
Share on other sites

If you need an actual file path, then tempnam() is the way to go.   tmpfile is for if you need a temporary file resource, just a shortcut essentially for doing fopen('php://temp', 'w+');.

As an example, I have a html2pdf class that generates some temp files and calls an external program to generate the PDF.  This is how that is coded (roughly).

public function generatePdf(){
	$pdf = null;

	try {
		$source = tempnam(sys_get_temp_dir(), 'htmlpdf');
		$destination = tempnam(sys_get_temp_dir(), 'htmlpdf');

		file_put_contents($source, $this->html);

		$cmd = $this->createCommandLine($source, $destination);
		exec($cmd, $output, $ret);
		if ($ret !== 0){
			throw new \RuntimeException('Failed to generate PDF with command [' . $cmd . '] Output: ' . implode(PHP_EOL, $output));
		}

		$pdf = file_get_contents($destination);
	} finally {
		unlink($source);
		unlink($destination);
	}

	return $pdf;
}

Generate the two temporary file locations, execute the command, then read the content out of the file.  The temporary files are then cleaned up using a finally clause which will run whether the function when the function exits, whether that be by a successful return or by throwing an exception.

 

Link to comment
Share on other sites

1 hour ago, requinix said:

Why do it that way since all you're doing is reinventing tempnam?

Yes, but you missed the important part: "when there are no remaining references to the file handle". Which is exactly the case when you use the handle, call stream_get_meta_data on it, and then forget the handle existed.

I didn't think I was quite reinventing tempnam().  tempnam() doesn't delete the file when complete, correct?  The example in the doc shows unlinking($tmpfname).

However, if calling stream_get_meta_data() deletes the file and I just create it back, and the PHP no longer thinks it is responsible to delete it, suppose I am reinventing.

Link to comment
Share on other sites

43 minutes ago, kicken said:

If you need an actual file path, then tempnam() is the way to go.   tmpfile is for if you need a temporary file resource, just a shortcut essentially for doing fopen('php://temp', 'w+');.

As an example, I have a html2pdf class that generates some temp files and calls an external program to generate the PDF.  This is how that is coded (roughly).

public function generatePdf(){
	$pdf = null;

	try {
		$source = tempnam(sys_get_temp_dir(), 'htmlpdf');
		$destination = tempnam(sys_get_temp_dir(), 'htmlpdf');

		file_put_contents($source, $this->html);

		$cmd = $this->createCommandLine($source, $destination);
		exec($cmd, $output, $ret);
		if ($ret !== 0){
			throw new \RuntimeException('Failed to generate PDF with command [' . $cmd . '] Output: ' . implode(PHP_EOL, $output));
		}

		$pdf = file_get_contents($destination);
	} finally {
		unlink($source);
		unlink($destination);
	}

	return $pdf;
}

Generate the two temporary file locations, execute the command, then read the content out of the file.  The temporary files are then cleaned up using a finally clause which will run whether the function when the function exits, whether that be by a successful return or by throwing an exception.

 

Thanks kicken,  Was just trying to get out of the measly two unlink statements, and will stop trying.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.