implementation of C# "using" statement in PHP
using(new File(__DIR__ . "/file.txt", 'w'), function (File $file) {
$file->write("Hello\n");
$file->write("Hello\n");
$file->write("Hello\n");
});
Imagine this class:
class File
{
private $resource;
public function __construct($filename, $mode)
{
$this->resource = fopen($filename, $mode);
}
public function write($string)
{
fwrite($this->resource, $string);
}
public function close()
{
fclose($this->resource);
}
}
We can use this class:
$file = new File(__DIR__ . "/file.txt", 'w');
$file->write("Hello\n");
// ...
// some other things
// ...
$file->write("Hello\n");
$file->close();
What happens if there is an exceptions in "some other things"? Simple: close() function isn't called.
We can solve the problem with try - catch:
try {
$file->write("Hello\n");
// ...
// some other things
// ...
$file->write("Hello\n");
$file->close();
} catch (\Exception $e) {
$file->close();
}
or using "finally" keyword is we use PHP5.5
try {
$file->write("Hello\n");
// ...
// some other things
// ...
$file->write("Hello\n");
} catch (\Exception $e) {
} finally {
$file->close();
}
c# has "using" statement to solve this problem in a smart way.
http://msdn.microsoft.com/en-us//library/yh598w02(v=vs.90).aspx
We're going to implement something similar in PHP.
First we will add G\IDisposable interface to our File class
namespace G;
interface IDisposable
{
public function dispose();
}
Now our File class looks like this:
class File implements IDisposable
{
private $resource;
public function __construct($filename, $mode)
{
$this->resource = fopen($filename, $mode);
}
public function write($string)
{
fwrite($this->resource, $string);
}
public function close()
{
fclose($this->resource);
}
public function dispose()
{
$this->close();
}
}
And we can use our "using" funcion in PHP:
using(new File(__DIR__ . "/file.txt", 'w'), function (File $file) {
$file->write("Hello\n");
$file->write("Hello\n");
$file->write("Hello\n");
});
As we can see we can forget to close() our file instance. "using" will do it for us, even if one exception is triggered inside.
We also can use an array of instances (implementing the IDisposable interface of course)
using([new Bar, new Foo], function (Bar $bar, Foo $foo) {
echo $bar->hello("Gonzalo");
echo $foo->hello("Gonzalo");
});