Ajax 根据标题切换渲染,应用程序范围
这是一个有待解决的问题 让我们设想一个显示过滤产品列表的网站页面:Ajax 根据标题切换渲染,应用程序范围,ajax,content-type,phalcon,Ajax,Content Type,Phalcon,这是一个有待解决的问题 让我们设想一个显示过滤产品列表的网站页面: 如果我在浏览器中请求/products?foo=bar,我会得到一个包装在版面中的完整页面,该版面包含一个标题,该标题带有一个允许更改搜索标准的表单 如果我将foo值更改为baz并提交表单,它将动态地重新加载结果(例如,使用jQuery$.load()),在Ajax中调用/products?foo=baz 如果我在iPhone应用程序中输入相同的条件,应用程序会向服务器请求/products?foo=bar,服务器会用json对
/products?foo=bar
,我会得到一个包装在版面中的完整页面,该版面包含一个标题,该标题带有一个允许更改搜索标准的表单foo
值更改为baz
并提交表单,它将动态地重新加载结果(例如,使用jQuery$.load()
),在Ajax中调用/products?foo=baz
/products?foo=bar
,服务器会用json对象进行回复X-request-With
(带或不带布局)和Accept
(html/json)触发
在Phalcon中,给出的示例可以实现为:
class ProductsController扩展\Phalcon\Mvc\Controller
{
公共函数索引()
{
//构建数据
$products=products::查找(数组)(
'foo'=>this->request->get('foo')
));
//JSON被识别
如果($this->request->getBestAccept()=='application/json')
{
//JSON呈现(案例3)
$this->response->setContentType('application/json');
$this->response->setJsonContent($products);
$this->view->disable();
返回$this->response;
}
//否则,默认为HTML
其他的
{
//向视图传递数据
$this->view->products=$products;
//Ajax调用被识别
如果($this->request->isAjax())
{
//部分渲染(案例2)
$view->disableLevel(数组)(
视图::LEVEL_布局=>true,
视图::LEVEL_MAIN_布局=>true
));
}
//默认为正常渲染
其他的
{
//布局渲染(案例1)
}
}
}
}
如何在应用程序范围内实现此机制,而不是在每个操作中重复此行为?最简单的方法是以统一的格式(如果还没有)将数据收集在一起,并将其传递给基本控制器中的方法,以与示例中所示的方式大致相同的方式处理该逻辑
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
(默认情况下为其他),具体取决于条件。但你最终会遇到臃肿的控制器。我想没有内置的准备响应吧?(类似于)有,但不是那种,因为“最终准备响应”发生在handle
方法中的调度程序和应用程序中。你可以覆盖它们,但我认为这不会有任何好处。还有一些可能是有用的,但它不是像上面那样高效/优雅的解决方案。它感觉你在寻找一种“真正的Phalcon方法”来做到这一点:)幸运的是,它并没有为每个问题提供解决方案,所以不要因为以你想要/需要的方式扩展它而感到内疚。我知道,以上是回答你问题的完美方法——比事件或其他任何事情都好。事实上,我是这样的,因为我一周前才发现:)我目前正试图“坚持书本”,而不是深入“重新发明轮子”。