这个问题就是一个案例。
让我们设想一个显示过滤产品列表的网站页面:
如果我在浏览器中请求/products?foo=bar
,我会在布局中包含一个完整页面,该布局包含一个标题,其中包含允许更改搜索标准的表单。
如果我将foo
值更改为baz
并提交表单,则会动态重新加载结果(例如,使用jQuery $.load()
),调用{{1}在Ajax中。
如果我在iPhone应用程序中输入相同的条件,应用程序会向服务器请求/products?foo=baz
,服务器会回复json对象。
所有3个调用都引用相同的资源(“产品列表”,资源意图与 REST资源一样),但都需要不同的呈现。
这个渲染开关可以由标题/products?foo=bar
(带或不带布局)和X-Requested-With
(html / json)触发。
在Phalcon中,给定的示例可以实现为:
Accept
我如何在应用程序范围内实现此机制,而不是在每个操作中复制此行为?
答案 0 :(得分:2)
最简单的方法是将数据以统一格式(如果还没有)合并到一起,并将其传递给基本控制器中的方法,以与您在示例中显示的方式完全相同的方式处理该逻辑。
abstract class AbstractController extends \Phalcon\Mvc\Controller
{
protected function prepareResponse($data)
{
// JSON is identified
if ($this->request->getBestAccept() == 'application/json')
{
// JSON rendering (case 3)
$this->response->setContentType('application/json');
$this->response->setJsonContent($data);
$this->view->disable();
return $this->response;
}
// Otherwise, defaults to HTML
// Passing data to the view
$this->view->setVars($data);
// Ajax call is identified
if ($this->request->isAjax())
{
// Partial rendering (case 2)
$view->disableLevel(array(
View::LEVEL_LAYOUT => true,
View::LEVEL_MAIN_LAYOUT => true
));
}
// Defaults to normal rendering
else
{
// Layout rendering (case 1)
}
return null;
}
}
class ProductsController extends AbstractController
{
public function indexAction()
{
// Build data and prepare response
return this->prepareResponse(array(
'products' => Products::find(array(
'foo' => $this->request->get('foo')
))
));
}
}
否则,它可能有点棘手。我看到以下备选方案。
使用renderJson
和renderPartial
方法扩展您的基本控制器,以处理这些逻辑位(否则默认),但在您的操作中,您仍需要检查要调用哪一个。复制...
使用路由器做一些疯狂的事情以进行不同的操作,例如indexJsonAction
和indexPartialAction
(否则默认),具体取决于条件。但你最终会得到臃肿的控制器。