【问题标题】:DataTables 1.10 serverside with table joins returning 'null' value responsesDataTables 1.10 服务器端,表连接返回“空”值响应
【发布时间】:2014-02-11 01:10:34
【问题描述】:

我正在尝试修改 DataTables 1.10(目前处于测试阶段的最新版本)的默认服务器端脚本,以允许表连接和自定义“WHERE”条件。 'WHERE' 条件可以正常工作,就像我之前所做的那样,但是,我在表连接方面遇到了一些问题。我早些时候取得了一些进展(我不再在 firebug 中收到任何错误),但是每行的所有列都返回一个空值作为响应。换句话说,我的表格显示在页面上,每一行都是空列。

我已经尝试过数据表论坛,但运气不佳。为简单起见,我没有包含所有内容,但也包含了服务器端 php 处理脚本和 ssp.class.php 脚本。

processing.php:

// DB table to use
$table = "`users`";

// Join condition
$myJoin = "LEFT JOIN `security` ON `users`.`user_id` = `security`.`user_id`";


// Table's primary key
$primaryKey = "`users`.`user_id`";

// Array of database columns which should be read and sent back to DataTables.
// The `db` parameter represents the column name in the database, while the `dt`
// parameter represents the DataTables column identifier. In this case simple
// indexes
$columns = array(
    array( 'db' => '`security`.`settings_id`', 'dt' => 'settings_id' ),
    array( 'db' => '`users`.`user_id`', 'dt' => 'user_id' ),
    array( 'db' => '`users`.`username`', 'dt' => 'username' ),
    array( 'db' => '`users`.`computer_name`', 'dt' => 'computer_name' ),
    array( 'db' => '`security`.`disable_desktop`', 'dt' => 'disable_desktop' ),
    array( 'db' => '`security`.`disable_start`', 'dt' => 'disable_start' ),
    array( 'db' => '`security`.`disable_shutdown`', 'dt' => 'disable_shutdown' ),
    array( 'db' => '`security`.`disable_run`', 'dt' => 'disable_run' ),
    array( 'db' => '`security`.`disable_mouse`', 'dt' => 'disable_mouse' ),
    array( 'db' => '`security`.`disable_bootkeys`', 'dt' => 'disable_bootkeys' ),
    array( 'db' => '`security`.`disable_cp`', 'dt' => 'disable_cp' ),
    array( 'db' => '`security`.`disable_network`', 'dt' => 'disable_network' ),
    array( 'db' => '`security`.`disable_taskbar`', 'dt' => 'disable_taskbar' ),
    array( 'db' => '`security`.`disable_clock`', 'dt' => 'disable_clock' ),
    array( 'db' => '`security`.`disable_logoff`', 'dt' => 'disable_logoff' ),
    array( 'db' => '`security`.`disable_startchange`', 'dt' => 'disable_startchange' ),
    array( 'db' => '`security`.`disable_taskman`', 'dt' => 'disable_taskman' ),
    array( 'db' => '`security`.`disable_clipboard`', 'dt' => 'disable_clipboard' ),
    array( 'db' => '`security`.`disable_drives`', 'dt' => 'disable_drives' )
);

echo json_encode(
    SSP::simple( $_GET, $db, $table, $primaryKey, $columns, $myJoin, "")
    //SSP::simple( $_GET, $db, $table, $primaryKey, $columns, $myJoin, $myWhere)
);

ssp.class.php:

class SSP {
    /**
     * Create the data output array for the DataTables rows
     *
     *  @param  array $columns Column information array
     *  @param  array $data    Data from the SQL get
     *  @return array          Formatted data in a row based format
     */
    static function data_output ( $primaryKey, $columns, $data )
    {
        $out = array();

        for ( $i=0, $ien=count($data) ; $i<$ien ; $i++ ) {
            $row = array();

            for ( $j=0, $jen=count($columns) ; $j<$jen ; $j++ ) {
                $column = $columns[$j];    
                // Is there a formatter?
                if ( isset( $column['formatter'] ) ) {
                    $row[ $column['dt'] ] = $column['formatter']( $data[$i][ $column['db'] ], $data[$i] );
                }
                else {
                    $row[ $column['dt'] ] = $data[$i][ $columns[$j]['db'] ];
                }

            }


            $out[] = $row;
        }

        return $out;
    }


    /**
     * Paging
     *
     * Construct the LIMIT clause for server-side processing SQL query
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array $columns Column information array
     *  @return string SQL limit clause
     */
    static function limit ( $request, $columns )
    {
        $limit = '';

        if ( isset($request['start']) && $request['length'] != -1 ) {
            $limit = "LIMIT ".intval($request['start']).", ".intval($request['length']);
        }

        return $limit;
    }


    /**
     * Ordering
     *
     * Construct the ORDER BY clause for server-side processing SQL query
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array $columns Column information array
     *  @return string SQL order by clause
     */
    static function order ( $request, $columns )
    {
        $order = '';

        if ( isset($request['order']) && count($request['order']) ) {
            $orderBy = array();
            $dtColumns = SSP::pluck( $columns, 'dt' );

            for ( $i=0, $ien=count($request['order']) ; $i<$ien ; $i++ ) {
                // Convert the column index into the column data property
                $columnIdx = intval($request['order'][$i]['column']);
                $requestColumn = $request['columns'][$columnIdx];

                $columnIdx = array_search( $requestColumn['data'], $dtColumns );
                $column = $columns[ $columnIdx ];

                if ( $requestColumn['orderable'] == true ) {
                    $dir = $request['order'][$i]['dir'] === 'asc' ?
                        'ASC' :
                        'DESC';

                    $orderBy[] = ''.$column['db'].' '.$dir;
                }
            }

            $order = 'ORDER BY '.implode(', ', $orderBy);
        }

        return $order;
    }


    /**
     * Searching / Filtering
     *
     * Construct the WHERE clause for server-side processing SQL query.
     *
     * 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 performance on large
     * databases would be very poor
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array $columns Column information array
     *  @param  array $bindings Array of values for PDO bindings, used in the
     *    sql_exec() function
     *  @return string SQL where clause
     EDIT : added $mywhere functionality for passing initial filtering conditions
     */
    static function filter ( $request, $columns, &$bindings, $myWhere )
    {
        $globalSearch = array();
        $columnSearch = array();
        $dtColumns = SSP::pluck( $columns, 'dt' );

        if ( isset($request['search']) && $request['search']['value'] != '' ) {
            $str = $request['search']['value'];

            for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
                $requestColumn = $request['columns'][$i];
                $columnIdx = array_search( $requestColumn['data'], $dtColumns );
                $column = $columns[ $columnIdx ];

                if ( $requestColumn['searchable'] == 'true' ) {
                    $binding = SSP::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
                    $globalSearch[] = "".$column['db']." LIKE ".$binding;
                }
            }
        }

        // Individual column filtering
        for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
            $requestColumn = $request['columns'][$i];
            $columnIdx = array_search( $requestColumn['data'], $dtColumns );
            $column = $columns[ $columnIdx ];

            $str = $requestColumn['search']['value'];

            if ( $requestColumn['searchable'] == 'true' &&
             $str != '' ) {
                $binding = SSP::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
                $columnSearch[] = "".$column['db']." LIKE ".$binding;
            }
        }

        // Combine the filters into a single string
        $where = '';

        if ( count( $globalSearch ) ) {
            $where = '('.implode(' OR ', $globalSearch).')';
        }

        if ( count( $columnSearch ) ) {
            $where = $where === '' ?
                implode(' AND ', $globalSearch) :
                $where .' AND '. implode(' AND ', $globalSearch);
        }

        if ( $where !== '' ) {
            $where = 'WHERE '.$where;

            // add my clause
            if ($myWhere !== '') {
                $where .= ' AND '.$myWhere;
            }
        }

        if ( $where == '' && $myWhere !== '') {
            // add my clause
            $where = 'WHERE '.$myWhere;
        }       

        return $where;
    }


    /**
     * Perform the SQL queries needed for an server-side processing requested,
     * utilising the helper functions of this class, limit(), order() and
     * filter() among others. The returned array is ready to be encoded as JSON
     * in response to an SSP request, or can be modified if needed before
     * sending back to the client.
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array $sql_details SQL connection details - see sql_connect()
     *  @param  string $table SQL table to query
     *  @param  string $primaryKey Primary key of the table
     *  @param  array $columns Column information array
     *  @return array          Server-side processing response array
     */
    static function simple ( $request, $db, $table, $primaryKey, $columns, $myJoin, $myWhere )
    {
        $bindings = array();
        //$db = SSP::sql_connect( $sql_details );

        // Build the SQL query string from the request
        $limit = SSP::limit( $request, $columns );
        $order = SSP::order( $request, $columns );
        $where = SSP::filter( $request, $columns, $bindings, $myWhere );    

        // Main query to actually get the data
        $data = SSP::sql_exec( $db, $bindings,
            "SELECT SQL_CALC_FOUND_ROWS ".implode(", ", SSP::pluck($columns, 'db'))."
             FROM $table
             $myJoin
             $where
             $order
             $limit"
        );

        // Data set length after filtering
        $resFilterLength = SSP::sql_exec( $db,
            "SELECT FOUND_ROWS()"
        );
        $recordsFiltered = $resFilterLength[0][0];  

        //add my initial where clause for correct results
        $dataWhere = ($myWhere !== '' ? 'WHERE '.$myWhere : '');

        // Total data set length        
        $resTotalLength = SSP::sql_exec( $db,
            "SELECT COUNT({$primaryKey})
             FROM $table
             $myJoin
             $dataWhere"
        );
        $recordsTotal = $resTotalLength[0][0];


        /*
         * Output
         */          
        return array(
            "draw"            => intval( $request['draw'] ),
            "recordsTotal"    => intval( $recordsTotal ),
            "recordsFiltered" => intval( $recordsFiltered ),
            "data"            => SSP::data_output( $primaryKey, $columns, $data )
        );
    }

    /**
     * Execute an SQL query on the database
     *
     * @param  resource $db  Database handler
     * @param  array    $bindings Array of PDO binding values from bind() to be
     *   used for safely escaping strings. Note that this can be given as the
     *   SQL query string if no bindings are required.
     * @param  string   $sql SQL query to execute.
     * @return array         Result from the query (all rows)
     */
    static function sql_exec ( $db, $bindings, $sql=null )
    {
        // Argument shifting
        if ( $sql === null ) {
            $sql = $bindings;
        }

        $stmt = $db->prepare( $sql );
        //echo $sql;

        // Bind parameters
        if ( is_array( $bindings ) ) {
            for ( $i=0, $ien=count($bindings) ; $i<$ien ; $i++ ) {
                $binding = $bindings[$i];
                $stmt->bindValue( $binding['key'], $binding['val'], $binding['type'] );
            }
        }

        // Execute
        try {
            $stmt->execute();
        }
        catch (PDOException $e) {
            SSP::fatal( "An SQL error occurred: ".$e->getMessage() );
        }

        // Return all
        return $stmt->fetchAll();
    }


    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Internal methods
     */

    /**
     * Throw a fatal error.
     *
     * This writes out an error message in a JSON string which DataTables will
     * see and show to the user in the browser.
     *
     * @param  string $msg Message to send to the client
     */
    static function fatal ( $msg )
    {
        echo json_encode( array( 
            "error" => $msg
        ) );

        exit(0);
    }

    /**
     * Create a PDO binding key which can be used for escaping variables safely
     * when executing a query with sql_exec()
     *
     * @param  array &$a    Array of bindings
     * @param  *      $val  Value to bind
     * @param  int    $type PDO field type
     * @return string       Bound key to be used in the SQL where this parameter
     *   would be used.
     */
    static function bind ( &$a, $val, $type )
    {
        $key = ':binding_'.count( $a );

        $a[] = array(
            'key' => $key,
            'val' => $val,
            'type' => $type
        );

        return $key;
    }


    /**
     * Pull a particular property from each assoc. array in a numeric array, 
     * returning and array of the property values from each item.
     *
     *  @param  array  $a    Array to get data from
     *  @param  string $prop Property to read
     *  @return array        Array of property values
     */
    static function pluck ( $a, $prop )
    {
        $out = array();

        for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) {
            $out[] = $a[$i][$prop];
        }

        return $out;
    }
}

编辑:

这是SSP::data_output( $primaryKey, $columns, $data ) 的结果。我不得不将其打印到文件中,因为我无法在屏幕上打印/显示。结果很明显,代码的数据部分出现了问题,因为它没有返回任何内容,但是,它返回了正确数量的结果(在本例中为 5)。请注意,命名是不同的,因为这些是返回给 DataTables 的名称,而不是实际的 db 列名,但是,这可能与它有关。

Array
(
    [0] => Array
        (
            [settings_id] => 
            [user_id] => 
            [username] => 
            [computer_name] => 
            [disable_desktop] => 
            [disable_start] => 
            [disable_shutdown] => 
            [disable_run] => 
            [disable_mouse] => 
            [disable_bootkeys] => 
            [disable_cp] => 
            [disable_network] => 
            [disable_taskbar] => 
            [disable_clock] => 
            [disable_logoff] => 
            [disable_startchange] => 
            [disable_taskman] => 
            [disable_clipboard] => 
            [disable_drives] => 
            [DT_RowId] => 
        )

    [1] => Array
        (
            [settings_id] => 
            [user_id] => 
            [username] => 
            [computer_name] => 
            [disable_desktop] => 
            [disable_start] => 
            [disable_shutdown] => 
            [disable_run] => 
            [disable_mouse] => 
            [disable_bootkeys] => 
            [disable_cp] => 
            [disable_network] => 
            [disable_taskbar] => 
            [disable_clock] => 
            [disable_logoff] => 
            [disable_startchange] => 
            [disable_taskman] => 
            [disable_clipboard] => 
            [disable_drives] => 
            [DT_RowId] => 
        )

    [2] => Array
        (
            [settings_id] => 
            [user_id] => 
            [username] => 
            [computer_name] => 
            [disable_desktop] => 
            [disable_start] => 
            [disable_shutdown] => 
            [disable_run] => 
            [disable_mouse] => 
            [disable_bootkeys] => 
            [disable_cp] => 
            [disable_network] => 
            [disable_taskbar] => 
            [disable_clock] => 
            [disable_logoff] => 
            [disable_startchange] => 
            [disable_taskman] => 
            [disable_clipboard] => 
            [disable_drives] => 
            [DT_RowId] => 
        )

    [3] => Array
        (
            [settings_id] => 
            [user_id] => 
            [username] => 
            [computer_name] => 
            [disable_desktop] => 
            [disable_start] => 
            [disable_shutdown] => 
            [disable_run] => 
            [disable_mouse] => 
            [disable_bootkeys] => 
            [disable_cp] => 
            [disable_network] => 
            [disable_taskbar] => 
            [disable_clock] => 
            [disable_logoff] => 
            [disable_startchange] => 
            [disable_taskman] => 
            [disable_clipboard] => 
            [disable_drives] => 
            [DT_RowId] => 
        )

    [4] => Array
        (
            [settings_id] => 
            [user_id] => 
            [username] => 
            [computer_name] => 
            [disable_desktop] => 
            [disable_start] => 
            [disable_shutdown] => 
            [disable_run] => 
            [disable_mouse] => 
            [disable_bootkeys] => 
            [disable_cp] => 
            [disable_network] => 
            [disable_taskbar] => 
            [disable_clock] => 
            [disable_logoff] => 
            [disable_startchange] => 
            [disable_taskman] => 
            [disable_clipboard] => 
            [disable_drives] => 
            [DT_RowId] => 
        )

)

更多信息 - 在下面显示的代码的此时查看 $data 会返回所有正确的值。

$data = SSP::sql_exec( $db, $bindings,
    "SELECT SQL_CALC_FOUND_ROWS ".implode(", ", SSP::pluck($columns, 'db'))."
     FROM $table
     $myJoin
     $where
     $order
     $limit"
);

这是返回数组的一部分(一行),上面有正确的值:

[3] => Array
    (
        [settings_id] => 1
        [0] => 1
        [user_id] => 11
        [1] => 11
        [username] => steve
        [2] => steve
        [computer_name] => TESTING
        [3] => TESTING
        [disable_desktop] => 1
        [4] => 1
        [disable_start] => 0
        [5] => 0
        [disable_shutdown] => 0
        [6] => 0
        [disable_run] => 0
        [7] => 0
        [disable_mouse] => 0
        [8] => 0
        [disable_bootkeys] => 0
        [9] => 0
        [disable_cp] => 0
        [10] => 0
        [disable_network] => 0
        [11] => 0
        [disable_taskbar] => 0
        [12] => 0
        [disable_clock] => 0
        [13] => 0
        [disable_logoff] => 0
        [14] => 0
        [disable_startchange] => 0
        [15] => 0
        [disable_taskman] => 0
        [16] => 0
        [disable_clipboard] => 0
        [17] => 0
        [disable_drives] => 0
        [18] => 0
    )

不完全确定这是否是正确的输出,但是,我相信您可以通过名称或索引引用数据表中的数据来解释此输出。

编辑:

我进一步缩小了问题的范围。静态函数 data_output ( $primaryKey, $columns, $data ) 是预期的问题的一部分。 $primaryKey 和 $columns 具有正确的值,但是 $data 没有。

在函数中,当您到达实际设置值的部分时,数组中没有要设置的值。

$row[ $column['dt'] ] = $data[$i][ $columns[$j]['db'] ];

这里$row[ $column['dt'] ] 是正确的,但是$data[$i][ $columns[$j]['db'] ]; 没有db 值。正如您在上面 $data 的示例输出中看到的那样,不存在 db 值,而是将 dt 值与索引一起作为相同的值。通过将其更改为 dt 我的表显示数据,但是,这会破坏其他一些东西。我不确定为什么 $data 没有包含应有的 db 值。

【问题讨论】:

  • 尝试转储整个查询并尝试将它们直接执行到mysql命令行,看看是否有任何错误。
  • 如果我理解正确,那将无济于事。我可以很容易地用我想要的查询数据库......这是一个修改这个脚本以接受我所追求的表连接的问题。 draw、recordsTotal 和 recordsFiltered 正在正确返回。 "data" =&gt; SSP::data_output( $primaryKey, $columns, $data ) 似乎是所有列都返回 null 的问题。
  • 你能在 SSP::sql_exec(, 之后尝试转储 $data 变量吗?

标签: php sql pdo jquery-datatables


【解决方案1】:

通过对 ssp 的一些更改让它工作。更改了包括 select x AS x 以确保获取正确的表列以及对 data_output 函数的微小更改。 $data 现在可以正确返回。有点hacky,可以清理,但它适用于我迄今为止所做的所有测试。

class SSP {
    /**
     * Create the data output array for the DataTables rows
     *
     *  @param  array $columns Column information array
     *  @param  array $data    Data from the SQL get
     *  @return array          Formatted data in a row based format
     */
    static function data_output ( $columns, $data )
    {
        //show $data values in file since it cannot be echo'ed out
        //file_put_contents('/home/test/public_html/filename.txt', print_r($data, true));

        $out = array();

        for ( $i=0, $ien=count($data) ; $i<$ien ; $i++ ) {
            $row = array();

            for ( $j=0, $jen=count($columns) ; $j<$jen ; $j++ ) {
                $column = $columns[$j];

                // Is there a formatter?
                if ( isset( $column['formatter'] ) ) {
                    $row[ $column['dt'] ] = $column['formatter']( $data[$i][ $column['dt'] ], $data[$i] );
                }
                else {
                    $row[ $column['dt'] ] = $data[$i][ $columns[$j]['dt'] ];
                }

            }

            $out[] = $row;
        }

        return $out;
    }


    /**
     * Paging
     *
     * Construct the LIMIT clause for server-side processing SQL query
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array $columns Column information array
     *  @return string SQL limit clause
     */
    static function limit ( $request, $columns )
    {
        $limit = '';

        if ( isset($request['start']) && $request['length'] != -1 ) {
            $limit = "LIMIT ".intval($request['start']).", ".intval($request['length']);
        }

        return $limit;
    }


    /**
     * Ordering
     *
     * Construct the ORDER BY clause for server-side processing SQL query
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array $columns Column information array
     *  @return string SQL order by clause
     */
    static function order ( $request, $columns )
    {
        $order = '';

        if ( isset($request['order']) && count($request['order']) ) {
            $orderBy = array();
            $dtColumns = SSP::pluck( $columns, 'dt' );

            for ( $i=0, $ien=count($request['order']) ; $i<$ien ; $i++ ) {
                // Convert the column index into the column data property
                $columnIdx = intval($request['order'][$i]['column']);
                $requestColumn = $request['columns'][$columnIdx];

                $columnIdx = array_search( $requestColumn['data'], $dtColumns );
                $column = $columns[ $columnIdx ];

                if ( $requestColumn['orderable'] == true ) {
                    $dir = $request['order'][$i]['dir'] === 'asc' ?
                        'ASC' :
                        'DESC';

                    $orderBy[] = ''.$column['db'].' '.$dir;
                }
            }

            $order = 'ORDER BY '.implode(', ', $orderBy);
        }

        return $order;
    }


    /**
     * Searching / Filtering
     *
     * Construct the WHERE clause for server-side processing SQL query.
     *
     * 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 performance on large
     * databases would be very poor
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array $columns Column information array
     *  @param  array $bindings Array of values for PDO bindings, used in the
     *    sql_exec() function
     *  @return string SQL where clause
     EDIT : added $mywhere functionality for passing initial filtering conditions
     */
    static function filter ( $request, $columns, &$bindings, $myWhere )
    {
        $globalSearch = array();
        $columnSearch = array();
        $dtColumns = SSP::pluck( $columns, 'dt' );

        if ( isset($request['search']) && $request['search']['value'] != '' ) {
            $str = $request['search']['value'];

            for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
                $requestColumn = $request['columns'][$i];
                $columnIdx = array_search( $requestColumn['data'], $dtColumns );
                $column = $columns[ $columnIdx ];

                if ( $requestColumn['searchable'] == 'true' ) {
                    $binding = SSP::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
                    $globalSearch[] = "".$column['db']." LIKE ".$binding;
                }
            }
        }

        // Individual column filtering
        for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
            $requestColumn = $request['columns'][$i];
            $columnIdx = array_search( $requestColumn['data'], $dtColumns );
            $column = $columns[ $columnIdx ];

            $str = $requestColumn['search']['value'];

            if ( $requestColumn['searchable'] == 'true' &&
             $str != '' ) {
                $binding = SSP::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
                $columnSearch[] = "".$column['db']." LIKE ".$binding;
            }
        }

        // Combine the filters into a single string
        $where = '';

        if ( count( $globalSearch ) ) {
            $where = '('.implode(' OR ', $globalSearch).')';
        }

        if ( count( $columnSearch ) ) {
            $where = $where === '' ?
                implode(' AND ', $globalSearch) :
                $where .' AND '. implode(' AND ', $globalSearch);
        }

        if ( $where !== '' ) {
            $where = 'WHERE '.$where;

            // add my clause
            if ($myWhere !== '') {
                $where .= ' AND '.$myWhere;
            }
        }

        if ( $where == '' && $myWhere !== '') {
            // add my clause
            $where = 'WHERE '.$myWhere;
        }       

        return $where;
    }


    /**
     * Perform the SQL queries needed for an server-side processing requested,
     * utilising the helper functions of this class, limit(), order() and
     * filter() among others. The returned array is ready to be encoded as JSON
     * in response to an SSP request, or can be modified if needed before
     * sending back to the client.
     *
     *  @param  array $request Data sent to server by DataTables
     *  @param  array $sql_details SQL connection details - see sql_connect()
     *  @param  string $table SQL table to query
     *  @param  string $primaryKey Primary key of the table
     *  @param  array $columns Column information array
     *  @return array          Server-side processing response array
     */
    static function simple ( $request, $db, $table, $primaryKey, $columns, $myJoin, $myWhere )
    {
        $bindings = array();
        //$db = SSP::sql_connect( $sql_details );

        // Build the SQL query string from the request
        $limit = SSP::limit( $request, $columns );
        $order = SSP::order( $request, $columns );
        $where = SSP::filter( $request, $columns, $bindings, $myWhere );    

        // Main query to actually get the data
        $data = SSP::sql_exec( $db, $bindings,
            //"SELECT SQL_CALC_FOUND_ROWS ".implode(", ", SSP::pluck($columns, 'db'))."
            "SELECT SQL_CALC_FOUND_ROWS ".implode(", ", SSP::pluckAs($columns))."
             FROM $table
             $myJoin
             $where
             $order
             $limit"
        );

        // Data set length after filtering
        $resFilterLength = SSP::sql_exec( $db,
            "SELECT FOUND_ROWS()"
        );
        $recordsFiltered = $resFilterLength[0][0];  

        //add my initial where clause for correct results
        $dataWhere = ($myWhere !== '' ? 'WHERE '.$myWhere : '');

        // Total data set length        
        $resTotalLength = SSP::sql_exec( $db,
            "SELECT COUNT({$primaryKey})
             FROM $table
             $myJoin
             $dataWhere"
        );
        $recordsTotal = $resTotalLength[0][0];      

        /*
         * Output
         */          
        return array(
            "draw"            => intval( $request['draw'] ),
            "recordsTotal"    => intval( $recordsTotal ),
            "recordsFiltered" => intval( $recordsFiltered ),
            "data"            => SSP::data_output( $columns, $data )
        );

    }

    /**
     * Execute an SQL query on the database
     *
     * @param  resource $db  Database handler
     * @param  array    $bindings Array of PDO binding values from bind() to be
     *   used for safely escaping strings. Note that this can be given as the
     *   SQL query string if no bindings are required.
     * @param  string   $sql SQL query to execute.
     * @return array         Result from the query (all rows)
     */
    static function sql_exec ( $db, $bindings, $sql=null )
    {
        // Argument shifting
        if ( $sql === null ) {
            $sql = $bindings;
        }

        $stmt = $db->prepare( $sql );
        //echo $sql;

        // Bind parameters
        if ( is_array( $bindings ) ) {
            for ( $i=0, $ien=count($bindings) ; $i<$ien ; $i++ ) {
                $binding = $bindings[$i];
                $stmt->bindValue( $binding['key'], $binding['val'], $binding['type'] );
            }
        }

        // Execute
        try {
            $stmt->execute();
        }
        catch (PDOException $e) {
            SSP::fatal( "An SQL error occurred: ".$e->getMessage() );
        }

        // Return all
        return $stmt->fetchAll();
    }


    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * Internal methods
     */

    /**
     * Throw a fatal error.
     *
     * This writes out an error message in a JSON string which DataTables will
     * see and show to the user in the browser.
     *
     * @param  string $msg Message to send to the client
     */
    static function fatal ( $msg )
    {
        echo json_encode( array( 
            "error" => $msg
        ) );

        exit(0);
    }

    /**
     * Create a PDO binding key which can be used for escaping variables safely
     * when executing a query with sql_exec()
     *
     * @param  array &$a    Array of bindings
     * @param  *      $val  Value to bind
     * @param  int    $type PDO field type
     * @return string       Bound key to be used in the SQL where this parameter
     *   would be used.
     */
    static function bind ( &$a, $val, $type )
    {
        $key = ':binding_'.count( $a );

        $a[] = array(
            'key' => $key,
            'val' => $val,
            'type' => $type
        );

        return $key;
    }


    /**
     * Pull a particular property from each assoc. array in a numeric array, 
     * returning and array of the property values from each item.
     *
     *  @param  array  $a    Array to get data from
     *  @param  string $prop Property to read
     *  @return array        Array of property values
     */
    static function pluck ( $a, $prop )
    {
        $out = array();

        for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) {
            $out[] = $a[$i][$prop];
        }

        return $out;
    }

    /**
     * Create and return select array in the format `db` AS `dt` 
     * returning and array of the property values from each item.
     *
     *  @param  array  $a    Array to get data from
     *  @return array        Array of property values
     */
    static function pluckAs ( $a )
    {
        $out = array();

        for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) {
            $out[] = $a[$i]['db']." AS `".$a[$i]['dt']."`";
        }

        return $out;
    }

}

【讨论】:

    【解决方案2】:

    看看:emranulhadi 提供了一个定制的 SSP 类,实现了 JOIN 和额外条件(WHERE):

    https://emranulhadi.wordpress.com/2014/06/05/join-and-extra-condition-support-at-datatables-library-ssp-class/

    在 Github 上可用:https://github.com/emran/ssp

    【讨论】:

      【解决方案3】:

      对于脚本中的记录有一个bug,下一行:

          if ( count( $columnSearch ) ) {
              $where = $where === '' ?
                  implode(' AND ', $globalSearch) :
                  $where .' AND '. implode(' AND ', $globalSearch);
          }
      

      必须

          if ( count( $columnSearch ) ) {
              $where = $where === '' ?
                  implode(' AND ', $columnSearch ) :
                  $where .' AND '. implode(' AND ', $columnSearch );
          }
      

      我已经搜索了好几天,但这是 php 脚本文件中的错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-01
        • 1970-01-01
        • 2018-03-01
        • 1970-01-01
        • 2019-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多