Php DataTables 1.10具有返回“null”值响应的表联接的服务器端
我正在尝试修改DataTables 1.10的默认服务器端脚本(最新版本,目前处于测试阶段),以允许表连接和自定义“WHERE”条件。“WHERE”条件工作得很好,就像我之前做的那样,但是,我在表联接方面遇到了一些问题。我在前面取得了一些进展,我不再收到firebug中的任何错误,但是每行的所有列都返回一个空值作为响应。换句话说,我的表格显示在页面上,每行都有空列 我尝试过datatables论坛,但没有得到太多的运气。为简单起见,我没有包括所有内容,但也包括了服务器端php处理脚本和ssp.class.php脚本 processing.php: ssp.class.php: 进一步信息-在下面显示的代码的这一点查看$数据将返回所有正确的值Php DataTables 1.10具有返回“null”值响应的表联接的服务器端,php,sql,pdo,jquery-datatables,Php,Sql,Pdo,Jquery Datatables,我正在尝试修改DataTables 1.10的默认服务器端脚本(最新版本,目前处于测试阶段),以允许表连接和自定义“WHERE”条件。“WHERE”条件工作得很好,就像我之前做的那样,但是,我在表联接方面遇到了一些问题。我在前面取得了一些进展,我不再收到firebug中的任何错误,但是每行的所有列都返回一个空值作为响应。换句话说,我的表格显示在页面上,每行都有空列 我尝试过datatables论坛,但没有得到太多的运气。为简单起见,我没有包括所有内容,但也包括了服务器端php处理脚本和ssp.c
$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
)
不完全确定这是否是正确的输出,但是,我相信这是因为您可以通过名称或索引引用datatables中的数据,这将解释此输出
编辑:
我把问题缩小了一点。静态函数数据_输出$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值。对ssp进行了一些更改,使其正常工作。已更改的包括选择x作为x,以确保获取正确的表列以及对数据输出函数的微小更改$数据现在已正确返回。有点黑,可以清理,但它在所有的测试,我已经做了迄今为止的作品
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;
}
}
看一看:emranulhadi提供了一个定制的SSP类,用于实现连接和附加条件,其中:
Github上提供:对于脚本中的记录,有一个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脚本文件中的错误 尝试转储整个查询并直接执行到mysql命令行,看看是否有任何错误。如果我理解正确,那就没有什么帮助了。我可以很容易地查询数据库与我想要的。。。这是一个修改此脚本以接受我所追求的表联接的问题。正在正确返回draw、recordsTotal和recordsFiltered。data=>SSP::data\u输出$primaryKey、$columns、$data似乎是问题所在,因为所有列都返回null。能否尝试在SSP::sql\u exec之后转储$data变量,
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;
}
}
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 );
}