jquery DataTables在搜索框上出错

时间:2013-12-31 09:02:31

标签: pdo datatables jquery-datatables

尝试让DataTables与PDO一起使用。我在网上找到了这个脚本并且工作正常,但是,当我将ATTR_EMULATE_PREPARES设置为false时,搜索功能不起作用并报告此错误。

我无法查看json响应,因为在发生此错误时无法查看,但是,在除了使用搜索之外的所有其他情况下,正确返回json并且它完全正常。由于错误只发生在仿真设置为false时,我认为这与绑定有关?我无法弄明白这一点,因为我没有看到任何错误的东西突然出现在我身上。

另外,我也不打算将仿真作为解决方案。非常感谢帮助。

获取萤火虫:

http://www.example.com/assets/data-tables/test-pdo.php?sEcho=3&iColumns=4&sColumns=&iDisplayStart=0&iDisplayLength=10&mDataProp_0=0&mDataProp_1=1&mDataProp_2=2&mDataProp_3=3&sSearch=d&bRegex=false&sSearch_0=&bRegex_0=false&bSearchable_0=true&sSearch_1=&bRegex_1=false&bSearchable_1=true&sSearch_2=&bRegex_2=false&bSearchable_2=true&sSearch_3=&bRegex_3=false&bSearchable_3=true&iSortCol_0=2&sSortDir_0=asc&iSortingCols=1&bSortable_0=false&bSortable_1=true&bSortable_2=true&bSortable_3=true&_=1388479579319

萤火虫错误:

<br />
<b>Fatal error</b>:  Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number' in /home/test/public_html/assets/data-tables/test-pdo.php:107
Stack trace:
#0 /home/test/public_html/assets/data-tables/test-pdo.php(107): PDOStatement-&gt;execute()
#1 /home/test/public_html/assets/data-tables/test-pdo.php(155): TableData-&gt;get('accounts', 'account_id', Array)
#2 {main}
  thrown in <b>/home/test/public_html/assets/data-tables/test-pdo.php</b> on line <b>107</b><br />

数据库连接:

$db = new PDO("mysql:host=$db_host;dbname=$db_database;charset=utf8", $db_user, $db_pass, array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_PERSISTENT => true));

处理:

<?php

/*
 * Script:    DataTables server-side script for PHP and MySQL
 * Copyright: 2012 - John Becker, Beckersoft, Inc.
 * Copyright: 2010 - Allan Jardine
 * License:   GPL v2 or BSD (3-point)
 */

define('INCLUDE_CHECK',true);

// These files can be included only if INCLUDE_CHECK is defined
require '/home/test/public_html/assets/functions/connect.php';

//inject db connection into class
class TableData {
    /** @var \PDO */
    protected $_db;

    public function __construct(\PDO $_db) {
         $this->_db = $_db;
    }

    public function get($table, $index_column, $columns) {

        // Paging
        $sLimit = "";
        if ( isset( $_GET['iDisplayStart'] ) && $_GET['iDisplayLength'] != '-1' ) {
            $sLimit = "LIMIT ".intval( $_GET['iDisplayStart'] ).", ".intval( $_GET['iDisplayLength'] );
        }

        // Ordering
        $sOrder = "";
        if ( isset( $_GET['iSortCol_0'] ) ) {
            $sOrder = "ORDER BY  ";
            for ( $i=0 ; $i<intval( $_GET['iSortingCols'] ) ; $i++ ) {
                if ( $_GET[ 'bSortable_'.intval($_GET['iSortCol_'.$i]) ] == "true" ) {
                    $sortDir = (strcasecmp($_GET['sSortDir_'.$i], 'ASC') == 0) ? 'ASC' : 'DESC';
                    $sOrder .= "`".$columns[ intval( $_GET['iSortCol_'.$i] ) ]."` ". $sortDir .", ";
                }
            }

            $sOrder = substr_replace( $sOrder, "", -2 );
            if ( $sOrder == "ORDER BY" ) {
                $sOrder = "";
            }
        }

        /* 
        * Filtering
        * NOTE this does not match the built-in DataTables filtering which does it
        * word by word on any field. It's possible to do here, but concerned about efficiency
        * on very large tables, and MySQL's regex functionality is very limited
        */
        //need this change to only show correct responses from db
        //$test = 100;
        //$sWhere = ""; OR $sWhere = "WHERE account_id < ".$test;

        $sWhere = "";
        if ( isset($_GET['sSearch']) && $_GET['sSearch'] != "" ) {

            // changes for correct display from db plus searching       
            if ($sWhere == ""){
                $sWhere = "WHERE (";
            }
            else {
                $sWhere .= " AND (";
            }

            //$sWhere = "WHERE (";
            for ( $i=0 ; $i<count($columns) ; $i++ ) {
                if ( isset($_GET['bSearchable_'.$i]) && $_GET['bSearchable_'.$i] == "true" ) {
                    $sWhere .= "`".$columns[$i]."` LIKE :search OR ";
                }
            }
            $sWhere = substr_replace( $sWhere, "", -3 );
            $sWhere .= ')';
        }

        // Individual column filtering
        for ( $i=0 ; $i<count($columns) ; $i++ ) {
            if ( isset($_GET['bSearchable_'.$i]) && $_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '' ) {
                if ( $sWhere == "" ) {
                    $sWhere = "WHERE ";
                }
                else {
                    $sWhere .= " AND ";
                }
                $sWhere .= "`".$columns[$i]."` LIKE :search".$i." ";
            }
        }

        // SQL queries get data to display
        $sQuery = "SELECT SQL_CALC_FOUND_ROWS `".str_replace(" , ", " ", implode("`, `", $columns))."` FROM `".$table."` ".$sWhere." ".$sOrder." ".$sLimit;
        $statement = $this->_db->prepare($sQuery);

        // Bind parameters
        if ( isset($_GET['sSearch']) && $_GET['sSearch'] != "" ) {
            $statement->bindValue(':search', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR);
        }
        for ( $i=0 ; $i<count($columns) ; $i++ ) {
            if ( isset($_GET['bSearchable_'.$i]) && $_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '' ) {
                $statement->bindValue(':search'.$i, '%'.$_GET['sSearch_'.$i].'%', PDO::PARAM_STR);
            }
        }

        $statement->execute();
        $rResult = $statement->fetchAll();

        $iFilteredTotal = current($this->_db->query('SELECT FOUND_ROWS()')->fetch());

        // Get total number of rows in table
        $sQuery = "SELECT COUNT(`".$index_column."`) FROM `".$table."`";
        //$sQuery = "SELECT COUNT(`".$index_column."`) FROM `".$table."` WHERE account_id < 100";
        $iTotal = current($this->_db->query($sQuery)->fetch());

        // Output
        $output = array(
            "sEcho" => intval($_GET['sEcho']),
            "iTotalRecords" => $iTotal,
            "iTotalDisplayRecords" => $iFilteredTotal,
            "aaData" => array()
        );

        // Return array of values
        foreach($rResult as $aRow) {
            $row = array();         
            for ( $i = 0; $i < count($columns); $i++ ) {

                //else if ( $aColumns[$i] != ' ' )
                if ( $columns[$i] != ' ' )
                {
                    /* General output */
                    //if column is empty give it n/a
                    $row[] = ($aRow[ $columns[$i] ]=="") ? 'n/a' : $aRow[ $columns[$i] ];
                }   

            }
            $output['aaData'][] = $row;
        }

        echo json_encode( $output );
    }

}

header('Pragma: no-cache');
header('Cache-Control: no-store, no-cache, must-revalidate');

// Create instance of TableData class
$table_data = new TableData($db);

// Get the data
//$table_data->get('table_name', 'index_column', array('column1', 'column2', 'columnN'));
$table_data->get('accounts', 'account_id', array('account_id', 'account_username', 'account_password', 'account_email'));

?>

1 个答案:

答案 0 :(得分:0)

我怀疑任何人都会感兴趣,但我终于明白了这一点。该脚本试图在语句中多次使用相同的绑定:search。

即使它始终是相同的实际值,也会抛出错误,因为它是相同的绑定。我以前怎么没看到这个我不知道,但现在对我来说很明显。

//$sWhere .= "`".$columns[$i]."` LIKE :search OR ";
$sWhere .= "`".$columns[$i]."` LIKE :searchm".$i." OR ";

// Bind parameters
//if ( isset($_GET['sSearch']) && $_GET['sSearch'] != "" ) {
//  $statement->bindValue(':search', '%'.$_GET['sSearch'].'%', PDO::PARAM_STR);
//}
if ( isset($_GET['sSearch']) && $_GET['sSearch'] != "" ) {
    for ( $i=0 ; $i<count($columns) ; $i++ ) {
        $statement->bindValue(':searchm'.$i, '%'.$_GET['sSearch'].'%', PDO::PARAM_STR);
    }
}