MySQL からデータを取得する PHP サーバー側スクリプトで JQuery Datatables を使用しています。Datatables サイトから PHP スクリプトの例を取得し、古い mysql から mysqli に変更するために少し変更しました。このスクリプトは、ページング、順序付け、フィルタリングなどのいくつかのパラメーターを受け入れます。最初の 2 つは常に数字であり、MySQL リクエストに渡す前に intval 関数で初期化できるため、問題はありません。しかし、フィルタリングにはテキスト値が必要であり、mysqli の準備済みステートメントを使用してサニタイズしたいと考えています。コードは次のとおりです。
require_once "mysqli_conection.php"
$aColumns = array( 'engine', 'browser', 'platform', 'version', 'grade' );
/*
* 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" )
{
$sOrder .= $aColumns[ intval( $_GET['iSortCol_'.$i] ) ]."
".($_GET['sSortDir_'.$i]==='asc' ? 'asc' : 'desc') .", ";
}
}
$sOrder = substr_replace( $sOrder, "", -2 );
if ( $sOrder == "ORDER BY" )
{
$sOrder = "";
}
}
/*
* Filtering
*/
$sWhere = "";
if ( isset($_GET['sSearch']) && $_GET['sSearch'] != "" )
{
$sWhere = "WHERE (";
for ( $i=0 ; $i<count($aColumns) ; $i++ )
{
if ( isset($_GET['bSearchable_'.$i]) && $_GET['bSearchable_'.$i] == "true" )
{
$sWhere .= $aColumns[$i]." LIKE '%".mysql_real_escape_string( $_GET['sSearch'] )."%' OR ";
}
}
$sWhere = substr_replace( $sWhere, "", -3 );
$sWhere .= ')';
}
/*
* SQL queries
*/
$sQuery = "
SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))."
FROM $sTable
$sWhere
$sOrder
$sLimit
";
$rResult = $mysqli->query( $sQuery, $gaSql['link'] );
/* Data set length after filtering */
$sQuery = "
SELECT FOUND_ROWS()
";
$rResultFilterTotal = $mysqli->query( $sQuery, $gaSql['link'] );
$aResultFilterTotal = $rResultFilterTotal->fetch_array(MYSQLI_NUM);
$iFilteredTotal = $aResultFilterTotal[0];
/* Total data set length */
$sQuery = "
SELECT COUNT(".$sIndexColumn.")
FROM $sTable
";
$rResultTotal = $mysqli->query( $sQuery, $gaSql['link'] );
$aResultTotal = $rResultTotal->fetch_array(MYSQLI_NUM);
$iTotal = $aResultTotal[0];
/*
* Output
*/
$output = array(
"sEcho" => intval($_GET['sEcho']),
"iTotalRecords" => $iTotal,
"iTotalDisplayRecords" => $iFilteredTotal,
"aaData" => array()
);
while ( $aRow = $rResult->fetch_array(MYSQLI_NUM) )
{
$row = array();
for ( $i=0 ; $i<count($aColumns) ; $i++ )
{
if ( $aColumns[$i] != ' ' )
{
$row[] = $aRow[ $aColumns[$i] ];
}
}
$output['aaData'][] = $row;
}
echo json_encode( $output );
問題は、フィルタリングがオプションのパラメーターであり、その上で準備されたステートメントを実行する方法がわからないことです。そのリクエストが常に存在する場合、私は次のようにします:
$stmt = $mysqli->prepare( $dataQuery );
$stmt->bind_param("sssss", "%".$_GET['sSearch']."%", "%".$_GET['sSearch']."%", "%".$_GET['sSearch']."%", "%".$_GET['sSearch']."%", "%".$_GET['sSearch']."%")
$stmt->execute();
$rResult = $stmt->get_result();
/* 出力 */ セクションの直前に配置します。sSearch リクエスト セットに応じて、準備されたステートメントと通常のステートメントを切り替えるだけでよいでしょうか。
if ( isset($_GET['sSearch']) && $_GET['sSearch'] != "" ) {
$stmt = $mysqli->prepare( $dataQuery );
$stmt->bind_param("%".$_GET['sSearch']."%", "%".$_GET['sSearch']."%", "%".$_GET['sSearch']."%", "%".$_GET['sSearch']."%", "%".$_GET['sSearch']."%")
$stmt->execute();
$rResult = $stmt->get_result();
} else {
$rResult = $mysqli->query($dataQuery);
}
/*
* Output
*/
//etc.
それは安全でしょうか?