Datatables + PHP:多表的服务器端处理
Datatables + PHP: Server-Side Processing on Multiple Tables
如何获取数据tables 服务器端处理 脚本来处理自定义查询?我需要来自多个 table 的 select 列,并让 Datatable 呈现它们。
Datatables.net 与 PHP 的服务器端处理 (SSP) 总结如下:https://datatables.net/examples/server_side/simple.html
我找到了这个 SO question,但是原来的 poster 从来没有提供他的解决方案。我没有足够的声誉要求他提供更多细节。
这是我的原始 SQL,没有使用 Datatable 的 SSP
SELECT tbl_houses.style, tbl_houses.roomCount, tbl_residents.firstName, tbl_residents.lastName
FROM tbl_houses, tbl_residents
WHERE tbl_houses.houseID = tbl_residents.residentID
/*
* # Equivalent query using JOIN suggested by @KumarRakesh
* # Note: JOIN ... ON is a synonym for INNER JOIN ... ON
* # Using JOIN conforms to syntax spec'd by ANSI-92
*
* SELECT tbl_houses.style, tbl_houses.roomCount, tbl_residents.firstName, tbl_residents.lastName
* FROM tbl_houses
* JOIN tbl_residents ON tbl_houses.houseID = tbl_residents.residentID
*/
如何使用 SSP 获取数据table 到 运行 查询?
看来 server_processing.php 只接受 1 个 table 并且没有自定义过滤(即 WHERE
子句)。
// DB table to use
$table = 'datatables_demo';
// Table's primary key
$primaryKey = 'id';
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* If you just want to use the basic configuration for DataTables with PHP
* server-side, there is no need to edit below this line.
*/
require( 'ssp.class.php' );
echo json_encode(
SSP::simple( $_GET, $sql_details, $table, $primaryKey, $columns )
);
但是,ssp.class.php 支持使用 WHERE
进行过滤。我在想我需要修改 ssp.class.php
以强制加入我的 WHERE
子句
更新
找到解决办法。有空的时候会post
看起来 DataTables 中的脚本确实不是为您的特定用例设计的。但是有一种方法允许自定义 where 子句并阅读 ssp.class.php#complex 的源代码我认为这种配置应该适用于您使用 WHERE
方法。 JOIN
方法在这里不起作用。
长话短说:将您的 server_processing.php 编辑为:
<?php
// DB table to use
$table = 'tbl_houses, tbl_residents';
// First table's primary key
$primaryKey = 'tbl_houses.id';
$columns = [
[ 'db' => 'tbl_houses.style'],
[ 'db' => 'bl_houses.roomCount'],
[ 'db' => 'tbl_residents.firstName'],
[ 'db' => 'tbl_residents.lastName']
);
// connection details
$sql_details = [
];
$whereAll = 'tbl_houses.houseID = tbl_residents.residentID';
require( 'ssp.class.php' );
echo json_encode(
SSP::complex( $_GET, $sql_details, $table, $primaryKey, $columns , null, $whereAll);
);
complex
方法接受您的自定义 WHERE
子句。但棘手的是使用 2 个表。这似乎不是脚本设计的目的。我看了一下它是如何构建最终的 sql 查询的,看来您可以在配置中使用这个 table_name.field_name
表示法,以及 [=] 的 table_name, table_name
表示法17=] 和 $primaryKey
变量。
如前所述,DataTables 脚本不打算使用 2 个表。我不知道 DataTables 的所有功能是否都适用。
TL;DR: 我最终使用了对原始数据表 ssp.class.php
的修改,称为 ssp.php
implemented by Emran Ul Hadi: https://github.com/emran/ssp
他的修改接受 JOIN、WHERE、GROUP BY 和列别名。虽然该文件已经一年多没有更新,但它仍然适用于 DataTables 1.12.x。我对他的版本做了一些修改,增加了它的健壮性,并用更清晰的例子改进了文档。
我的 mods/updates post 有空的时候可以过来吗?最终我希望提出一个拉取请求,将我的更新放入他的存储库中。
解决方案
Class ssp.class.php
不支持连接和子查询,但有一个解决方法。诀窍是使用子查询,如下面的 $table
定义所示。将 table
替换为您在子查询中的实际 table 名称。
$table = <<<EOT
(
SELECT
a.id,
a.name,
a.father_id,
b.name AS father_name
FROM table a
LEFT JOIN table b ON a.father_id = b.id
) temp
EOT;
$primaryKey = 'id';
$columns = array(
array( 'db' => 'id', 'dt' => 0 ),
array( 'db' => 'name', 'dt' => 1 ),
array( 'db' => 'father_id', 'dt' => 2 ),
array( 'db' => 'father_name', 'dt' => 3 )
);
$sql_details = array(
'user' => '',
'pass' => '',
'db' => '',
'host' => ''
);
require( 'ssp.class.php' );
echo json_encode(
SSP::simple( $_GET, $sql_details, $table, $primaryKey, $columns )
);
您还需要编辑 ssp.class.php
并将 FROM `$table`
的所有实例替换为 FROM $table
以删除反引号。
确保所有列名都是唯一的,否则使用 AS
分配别名。
注意事项
还有 github.com/emran/ssp 存储库,其中包含增强的 ssp.class.php
支持 JOIN。
链接
有关详细信息,请参阅 jQuery DataTables: Using WHERE, JOIN and GROUP BY with ssp.class.php。
我对原始 Datatables 的分支 ssp.class.php:https://github.com/emayskiy/Datatables-SSP-MultiTables
您可以为表和列添加别名,使用 where,对表使用 [LEFT, INNER, RIGHT, CROSS] JOIN。
示例 server_processing.php:
<?php
//For one table:
//$table = "main_table_name";
//Or for multitable queries:
$table = array(
array('table'=>'main_table_name', 'as'=>'mt'),
array('table'=>'join1_table_name', 'as'=>'jt1', 'join_type'=>'INNER', 'join_on'=>'mt.field = jt1.field'),
array('table'=>'join2_table_name', 'as'=>'jt2', 'join_type'=>'LEFT', 'join_on'=>'mt.field1 = jt2.field')
);
//Columns definition with alias
$columns = array(
array( 'db' => 'mt.field1', 'dt' => 0 ),
array( 'db' => 'mt.field2', 'dt' => 1 ),
array( 'db' => 'mt.name', 'as'=>'field3', 'dt' => 2 ),
array( 'db' => 'jt1.field1', 'as'=>'field4', 'dt' => 3 ),
array( 'db' => 'jt2.field5', 'as'=>'field5', 'dt' => 4 )
);
$primaryKey = 'mt.id'; //Primary key, for check records count
$sql_details = array(
'user' => $db_user,
'pass' => $db_password,
'db' => $db_name,
'host' => $db_host
);
$where = "mt.field1 > 10"; //You SQL where condition
require('ssp.class.php' ); //File from github.com/emayskiy/Datatables-SSP-MultiTables
echo json_encode(
// All params same as in original class SSP
SSP::complex( $_GET, $sql_details, $table, $primaryKey, $columns , '', $where)
);
?>
抱歉来晚了,但我能够通过构建自己的服务器端文件来解决问题,这样我就可以自定义查询和 json 输出。
文件服务器端自定义:
public function produtosEstoque($arr)
{
//COLUNAS
$column = array('prodNome', 'prodPreco', 'prodQtdEst', 'categDescricao');
//SQL
$query2 = "SELECT a.prodID, a.prodNome, a.prodMedida, a.prodPrecoAnt, a.prodPreco, a.prodCategoriaID, a.prodOferta,a.prodQtdEst, a.prodQtdMEst, b.categDescricao FROM produtos a INNER JOIN categoria b ON a.prodCategoriaID = b.categID WHERE a.prodEstatusID = 6 ";
//SEARCH
if ($arr['search']['value']) {
$query2 .= "AND prodNome LIKE '%".$arr['search']['value']."%' ";
}
//ORDER
if (isset($arr['order'])) {
$query2 .= 'ORDER BY ' . $column[$arr['order']['0']['column']] . ' ' . $arr['order']['0']['dir'] . ' ';
} else {
$query2 .= 'ORDER BY a.prodID DESC ';
}
//LIMIT
if ($arr["length"] != -1) {
$query3 = 'LIMIT ' . $arr['start'] . ', ' . $arr['length'];
}
try {
//TOTAL DE REGISTROS NA TABELA
$query1 = "SELECT * FROM produtos WHERE prodEstatusID = 6";
$stm1 = $this->pdo->prepare($query1);
$stm1->execute();
$contReg = $stm1->rowCount($stm1);
$stm = $this->pdo->prepare($query2);
$stm->execute();
$number_filter_row = $stm->rowCount($stm);
$stm = $this->pdo->prepare($query2 . $query3);
$stm->execute();
$list = $stm->fetchAll(PDO::FETCH_OBJ);
$data = [];
foreach ($list as $row) {
$data[] = array('prod_nome' => $row->prodNome . ", " . $row->prodMedida, 'prod_preco' => "R$ ".$this->convInReal($row->prodPreco)." ".$this->formatProdOff($row->prodOferta), 'prod_estoque' => $row->prodQtdEst . " - M: " . $row->prodQtdMEst, 'prod_categoria' => $row->categDescricao);
}
$dat = array('draw' => intval($arr["draw"]),
'recordsTotal' => $contReg,
'recordsFiltered' => $number_filter_row,
'data' => $data
);
return json_encode($dat, JSON_UNESCAPED_UNICODE);
} catch (PDOException $erro) {
$data = array('msgEr' => 'ERR_002_EI', 'erroLine' => $erro->getLine());
return json_encode($data);
}
}
我通过在 mysql phpmyadmin 中创建视图 table 解决了这个问题。
运行 您在 phpmyadmin 中的 sql 脚本,然后单击 创建视图
enter image description here
如何获取数据tables 服务器端处理 脚本来处理自定义查询?我需要来自多个 table 的 select 列,并让 Datatable 呈现它们。
Datatables.net 与 PHP 的服务器端处理 (SSP) 总结如下:https://datatables.net/examples/server_side/simple.html
我找到了这个 SO question,但是原来的 poster 从来没有提供他的解决方案。我没有足够的声誉要求他提供更多细节。
这是我的原始 SQL,没有使用 Datatable 的 SSP
SELECT tbl_houses.style, tbl_houses.roomCount, tbl_residents.firstName, tbl_residents.lastName
FROM tbl_houses, tbl_residents
WHERE tbl_houses.houseID = tbl_residents.residentID
/*
* # Equivalent query using JOIN suggested by @KumarRakesh
* # Note: JOIN ... ON is a synonym for INNER JOIN ... ON
* # Using JOIN conforms to syntax spec'd by ANSI-92
*
* SELECT tbl_houses.style, tbl_houses.roomCount, tbl_residents.firstName, tbl_residents.lastName
* FROM tbl_houses
* JOIN tbl_residents ON tbl_houses.houseID = tbl_residents.residentID
*/
如何使用 SSP 获取数据table 到 运行 查询?
看来 server_processing.php 只接受 1 个 table 并且没有自定义过滤(即 WHERE
子句)。
// DB table to use
$table = 'datatables_demo';
// Table's primary key
$primaryKey = 'id';
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* If you just want to use the basic configuration for DataTables with PHP
* server-side, there is no need to edit below this line.
*/
require( 'ssp.class.php' );
echo json_encode(
SSP::simple( $_GET, $sql_details, $table, $primaryKey, $columns )
);
但是,ssp.class.php 支持使用 WHERE
进行过滤。我在想我需要修改 ssp.class.php
以强制加入我的 WHERE
子句
更新
找到解决办法。有空的时候会post
看起来 DataTables 中的脚本确实不是为您的特定用例设计的。但是有一种方法允许自定义 where 子句并阅读 ssp.class.php#complex 的源代码我认为这种配置应该适用于您使用 WHERE
方法。 JOIN
方法在这里不起作用。
长话短说:将您的 server_processing.php 编辑为:
<?php
// DB table to use
$table = 'tbl_houses, tbl_residents';
// First table's primary key
$primaryKey = 'tbl_houses.id';
$columns = [
[ 'db' => 'tbl_houses.style'],
[ 'db' => 'bl_houses.roomCount'],
[ 'db' => 'tbl_residents.firstName'],
[ 'db' => 'tbl_residents.lastName']
);
// connection details
$sql_details = [
];
$whereAll = 'tbl_houses.houseID = tbl_residents.residentID';
require( 'ssp.class.php' );
echo json_encode(
SSP::complex( $_GET, $sql_details, $table, $primaryKey, $columns , null, $whereAll);
);
complex
方法接受您的自定义 WHERE
子句。但棘手的是使用 2 个表。这似乎不是脚本设计的目的。我看了一下它是如何构建最终的 sql 查询的,看来您可以在配置中使用这个 table_name.field_name
表示法,以及 [=] 的 table_name, table_name
表示法17=] 和 $primaryKey
变量。
如前所述,DataTables 脚本不打算使用 2 个表。我不知道 DataTables 的所有功能是否都适用。
TL;DR: 我最终使用了对原始数据表 ssp.class.php
的修改,称为 ssp.php
implemented by Emran Ul Hadi: https://github.com/emran/ssp
他的修改接受 JOIN、WHERE、GROUP BY 和列别名。虽然该文件已经一年多没有更新,但它仍然适用于 DataTables 1.12.x。我对他的版本做了一些修改,增加了它的健壮性,并用更清晰的例子改进了文档。
我的 mods/updates post 有空的时候可以过来吗?最终我希望提出一个拉取请求,将我的更新放入他的存储库中。
解决方案
Class ssp.class.php
不支持连接和子查询,但有一个解决方法。诀窍是使用子查询,如下面的 $table
定义所示。将 table
替换为您在子查询中的实际 table 名称。
$table = <<<EOT
(
SELECT
a.id,
a.name,
a.father_id,
b.name AS father_name
FROM table a
LEFT JOIN table b ON a.father_id = b.id
) temp
EOT;
$primaryKey = 'id';
$columns = array(
array( 'db' => 'id', 'dt' => 0 ),
array( 'db' => 'name', 'dt' => 1 ),
array( 'db' => 'father_id', 'dt' => 2 ),
array( 'db' => 'father_name', 'dt' => 3 )
);
$sql_details = array(
'user' => '',
'pass' => '',
'db' => '',
'host' => ''
);
require( 'ssp.class.php' );
echo json_encode(
SSP::simple( $_GET, $sql_details, $table, $primaryKey, $columns )
);
您还需要编辑 ssp.class.php
并将 FROM `$table`
的所有实例替换为 FROM $table
以删除反引号。
确保所有列名都是唯一的,否则使用 AS
分配别名。
注意事项
还有 github.com/emran/ssp 存储库,其中包含增强的 ssp.class.php
支持 JOIN。
链接
有关详细信息,请参阅 jQuery DataTables: Using WHERE, JOIN and GROUP BY with ssp.class.php。
我对原始 Datatables 的分支 ssp.class.php:https://github.com/emayskiy/Datatables-SSP-MultiTables
您可以为表和列添加别名,使用 where,对表使用 [LEFT, INNER, RIGHT, CROSS] JOIN。 示例 server_processing.php:
<?php
//For one table:
//$table = "main_table_name";
//Or for multitable queries:
$table = array(
array('table'=>'main_table_name', 'as'=>'mt'),
array('table'=>'join1_table_name', 'as'=>'jt1', 'join_type'=>'INNER', 'join_on'=>'mt.field = jt1.field'),
array('table'=>'join2_table_name', 'as'=>'jt2', 'join_type'=>'LEFT', 'join_on'=>'mt.field1 = jt2.field')
);
//Columns definition with alias
$columns = array(
array( 'db' => 'mt.field1', 'dt' => 0 ),
array( 'db' => 'mt.field2', 'dt' => 1 ),
array( 'db' => 'mt.name', 'as'=>'field3', 'dt' => 2 ),
array( 'db' => 'jt1.field1', 'as'=>'field4', 'dt' => 3 ),
array( 'db' => 'jt2.field5', 'as'=>'field5', 'dt' => 4 )
);
$primaryKey = 'mt.id'; //Primary key, for check records count
$sql_details = array(
'user' => $db_user,
'pass' => $db_password,
'db' => $db_name,
'host' => $db_host
);
$where = "mt.field1 > 10"; //You SQL where condition
require('ssp.class.php' ); //File from github.com/emayskiy/Datatables-SSP-MultiTables
echo json_encode(
// All params same as in original class SSP
SSP::complex( $_GET, $sql_details, $table, $primaryKey, $columns , '', $where)
);
?>
抱歉来晚了,但我能够通过构建自己的服务器端文件来解决问题,这样我就可以自定义查询和 json 输出。
文件服务器端自定义:
public function produtosEstoque($arr)
{
//COLUNAS
$column = array('prodNome', 'prodPreco', 'prodQtdEst', 'categDescricao');
//SQL
$query2 = "SELECT a.prodID, a.prodNome, a.prodMedida, a.prodPrecoAnt, a.prodPreco, a.prodCategoriaID, a.prodOferta,a.prodQtdEst, a.prodQtdMEst, b.categDescricao FROM produtos a INNER JOIN categoria b ON a.prodCategoriaID = b.categID WHERE a.prodEstatusID = 6 ";
//SEARCH
if ($arr['search']['value']) {
$query2 .= "AND prodNome LIKE '%".$arr['search']['value']."%' ";
}
//ORDER
if (isset($arr['order'])) {
$query2 .= 'ORDER BY ' . $column[$arr['order']['0']['column']] . ' ' . $arr['order']['0']['dir'] . ' ';
} else {
$query2 .= 'ORDER BY a.prodID DESC ';
}
//LIMIT
if ($arr["length"] != -1) {
$query3 = 'LIMIT ' . $arr['start'] . ', ' . $arr['length'];
}
try {
//TOTAL DE REGISTROS NA TABELA
$query1 = "SELECT * FROM produtos WHERE prodEstatusID = 6";
$stm1 = $this->pdo->prepare($query1);
$stm1->execute();
$contReg = $stm1->rowCount($stm1);
$stm = $this->pdo->prepare($query2);
$stm->execute();
$number_filter_row = $stm->rowCount($stm);
$stm = $this->pdo->prepare($query2 . $query3);
$stm->execute();
$list = $stm->fetchAll(PDO::FETCH_OBJ);
$data = [];
foreach ($list as $row) {
$data[] = array('prod_nome' => $row->prodNome . ", " . $row->prodMedida, 'prod_preco' => "R$ ".$this->convInReal($row->prodPreco)." ".$this->formatProdOff($row->prodOferta), 'prod_estoque' => $row->prodQtdEst . " - M: " . $row->prodQtdMEst, 'prod_categoria' => $row->categDescricao);
}
$dat = array('draw' => intval($arr["draw"]),
'recordsTotal' => $contReg,
'recordsFiltered' => $number_filter_row,
'data' => $data
);
return json_encode($dat, JSON_UNESCAPED_UNICODE);
} catch (PDOException $erro) {
$data = array('msgEr' => 'ERR_002_EI', 'erroLine' => $erro->getLine());
return json_encode($data);
}
}
我通过在 mysql phpmyadmin 中创建视图 table 解决了这个问题。
运行 您在 phpmyadmin 中的 sql 脚本,然后单击 创建视图
enter image description here