服务器端(PHP)过滤和排序使用Ajax和无限滚动服务器端、PHP、Ajax

由网友(泛黄照片。)分享简介:我已经实现了无限的ajax滚动插件到我的项目(​​的https:// github上。 COM / webcreate /无限AJAX滚动)。它是一个PHP项目,其显示的div一个长长的清单。该infinate滚动使用服务器端分页。我也有服务器端过滤和排序,最好想这个使用Ajax,以便它可以很好的和我的无限滚动。我如何...

我已经实现了无限的ajax滚动插件到我的项目(​​的https:// github上。 COM / webcreate /无限AJAX滚动)。它是一个PHP项目,其显示的div一个长长的清单。该infinate滚动使用服务器端分页。我也有服务器端过滤和排序,最好想这个使用Ajax,以便它可以很好的和我的无限滚动。我如何通过过滤器使用Ajax?我已经找到了如何使用JQuery,但无无本使用PHP的过滤的教程。

我发现 http://isotope.metafizzy.co/ 其中既有筛选和无限滚动功能但文件中也建议不要同时使用起来这是一个巨大的耻辱,我因为它看起来像一个巨大的插件。

任何人都可以提出建议,以我这个最好的方法?如果我需要重置的无限​​滚动的时候都选择了新的过滤器,然后那优良。不过,我将如何做到这一点,我如何通过所选择的过滤器,以无限滚动?

下面是我迄今。

  $猫=(使用isset($ _ GET ['猫'])urlde code($ _ GET ['猫']):?'');
    $页=(INT)(!使用isset($ _ GET ['P']))? 1:$ _ GET ['P'];
    $启动=($页* $ pagelimit) -  $ pagelimit;
    $上限= $ pagelimit * $页;

    //得到折扣搜索总数
    $ total_items =东西:: countItems($猫);

    如果($ total_items>($页* $限制)){
      $下一= ++ $页;
    }

    //获取物品
$项目=东西:: getItems($猫,$ sortby,$目录,$开始,$限制);

如果(!$项){
  头(HTTP / 1.0 404未找​​到);
  回声找不到网页!;
  出口();
}

?>
< HTML>
    < HEAD>
        <冠军>< /标题>
        < META HTTP-当量=Content-Type的CONTENT =text / html的;字符集= UTF-8>
        &所述;脚本的src =htt​​p://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js>&所述; /脚本>
        <脚本类型=文/ JavaScript的SRC =JS / jQuery的-ias.min.js>< / SCRIPT>
        <脚本类型=文/ JavaScript的>
          $(文件)。就绪(函数(){
            //无限阿贾克斯滚动配置
            jQuery.ias({
              集装箱:.wrap',//主容器中的数据去追加
              资料:.item',//单品
              分页:.paginate',//页面导航
              下一篇:.paginate一',//翻页选择
              装载机:'< IMG SRC =CSS / AJAX-loader.gif/>',//加载GIF
              noneleft:'没有更多的项目',//包含消息时,有没有更多的页左加载要被显示
              triggerPageThreshold:5,//显示加载更多如果滚动不止这个停止
              触发:加载更多的项目
            });
          });
        < / SCRIPT>
    < /头>
    <身体GT;
    < D​​IV CLASS =包装>
        < PHP
        回声总计:$ total_items'< BR />';。

        //通过类别过滤器* /
        回声按分类筛选:';
        的foreach($类别$类){
            $ categoryURL = urlen code($类);
            回声< A HREF = 的index.php猫= $ categoryURL ?> $类< A /> |;
        }
        //通过循环和显示项目
       的foreach($项目,如$ ID => $项){

           回声< D​​IV的风格= 边界:1px的固体绿色;保证金底:5像素; 级= 项ID = 本期特价货品$ ID >
                    ID:$ ID< BR />
                    $项目[名]< BR />
                    $项目[猫]< BR />
                    $项目[说明]< BR />
            < / DIV>中;
        }
        ?>
    &所述;! -  paginagation  - >
    ?< PHP的,如果(使用isset($明年)):>?
    < D​​IV CLASS =分页>
      < A HREF =?的index.php猫=< PHP的echo $猫>&安培; P =< PHP的echo $下一>?>接着< / A>
    < / DIV>
    <?PHP ENDIF>
    < / DIV>
    < /身体GT;
< / HTML>
 

解决方案

无限滚动和过滤使得只有当你应用过滤器客户端上(对已加载数据)意识和服务器(用于加载未来页)。

不过,运用一些完全不同的过滤器或排序我认为用户希望被带回第一页(或滚动回顶部的无限滚动)之后。 失去一些已经加载的结果是唯一的出路。也许你可以缓存这些结果以提高速度了一下。

为了简单起见,我建议你开始使用 KnockoutJS 或一些类似的客户端MVC库。 jQuery是好这么多的复杂性。在某些时候,你发现你需要更好的东西。

这里有一个程序,我以前工作过的一些时间需要类似的清理提取物。 (编辑链接)

Ajax

您就不再需要页参数都没有。我用它让我的假提供者可能返回顺序,可读性,名称。

服务器端,你需要知道在任何时候(所以也许 $ _ SESSION )当前的查询,你有多少结果发送给客户端。

事情是这样的:

 函数getResults($查询){
    如果($ _ SESSION ['查询'] ['类']!== $查询['类']){
        如果(!array_key_exists($查询['类'],$ _SESSION ['resultsSent'])){
            $ _SESSION ['resultsSent'] [$查询['类'] = 0;
        }
        $ _SESSION ['查询'] = $查询;
    }

    $ SQL =SELECT * FROM foo其中类别=?限制 ?, ?';
    $数据= $ DB->选择($ sql中,数组($ _ SESSION ['查询'] ['类'],$ _SESSION ['resultsSent'] [$查询['分类'],10);

     $ _SESSION ['resultsSent'] [$查询['类'] + =计数($的数据);

    返回json_en code($的数据);
}

如果(!array_key_exists('查询',$ _SESSION)){
    $ _SESSION ['resultsSent'] =阵列();
    $ _SESSION ['查询'] =阵列(); //也许有些默认值吗?
}

如果(array_key_exists('查询',$ _ POST)){
    回声getResults($ _ POST ['查询']);
}
 

您将不得不编写一个 resultsService ,做的AJAX调用。 大概是这样的:

 函数resultsService(){
    this.query =功能(查询,成功){
        jQuery.post({
            网址:的index.php,
            数据:查询,
            成功:成功
        });
    }
}
 

在所有你需要做的就是拍你的无限滚动库之上。

这依赖于一个事实,即(1)客户端,你永远不会删除已加载数据,你只是隐藏它,如果它不适合当前的过滤器和(2)对每个可能的过滤器组合你的服务器知道有多少数据是发送,从而它不再次发送回

如果你有更复杂的过滤器效果都没有独占(一个结果可能由多个过滤器的组合可以回来了 - 想到的价格的评级和数房间的,不会的类别的),那么你最终会落得重复发送到客户端。有没有真正的解决这个除了重置你的整个列表。你可以尝试,并保持所有你发送到客户端,不仅是数量的个人成绩的轨道,并过滤出来,而查询( WHERE ID NOT IN(1,2,17,20, ...)),但对于大数据量的操作肯定是不行的。

有关绝对排序有没有办法解决比知道正是你所发送到客户端或,很明显,重置列表等。

我是 POST 荷兰国际集团一个JS对象作为 JSON 连接codeD字符串(ko.toJS (this.query)),然后 json_de code 荷兰国际集团是在PHP。 无论你如何构建一个JS对象,送它作为 JSON 比手动序列化它自己是 GET 参数更好。

此外,它是最好的,如果你用你所有的过滤器类型的通用格式,并通过一组模式的服务器端处理。

有关 ['分类':1,子类别:2,用户:1234] 我定义 categoryFilter subcategoryFilter userFilter ,利用给他们打电话 call_user_func 并通过过滤值以及查询参数,将位它为每一个。

  $查询= DB ::表(东西);

$过滤器= json_de code($ _ POST ['查询']);
的foreach($过滤器为$ FILTERNAME => $值){
    $查询= call_user_func_array($ FILTERNAME'过滤器',数组($查询,$值)。);
}

$结果= $查询 - >获得();

功能categoryFilter($查询,$值){
    $查询 - 化合物其中('CATEGORY_ID','=',$值);

    返回$查询;
}
 

如何实际code看起来像,你会多么容易能够建立SQL查询取决于你所使用。我上面所用的DB类是一个捆绑 Laravel 。

在客户端创建的查询对象不应是很难甚至与基本的jQuery

I have implemented the infinite-ajax-scroll plugin onto my project (https://github.com/webcreate/infinite-ajax-scroll) . Its a PHP project which displays a long list of divs. The infinate scroll uses server side pagination. I also have server side filtering and ordering and ideally would like this to use Ajax so that it works nicely with my infinite scroll. How do I pass the filters using Ajax? I have found tutorials on how to filter using JQuery but none none of this using PHP.

I did find http://isotope.metafizzy.co/ which has both filtering and infinite scrolling capabilities but in the documentation it advises against using both together which is a massive shame for me as it looks like a great plugin.

Can anyone advise on my best approach to this? If I need to reset the infinite scroll when new filters are selected then thats fine. But how would I do this and how do I pass the selected filters to the infinite scroll?

Below is what I have thus far.

    $cat = (isset($_GET['cat']) ? urldecode($_GET['cat']) : ''); 
    $page = (int) (!isset($_GET['p'])) ? 1 : $_GET['p'];
    $start = ($page * $pagelimit) - $pagelimit;
    $limit = $pagelimit*$page; 

    //get total number of discounts for search
    $total_items = Stuff::countItems($cat);

    if( $total_items > ($page * $limit) ){
      $next = ++$page;
    }

    //get items
$items = Stuff::getItems($cat, $sortby, $dir, $start, $limit);

if(!$items){
  header('HTTP/1.0 404 Not Found');
  echo 'Page not found!';
  exit();
} 

?>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script type="text/javascript" src="js/jquery-ias.min.js"></script>
        <script type="text/javascript">
          $(document).ready(function() {
            // Infinite Ajax Scroll configuration
            jQuery.ias({
              container : '.wrap', // main container where data goes to append
              item: '.item', // single items
              pagination: '.paginate', // page navigation
              next: '.paginate a', // next page selector
              loader: '<img src="css/ajax-loader.gif"/>', // loading gif
              noneleft: 'No more items', //Contains the message to be displayed when there are no more pages left to load
              triggerPageThreshold: 5, // show "load more" if scroll more than this to stop
              trigger: "Load more items"
            });
          });
        </script>
    </head>
    <body>
    <div class="wrap">    
        <?php
        echo 'TOTAL: '.$total_items .'<br />';

        //filter through categories*/
        echo 'FILTER BY CATEGORY:';
        foreach ($categories as $category){
            $categoryURL = urlencode($category);
            echo "<a href="index.php?cat=$categoryURL">$category<a/> | ";
        }       
        //loop through and display items
       foreach ($items as $id => $item){

           echo "<div style="border:1px solid green;margin-bottom:5px;" class="item" id="item-$id">
                    ID: $id <br />
                    $item[name]<br />                                                                                                                                                                                                                                
                    $item[cat]<br />
                    $item[description]<br />
            </div>";
        }
        ?>
    <!--paginagation-->
    <?php if (isset($next)): ?>
    <div class="paginate">
      <a href='index.php?cat=<?php echo $cat?>&p=<?php echo $next?>'>Next</a>
    </div>
    <?php endif?>
    </div>
    </body>
</html>

解决方案

Infinite scroll and filtering makes sense only if you apply the filters on both client (for already loaded data) and server (for future pages to be loaded).

But after applying some totally different filter or sorting I would think that a user would like to be brought back to the first page (or scrolled back to top for infinite scroll). Losing some already loaded results is the only way. You could maybe cache those results to improve speed a bit.

To make this easy I recommend you start using KnockoutJS or some similar client-side MVC library. jQuery is good for so much complexity. At some point you find out you need something better.

Here's a cleaned up extract of an app I worked on some time ago that needed something similar. (edit link)

You won't need that "page" parameter at all. I used it so that my "fake" provider could return sequential, readable, names.

Server-side you need to know at any moment (so maybe $_SESSION) for the current query how many results you've sent to the client.

Something like this:

function getResults($query) {
    if($_SESSION['query']['category'] !== $query['category']) {
        if(!array_key_exists($query['category'], $_SESSION['resultsSent'])) {
            $_SESSION['resultsSent'][$query['category']] = 0;
        }
        $_SESSION['query'] = $query; 
    }

    $sql = 'SELECT * FROM foo WHERE category = ? LIMIT ?, ?';
    $data = $db->select($sql, array($_SESSION['query']['category'],  $_SESSION['resultsSent'][$query['category']], 10);

     $_SESSION['resultsSent'][$query['category']] += count($data);

    return json_encode($data);
}

if(!array_key_exists('query', $_SESSION)) {
    $_SESSION['resultsSent'] = array();
    $_SESSION['query'] = array(); // maybe some defaults here?
}

if(array_key_exists('query', $_POST)) {
    echo getResults($_POST['query']);
}

You'll have to write a resultsService that does the AJAX call. Probably something like this:

function resultsService() {
    this.query = function(query, success) {
        jQuery.post({
            url: 'index.php', 
            data: query,
            success: success
        });
    }
}

After that all you have to do is slap your infinite scroll library on top.

This relies on the fact that (1) on the client you never remove data already loaded, you just hide it if it does not fit the current filters and (2) for each possible filter combination your server knows how much data it sent so that it does not send it back again.

If you have more complex filters with results that are not exclusive (one result may be returned for multiple filter combinations - think price, rating and number of rooms, not categories) then you'll eventually end up sending duplicates to the client. There's no real solution to this other than resetting your whole list. You could try and keep track of all the individual results you've sent to the client, not only the count, and filter them out while querying (WHERE id NOT IN (1, 2, 17, 20, ...)) but this will definitely not work for large amounts of data.

For sorting there absolutely is no solution other than knowing exactly what you've sent to the client or, obviously, resetting the list.

I'm POSTing a JS object as a JSON encoded string (ko.toJS(this.query)) and then json_decodeing it in PHP. No matter how you build that JS object, sending it as JSON is better than manually serializing it yourself as GET parameters.

Also it's best if you use a common format for all your filter types and handle them by a set pattern server-side.

For ['category': 1, 'subcategory':2, 'user': 1234] I'd define categoryFilter, subcategoryFilter and userFilter, call them using call_user_func and pass the filtered value as a parameter along your query, adding bits to it for each one.

$query = DB::table('stuff');

$filters = json_decode($_POST['query']);
foreach($filters as $filterName => $value) {
    $query = call_user_func_array($filterName . 'Filter', array($query, $value));
}

$results = $query->get();

function categoryFilter($query, $value) {
    $query->where('category_id', '=', $value);

    return $query;
}

How your actual code will look like and how easy you'll be able to build the SQL query depends on what you are using. The DB class I've used above is the one bundled with Laravel.

On the client-side building the query object should not be that hard even with basic jQuery.

阅读全文

相关推荐

最新文章