您的位置:首页 > 编程语言 > PHP开发

Try-Catch-Finally in PHP

2012-08-29 00:00 246 查看
As of PHP 5.3 web developers can use a wonderful feature of the language, the
__invoke()
magic method
. This enables PHP to provide the Closure class and based on it the ability to define anonymous functions. Anonymous function is a powerful language construct, it can come handy in a number of ways. For example, it makes the code easier to manage by letting you define locally visible small functions inside a method or a function. This is useful when you want to sort an array by some special property of the elements in it – you don’t have to define a named function or method in your global scope or in a class, you can just hide the comparison callback inside the method that needs a specially sorted array. But anonymous functions combined with other language constructs, can even be used to emulate some features missing from PHP:
finally
for instance.

Some say the need for a
finally
keyword is the result of bad design. Most people would use
finally
in a similar situation like this to avoid code duplication in the
catch
block and after the
try
-
catch
statement:

class A
{
public function doSomething()
{
$my_resource = open_my_resource();
try
{
$result = use_my_resource($my_resource);
}
catch (Exception $e)
{
free_my_resource($my_resource);
throw $e;
}
free_my_resource($my_resource);
return $result;
}
}

Using
finally
the above code snippet would look like this:

class A
{
public function doSomething()
{
$my_resource = open_my_resource();
try
{
$result = use_my_resource($my_resource);
}
finally
{
free_my_resource($my_resource);
}
return $result;
}
}

In this situation rethinking the design can help avoid the need for
finally
:

class MyResource
{
public function __construct()
{
$this->resource = open_my_resource();
}

public function __destruct()
{
free_my_resource($this->resource);
}

public function use()
{
return use_my_resource($this->resource);
}

private $resource;
}

class A
{
public function doSomething()
{
$my_resource = new MyResource();
$result = $my_resource->use();
return $result;
}
}


But sometimes life’s not that easy. Sometimes your hands are bound, sometimes it’s not that trivial to circumvent the need for
finally
. That is the case when a nice hack based on closures can help:

class A
{
public function doSomething()
{
$my_resource = open_my_resource();
$finally = finally(function () use ($my_resource)
{
free_my_resource($my_resource);
});
try
{
$result = use_my_resource($my_resource);
}
catch (Exception $e)
{
fprintf(STDERR, "Error: %s\n", $e->getMessage());
throw $e;
}
$finally();
return $result;
}
}

Note that this workaround does not handle the
return
-inside-
finally
problem at all as you cannot return from the function from the simulated
finally
block
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: