Php Silex控制器中的动作方法代码重用
今天,在为Silex应用程序创建简单控制器时,我注意到许多操作方法的代码几乎相同:Php Silex控制器中的动作方法代码重用,php,silex,Php,Silex,今天,在为Silex应用程序创建简单控制器时,我注意到许多操作方法的代码几乎相同: public function someAction() { $id = $this->request->attributes->get('id') if($id) { $data = getMyDataFromDatabaseWithThisID($id); //do something with data $this
public function someAction()
{
$id = $this->request->attributes->get('id')
if($id)
{
$data = getMyDataFromDatabaseWithThisID($id);
//do something with data
$this->app->json($data, 200);
}
else
{
//do error stuff
}
}
public function someOtherAction()
{
$id = $this->request->attributes->get('id')
if($id)
{
$data = getMyDataFromDatabaseWithThisID($id);
//do something else with data
$this->app->json($data, 200);
}
else
{
//do error stuff
}
}
每种方法的要点几乎完全相同。我想如果我有3或4个方法遵循相同的模式,我可能应该抽象出一些代码
我的第一反应是使用一个大的executeAction($action)方法,但我不知道如何从Silex路由将变量传递给被调用的控制器操作。第二,我认为用一个大的方法代替很多小的方法是自找麻烦
我的下一个想法是创建一个executeAction(Closure$action)方法,该方法由传递所需任务的闭包的现有操作方法调用
因此,像updateAction()这样的操作方法可以将闭包传递给executeAction(),告诉它更新所需的资源:
public function updateAction
{
$this->executeAction(function($resource, $request) {
$resource->doSomethingToUpdateItFromInfoInRequest($request->get('data'));
});
}
public function executeAction(Closure $action)
{
$id = $this->request->attributes->get('id')
if($id)
{
$data = getMyDataFromDatabaseWithThisID($id);
//execute closure action
$action($data, $this->request);
$this->app->json($data, 200);
}
else
{
//do error stuff
}
}
从表面上看,这看起来很干净。它也很灵活,因为它取决于每个单独的方法是否使用executeAction。这个想法的问题是,我需要确保在闭包中所做的任何事情都在闭包之外得到正确反映(即变量/对象是否正确更新等)。这也感觉不是正确的方法。虽然这可能是因为PHP中的闭包对我来说是相当新的(在使用Silex之前,我从未在PHP代码中使用过它们)
第三种选择是将一些公共部分简化为它们自己的方法,例如
public function getResourceById($id)
{
//do stuff
return $resource;
}
public function errorStuff($code, $message)
{
//do stuff
}
//then in action method
public function updateAction()
{
$data = $this->getResourceById($this->request->get('id');
if($data)
{
//do stuff
}
else
{
$this->errorStuff(1001, 'uh oh!');
}
}
该方法看起来更小,但存在相同的问题-我将有几个看起来几乎相同的方法,如果有什么变化(方法名称等),则需要更新这些方法
因此,考虑到我正在使用Silex和Silex控制器类,这些方法中哪一种(如果有的话)是避免代码重复的更好选择?有人能提出完全不同的解决方案吗?您上面的代码在我看来不像silex代码库,更像symfony控制器。
所以我不会对这一点发表评论 不过,我建议您熟悉闭包,因为您已经重新连接了闭包,因为它们在Silex中大量使用 出于您的目的,您可能希望了解的Silex实现。
他们可以使用ThisID函数从数据库获取GetMyDataFromDatabase的一部分。此外,它们还可以处理错误 您可以在应用程序中注册findOr404方法:
$app['findOr404'] = $app->protect(function($id, $message = null) use ($app) {
//get the data or abort with 404
}
并将其用作Silex控制器中的参数转换器:
$app->get("/get/{id}", function (Data $data) {
// ...
})->convert("id", $app['findOr404']($id);
这个例子的灵感来源于此,你可以在这里找到更多的技巧
如果您在闭包中迷路了,还可以看看如何包装您的代码。这可能感觉有点熟悉。我在Silex项目中使用控制器类。我喜欢Silex使用简单闭包作为动作的能力(我用它来做更简单的事情),但我确实喜欢将相关动作组合到一个控制器中。我从来没有想过要看param转换器,所以谢谢你让我注意到它们。我认为建议的
findOr404
方法是一个很好的主意,可以帮助我避免很多重复。它可以在所有操作和控制器中重用也是一个很大的优点!