2013-04-05 70 views
0

我遇到了问题,我的网格不按预期排序/过滤。我总是从数据库中获取所有结果。KendoUI网格服务器端排序/过滤器不适用于SQL查询

这里是我的JS:

<script> 
'use strict'; 
(function($, kendo) { 
    $("#grid").kendoGrid({ 
     dataSource: { 
      type: "json", 
      transport: { 
       read: { 
        url:"http://server01/read.php", 
        type: "POST" 
       } 
      }, 
      schema: { 
       data: "data", 
       total: "total", 
       model: { 
        fields: { 
         tID: { type: "number" }, 
         tTitle: { type: "string" }, 
         oDate: { type: "date" }, 
         eDate: { type: "date" }, 
         cDate: { type: "date" }, 
         tKeywords: { type: "string" } 
        } 
       } 
      }, 
      pageSize: 2, 
      serverPaging: true, 
      serverFiltering: true, 
      serverSorting: true 
     }, 
     height: 430, 
     filterable: true, 
     sortable: true, 
     pageable: true, 
     columns: [{ 
       field:"tID", 
       title:"TicketID", 
       width:"60px", 
       filterable: false 
      },{ 
       field: "tTitle", 
       title: "Ticket Bezeichnung" 
      }, { 
       field: "oDate", 
       title: "Ticket eröffnet", 
       format: "{0:MM/dd/yyyy}", 
       width: "160px" 
      }, { 
       field: "eDate", 
       title: "Ticket escaliert", 
       format: "{0:MM/dd/yyyy}", 
       width: "160px" 
      }, { 
       field: "cDate", 
       title: "Ticket geschlossen", 
       format: "{0:MM/dd/yyyy}", 
       width: "160px" 

      }, { 
       field: "tKeywords", 
       title: "keywords" 
      } 
     ] 
    }); 
})(jQuery, kendo); 

在服务器端,它看起来像这样:

error_reporting(E_ALL); 
include 'classes/classes.php'; 
if ($_SERVER['REQUEST_METHOD'] == 'POST') { 
    header('Content-Type: application/json'); 
    $request = json_encode($_POST); 
    $result = new DataSourceResult('mysql:host=localhost;dbname=jarvis','root','',array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')); 
    echo json_encode($result->read('jar_ticketing_index', array('tID', 'tTitle', 'tDesc', 'oDate', 'eDate', 'cDate','tKeywords'), $request)); 
}else{ 
    echo "Opps..."; 
} 

对于应用过滤器来查询我使用的dataSourceResult类:

class DataSourceResult { 
    private $db; 

    private $stringOperators = array(
     'eq' => 'LIKE', 
     'neq' => 'NOT LIKE', 
     'doesnotcontain' => 'NOT LIKE', 
     'contains' => 'LIKE', 
     'startswith' => 'LIKE', 
     'endswith' => 'LIKE' 
    ); 

    private $operators = array(
     'eq' => '=', 
     'gt' => '>', 
     'gte' => '>=', 
     'lt' => '<', 
     'lte' => '<=', 
     'neq' => '!=' 
    ); 

    private $aggregateFunctions = array(
     'average' => 'AVG', 
     'min' => 'MIN', 
     'max' => 'MAX', 
     'count' => 'COUNT', 
     'sum' => 'SUM' 
    ); 

    function __construct($dsn, $username=null, $password=null, $driver_options=null) { 
     $this->db = new PDO($dsn, $username, $password, $driver_options); 

    } 

    private function total($tableName, $properties, $request) { 
     if (isset($request->filter)) { 
      $where = $this->filter($properties, $request->filter); 
      $statement = $this->db->prepare("SELECT COUNT(*) FROM $tableName $where"); 
      $this->bindFilterValues($statement, $request->filter); 
     } else { 
      $statement = $this->db->prepare("SELECT COUNT(*) FROM $tableName"); 
     } 

     $statement->execute(); 

     $total = $statement->fetch(PDO::FETCH_NUM); 
     return (int)($total[0]); 
    } 

    private function page() { 
     return ' LIMIT :skip,:take'; 
    } 

    private function group($data, $groups, $table, $request, $properties) { 
     if (count($data) > 0) { 
      return $this->groupBy($data, $groups, $table, $request, $properties); 
     } 
     return array(); 
    } 

    private function mergeSortDescriptors($request) { 
     $sort = isset($request->sort) && count($request->sort) ? $request->sort : array(); 
     $groups = isset($request->group) && count($request->group) ? $request->group : array(); 

     return array_merge($sort, $groups); 
    } 

    private function groupBy($data, $groups, $table, $request, $properties) { 
     if (count($groups) > 0) { 
      $field = $groups[0]->field; 
      $count = count($data); 
      $result = array(); 
      $value = $data[0][$field]; 
      $aggregates = isset($groups[0]->aggregates) ? $groups[0]->aggregates : array(); 

      $hasSubgroups = count($groups) > 1; 
      $groupItem = $this->createGroup($field, $value, $hasSubgroups, $aggregates, $table, $request, $properties); 

      for ($index = 0; $index < $count; $index++) { 
       $item = $data[$index]; 
       if ($item[$field] != $value) { 
        if (count($groups) > 1) { 
         $groupItem["items"] = $this->groupBy($groupItem["items"], array_slice($groups, 1), $table, $request, $properties); 
        } 

        $result[] = $groupItem; 

        $groupItem = $this->createGroup($field, $data[$index][$field], $hasSubgroups, $aggregates, $table, $request, $properties); 
        $value = $item[$field]; 
       } 
       $groupItem["items"][] = $item; 
      } 

      if (count($groups) > 1) { 
       $groupItem["items"] = $this->groupBy($groupItem["items"], array_slice($groups, 1), $table, $request, $properties); 
      } 

      $result[] = $groupItem; 

      return $result; 
     } 
     return array(); 
    } 

    private function addFilterToRequest($field, $value, $request) { 
     $filter = (object)array(
      'logic' => 'and', 
      'filters' => array(
       (object)array(
        'field' => $field, 
        'operator' => 'eq', 
        'value' => $value 
       )) 
      ); 

     if (isset($request->filter)) { 
      $filter->filters[] = $request->filter; 
     } 

     return (object) array('filter' => $filter); 
    } 

    private function addFieldToProperties($field, $properties) { 
     if (!in_array($field, $properties)) { 
      $properties[] = $field; 
     } 
     return $properties; 
    } 

    private function createGroup($field, $value, $hasSubgroups, $aggregates, $table, $request, $properties) { 
     if (count($aggregates) > 0) { 
      $request = $this->addFilterToRequest($field, $value, $request); 
      $properties = $this->addFieldToProperties($field, $properties); 
     } 

     $groupItem = array(
      'field' => $field, 
      'aggregates' => $this->calculateAggregates($table, $aggregates, $request, $properties), 
      'hasSubgroups' => $hasSubgroups, 
      'value' => $value, 
      'items' => array() 
     ); 

     return $groupItem; 
    } 

    private function calculateAggregates($table, $aggregates, $request, $properties) { 
     $count = count($aggregates); 

     if (count($aggregates) > 0) { 
      $functions = array(); 

      for ($index = 0; $index < $count; $index++) { 
       $aggregate = $aggregates[$index]; 
       $name = $this->aggregateFunctions[$aggregate->aggregate]; 
       $functions[] = $name.'('.$aggregate->field.') as '.$aggregate->field.'_'.$aggregate->aggregate; 
      } 

      $sql = sprintf('SELECT %s FROM %s', implode(', ', $functions), $table); 

      if (isset($request->filter)) { 
       $sql .= $this->filter($properties, $request->filter); 
      } 

      $statement = $this->db->prepare($sql); 

      if (isset($request->filter)) { 
       $this->bindFilterValues($statement, $request->filter); 
      } 

      $statement->execute(); 

      $result = $statement->fetchAll(PDO::FETCH_ASSOC); 

      return $this->convertAggregateResult($result[0]); 
     } 
     return (object)array(); 
    } 

    private function convertAggregateResult($properties) { 
     $result = array(); 

     foreach($properties as $property => $value) { 
      $item = array(); 
      $split = explode('_', $property); 
      $field = $split[0]; 
      $function = $split[1]; 
      if (array_key_exists($field, $result)) { 
       $result[$field][$function] = $value; 
      } else { 
       $result[$field] = array($function => $value); 
      } 
     } 

     return $result; 
    } 

    private function sort($properties, $sort) { 
     $count = count($sort); 

     $sql = ''; 

     if ($count > 0) { 
      $sql = ' ORDER BY '; 

      $order = array(); 

      for ($index = 0; $index < $count; $index ++) { 
       $field = $sort[$index]->field; 

       if (in_array($field, $properties)) { 
        $dir = 'ASC'; 

        if ($sort[$index]->dir == 'desc') { 
         $dir = 'DESC'; 
        } 

        $order[] = "$field $dir"; 
       } 

      } 

      $sql .= implode(',', $order); 
     } 

     return $sql; 
    } 

    private function where($properties, $filter, $all) { 
     if (isset($filter->filters)) { 
      $logic = ' AND '; 

      if ($filter->logic == 'or') { 
       $logic = ' OR '; 
      } 

      $filters = $filter->filters; 

      $where = array(); 

      for ($index = 0; $index < count($filters); $index++) { 
       $where[] = $this->where($properties, $filters[$index], $all); 
      } 

      $where = implode($logic, $where); 

      return "($where)"; 
     } 

     $field = $filter->field; 

     if (in_array($field, $properties)) { 
      $index = array_search($filter, $all); 

      $value = ":filter$index"; 

      if ($this->isDate($filter->value)) { 
       $field = "date($field)"; 
       $value = "date($value)"; 
      } 

      if ($this->isString($filter->value)) { 
       $operator = $this->stringOperators[$filter->operator]; 
      } else { 
       $operator = $this->operators[$filter->operator]; 
      } 

      return "$field $operator $value"; 
     } 
    } 

    private function flatten(&$all, $filter) { 
     if (isset($filter->filters)) { 
      $filters = $filter->filters; 

      for ($index = 0; $index < count($filters); $index++) { 
       $this->flatten($all, $filters[$index]); 
      } 
     } else { 
      $all[] = $filter; 
     } 
    } 

    private function filter($properties, $filter) { 
     $all = array(); 

     $this->flatten($all, $filter); 

     $where = $this->where($properties, $filter, $all); 

     return " WHERE $where"; 
    } 

    private function isDate($value) { 
     $result = date_parse($value); 
     return $result["error_count"] < 1; 
    } 

    private function isString($value) { 
     return !is_bool($value) && !is_numeric($value) && !$this->isDate($value); 
    } 

    private function bindFilterValues($statement, $filter) { 
     $filters = array(); 
     $this->flatten($filters, $filter); 

     for ($index = 0; $index < count($filters); $index++) { 
      $value = $filters[$index]->value; 
      $operator = $filters[$index]->operator; 
      $date = date_parse($value); 

      if ($operator == 'contains' || $operator == 'doesnotcontain') { 
       $value = "%$value%"; 
      } else if ($operator == 'startswith') { 
       $value = "$value%"; 
      } else if ($operator == 'endswith') { 
       $value = "%$value"; 
      } 

      $statement->bindValue(":filter$index", $value); 
     } 
    } 

    public function create($table, $properties, $models, $key) { 
     $result = array(); 
     $data = array(); 

     if (!is_array($models)) { 
      $models = array($models); 
     } 

     $errors = array(); 

     foreach ($models as $model) { 
      $columns = array(); 
      $values = array(); 
      $input_parameters = array(); 

      foreach ($properties as $property) { 
       if ($property != $key) { 
        $columns[] = $property; 
        $values[] = '?'; 
        $input_parameters[] = $model->$property; 
       } 
      } 

      $columns = implode(', ', $columns); 
      $values = implode(', ', $values); 

      $sql = "INSERT INTO $table ($columns) VALUES ($values)"; 

      $statement = $this->db->prepare($sql); 

      $statement->execute($input_parameters); 

      $status = $statement->errorInfo(); 

      if ($status[1] > 0) { 
       $errors[] = $status[2]; 
      } else { 
       $model->$key = $this->db->lastInsertId(); 
       $data[] = $model; 
      } 
     } 

     if (count($errors) > 0) { 
      $result['errors'] = $errors; 
     } else { 
      $result['data'] = $data; 
     } 

     return $result; 
    } 

    public function destroy($table, $models, $key) { 
     $result = array(); 

     if (!is_array($models)) { 
      $models = array($models); 
     } 

     $errors = array(); 

     foreach ($models as $model) { 
      $sql = "DELETE FROM $table WHERE $key=?"; 

      $statement = $this->db->prepare($sql); 

      $statement->execute(array($model->$key)); 

      $status = $statement->errorInfo(); 

      if ($status[1] > 0) { 
       $errors[] = $status[2]; 
      } 
     } 

     if (count($errors) > 0) { 
      $result['errors'] = $errors; 
     } 

     return $result; 
    } 

    public function update($table, $properties, $models, $key) { 
     $result = array(); 

     if (in_array($key, $properties)) { 

      if (!is_array($models)) { 
       $models = array($models); 
      } 

      $errors = array(); 

      foreach ($models as $model) { 
       $set = array(); 

       $input_parameters = array(); 

       foreach ($properties as $property) { 
        if ($property != $key) { 
         $set[] = "$property=?"; 
         $input_parameters[] = $model->$property; 
        } 
       } 

       $input_parameters[] = $model->$key; 

       $set = implode(', ', $set); 

       $sql = "UPDATE $table SET $set WHERE $key=?"; 

       $statement = $this->db->prepare($sql); 

       $statement->execute($input_parameters); 

       $status = $statement->errorInfo(); 

       if ($status[1] > 0) { 
        $errors[] = $status[2]; 
       } 
      } 

      if (count($errors) > 0) { 
       $result['errors'] = $errors; 
      } 
     } 

     if (count($result) == 0) { 
      $result = ""; 
     } 

     return $result; 
    } 

    public function read($table, $properties, $request = null) { 
     $result = array(); 

     $result['total'] = $this->total($table, $properties, $request); 

     $sql = sprintf('SELECT %s FROM %s', implode(', ', $properties), $table); 

     if (isset($request->filter)) { 
      $sql .= $this->filter($properties, $request->filter); 
     } 

     $sort = $this->mergeSortDescriptors($request); 

     if (count($sort) > 0) { 
      $sql .= $this->sort($properties, $sort); 
     } 

     if (isset($request->skip) && isset($request->take)) { 
      $sql .= $this->page(); 
     } 

     $statement = $this->db->prepare($sql); 

     if (isset($request->filter)) { 
      $this->bindFilterValues($statement, $request->filter); 
     } 

     if (isset($request->skip) && isset($request->take)) { 
      $statement->bindValue(':skip', (int)$request->skip, PDO::PARAM_INT); 
      $statement->bindValue(':take', (int)$request->take, PDO::PARAM_INT); 
     } 

     $statement->execute(); 

     $data = $statement->fetchAll(PDO::FETCH_ASSOC); 

     if (isset($request->group) && count($request->group) > 0) { 
      $data = $this->group($data, $request->group, $table, $request, $properties); 
      $result['groups'] = $data; 
     } else { 
      $result['data'] = $data; 
     } 

     if (isset($request->aggregate)) { 
      $result["aggregates"] = $this->calculateAggregates($table, $request->aggregate, $request, $properties); 
     } 

     return $result; 
    } 
} 

我总是从数据库中获取所有记录。它看起来像我的DataSourceResult对象没有得到正确的方式过滤器变量。但我根本没有看到任何错误。

你能给我一个提示吗?

+0

那么你如何将过滤器应用到网格?你可以发布应用过滤器的代码吗? – 2013-04-05 12:54:13

+0

你是什么意思?当我点击标题栏时,我看到在FireBug中触发了ajax请求。还有返回的JSON,但它不在预期的新订单中。我只是把所有的记录都拿回来了,因为我把它们放在了网格中。 – 2013-04-05 13:00:59

回答

0

奥克我指出了。我通过POST获取的过滤器需要作为对象传递给dataSourceResult类。 $ object = json_decode(json_encode($ _ POST),FALSE);}};}}

现在它的工作就像一个魅力!

+0

我有类似的问题。我的设置基本上和你的一样。 DataSourceResult类正在返回正确的数据,并使用任何常规运算符进行筛选。但是,使用字符串操作符进行筛选不起作用。 – Mat 2013-04-15 12:42:52

+0

糟糕...对它进行排序:我没有使用ParameterMap对读取参数进行字符串化。它现在完美。 – Mat 2013-04-15 13:15:43