2016年6月

slim框架中pjax的实现

pjax = pushState + ajax

由于这是一个比较通用的组件,所以我把它写成了slim的Middleware (如果不知道middleware是什么或者怎么写,可以看这里)

大概原理是在slim框架渲染之后,输出之前,对dom结构进行分析,摘取出pjax所需要的部分,然后将这部分的内容作为response返回给浏览器的ajax请求

预览: 码农文库 点击分页可以看到效果

$app->add(new \Support\PjaxMiddleware());
<?php
namespace Support;

use Slim\Middleware;
use Slim\Http\Request;
use Slim\Http\Response;
use Symfony\Component\DomCrawler\Crawler;
class PjaxMiddleware extends Middleware
{
    public function call()
    {
        $request = $this->app->request();
        $response = $this->app->response();
        $this->next->call();
        if (!$request->headers('X-PJAX') || $response->isRedirect()) {
            return;
        }
        $this->filterResponse($response, $request->headers('X-PJAX-CONTAINER'))->setUriHeader($response, $request);
    }
    private function filterResponse(Response $response, $container)
    {
        $crawler = new Crawler($response->getBody());
        $response->setBody($this->makeTitle($crawler) . $this->fetchContents($crawler, $container));
        return $this;
    }
    private function makeTitle(Crawler $crawler)
    {
        $title = $crawler->filter('head > title')->html();
        return "<title>{$title}</title>";
    }
    private function fetchContents(Crawler $crawler, $container)
    {
        $content = $crawler->filter($container);
        if (!$content->count()) {
            $this->app->stop();
        }
        return $content->html();
    }
    private function setUriHeader(Response $response, Request $request)
    {
        $query = $request->get();
        unset($query['_pjax']);
        $response->header('X-PJAX-URL', $request->getResourceUri() . '?' . http_build_query($query));
    }
}