Reputation: 11
I have been using DataTables with the below PHP script that uses OCI however since I re-wrote the whole site to utilize PDO I now need to update this PHP script to also utilize PDO.
The problem is that there are no error messages reported (I have error reporting enabled) but the DataTable is empty.
Is there a noticeable mistake in how I converted it to utilize PDO?
// Database connection information
$sql = array(
'user' => 'user',
'password' => 'pass',
'server' => '192.168.0.1',
'db' => 'A.world'
);
// Oracle connection
$conn = oci_connect($sql['user'], $sql['password'], $sql['server'].'/'.$sql['db']);//$connection_string);
if (!$conn) {
$e = oci_error();
trigger_error( htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR );
}
// Action
$out = dt_oci_ssp( $conn, $query, $_POST );
echo json_encode( $out );
/**
* DataTables 1.10+ server-side processing function for Oracle using oci_*
* methods
* @param resource $conn Connection from `oci_connect`
* @param array $query Information for the query to be performed
* @param array $data Data from the server-side processing request
* @return array Data returned for server-side processing
*/
function dt_oci_ssp( $conn, $query, $data ) {
$bindings = array();
/*
* Ordering
*/
$orderBy = array();
if ( isset( $data['order'] ) ) {
for ( $i=0, $size=count( $data['order'] ) ; $i<$size ; ++$i ) {
$sort = $data['order'][$i];
//Add to the order by clause
$orderBy[] = dt_oci_field( $query, $sort['column'] ) .' '. (
$sort['dir'] === 'asc' ?
'asc' :
'desc'
);
}
}
$orderBy = count( $orderBy ) ?
'ORDER BY '.implode(', ', $orderBy) :
'';
// Conditions
$where = array();
$whereJoinOnly = array();
$globalWhere = array();
for ( $i=0, $size=count( $data['columns'] ) ; $i<$size ; ++$i ) {
$column = $data['columns'][$i];
if ( $column['searchable'] && $data['search']['value'] ) {
$bindings[':globalSearch'.$i] = '%'.$data['search']['value'].'%';
$globalWhere[] = dt_oci_field( $query, $i ) ." LIKE :globalSearch".$i;
}
}
if ( count( $globalWhere ) ) {
$where[] .= '('.implode(' OR ', $globalWhere).')';
}
// Column filter
for ( $i=0, $size=count( $data['columns'] ) ; $i<$size ; ++$i ) {
$column = $data['columns'][$i];
if ( $column['searchable'] && $column['search']['value'] ) {
$bindings[':columnSearch'.$i] = '%'.$column['search']['value'].'%';
$where[] = dt_oci_field( $query, $i ) ." LIKE :columnSearch".$i;
}
}
// Joins
for ( $i=0, $size=count( $query['conditions'] ) ; $i<$size ; ++$i ) {
$where[] = $query['conditions'][$i];
$whereJoinOnly[] = $query['conditions'][$i];
}
$where = count( $where ) ?
'WHERE '.implode( ' AND ', $where ) :
'';
$whereJoinOnly = count( $whereJoinOnly ) ?
'WHERE '.implode( ' AND ', $whereJoinOnly ) :
'';
$tables = implode( ', ', $query['tables'] );
$select = array();
for ( $i=0, $size=count( $query['fields'] ) ; $i<$size ; ++$i ) {
$select[] = dt_oci_field( $query, $i, 'select' ) .' as "'. dt_oci_field( $query, $i ).'"';
}
$select = implode( ', ', $select );
$betweenLower = intval($data['start']);
$betweenUpper = intval($data['start'] + $data['length']);
if ( $data['length'] != -1 ) {
$dataOut = dt_oci_exec( $conn, $bindings, <<<EOD
SELECT a.*
FROM (
SELECT rownum rnum, b.*
FROM (
SELECT $select
FROM $tables
$where
$orderBy
) b
WHERE rownum <= $betweenUpper
) a
WHERE rnum > $betweenLower
EOD
);
}
else {
// All records
$dataOut = dt_oci_exec( $conn, $bindings, <<<EOD
SELECT a.*
FROM (
SELECT rownum rnum, b.*
FROM (
SELECT $select
FROM $tables
$where
$orderBy
) b
) a
EOD
);
}
$filterCount = dt_oci_exec( $conn, $bindings, <<<EOD
SELECT COUNT(*) as COUNT
FROM $tables
$where
$orderBy
EOD
);
$fullCount = dt_oci_exec( $conn, $bindings, <<<EOD
SELECT COUNT(*) as COUNT
FROM $tables
$whereJoinOnly
EOD
);
// Output
$out = array(
'draw' => intval( $data['draw'] ),
'data' => array(),
'recordsFiltered' => intval($filterCount['COUNT'][0]),
'recordsTotal' => intval($fullCount['COUNT'][0])
);
for ( $i=0, $ien=count($dataOut['RNUM']) ; $i<$ien ; ++$i ) {
$row = array();
for ( $j=0, $jen=count($data['columns']) ; $j<$jen ; ++$j ) {
$row[] = $dataOut[ dt_oci_field( $query, $j ) ][$i];
}
$out['data'][] = $row;
}
return $out;
}
/**
* Get a field property for a query
* @param array $query Query information
* @param integer $idx Field index
* @param string $type `name` or `select`
* @return string column name
*/
function dt_oci_field ( $query, $idx, $type='name' ) {
if ( is_array( $query['fields'][$idx] ) ) {
return $query['fields'][$idx][$type];
}
return $query['fields'][$idx];
}
/**
* Perform a SQL command, returning the full result set
* @param resource $conn Connection from `oci_connect`
* @param array $bindings Binding information to use
* @param string $query SQL query
* @return array Results
*/
function dt_oci_exec( $conn, $bindings, $query )
{
$stmt = oci_parse( $conn, trim($query) );
foreach ($bindings as $key => $value) {
if ( strpos( $query, $key) ) {
oci_bind_by_name( $stmt, $key, $value );
}
}
oci_execute( $stmt );
oci_fetch_all( $stmt, $data );
oci_free_statement( $stmt );
return $data;
// Oracle connection
$dbh = new PDO('oci:dbname=//192.168.0.1:1521/A.world', 'user', 'pass', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
// Action
$out = dt_oci_ssp( $dbh, $query, $_POST );
echo json_encode( $out );
/**
* DataTables 1.10+ server-side processing function for Oracle using oci_*
* methods
* @param resource $dbh Connection from `oci_connect`
* @param array $query Information for the query to be performed
* @param array $data Data from the server-side processing request
* @return array Data returned for server-side processing
*/
function dt_oci_ssp( $dbh, $query, $data ) {
$bindings = array();
/*
* Ordering
*/
$orderBy = array();
if ( isset( $data['order'] ) ) {
for ( $i=0, $size=count( $data['order'] ) ; $i<$size ; ++$i ) {
$sort = $data['order'][$i];
//Add to the order by clause
$orderBy[] = dt_oci_field( $query, $sort['column'] ) .' '. (
$sort['dir'] === 'asc' ?
'asc' :
'desc'
);
}
}
$orderBy = count( $orderBy ) ?
'ORDER BY '.implode(', ', $orderBy) :
'';
// Conditions
$where = array();
$whereJoinOnly = array();
$globalWhere = array();
for ( $i=0, $size=count( $data['columns'] ) ; $i<$size ; ++$i ) {
$column = $data['columns'][$i];
if ( $column['searchable'] && $data['search']['value'] ) {
$bindings[':globalSearch'.$i] = '%'.$data['search']['value'].'%';
$globalWhere[] = dt_oci_field( $query, $i ) ." LIKE :globalSearch".$i;
}
}
if ( count( $globalWhere ) ) {
$where[] .= '('.implode(' OR ', $globalWhere).')';
}
// Column filter
for ( $i=0, $size=count( $data['columns'] ) ; $i<$size ; ++$i ) {
$column = $data['columns'][$i];
if ( $column['searchable'] && $column['search']['value'] ) {
$bindings[':columnSearch'.$i] = '%'.$column['search']['value'].'%';
$where[] = dt_oci_field( $query, $i ) ." LIKE :columnSearch".$i;
}
}
// Joins
for ( $i=0, $size=count( $query['conditions'] ) ; $i<$size ; ++$i ) {
$where[] = $query['conditions'][$i];
$whereJoinOnly[] = $query['conditions'][$i];
}
$where = count( $where ) ?
'WHERE '.implode( ' AND ', $where ) :
'';
$whereJoinOnly = count( $whereJoinOnly ) ?
'WHERE '.implode( ' AND ', $whereJoinOnly ) :
'';
$tables = implode( ', ', $query['tables'] );
$select = array();
for ( $i=0, $size=count( $query['fields'] ) ; $i<$size ; ++$i ) {
$select[] = dt_oci_field( $query, $i, 'select' ) .' as "'. dt_oci_field( $query, $i ).'"';
}
$select = implode( ', ', $select );
$betweenLower = intval($data['start']);
$betweenUpper = intval($data['start'] + $data['length']);
if ( $data['length'] != -1 ) {
$dataOut = dt_oci_exec( $dbh, $bindings, <<<EOD
SELECT a.*
FROM (
SELECT rownum rnum, b.*
FROM (
SELECT $select
FROM $tables
$where
$orderBy
) b
WHERE rownum <= $betweenUpper
) a
WHERE rnum > $betweenLower
EOD
);
}
else {
// All records
$dataOut = dt_oci_exec( $dbh, $bindings, <<<EOD
SELECT a.*
FROM (
SELECT rownum rnum, b.*
FROM (
SELECT $select
FROM $tables
$where
$orderBy
) b
) a
EOD
);
}
$filterCount = dt_oci_exec( $dbh, $bindings, <<<EOD
SELECT COUNT(*) as COUNT
FROM $tables
$where
$orderBy
EOD
);
$fullCount = dt_oci_exec( $dbh, $bindings, <<<EOD
SELECT COUNT(*) as COUNT
FROM $tables
$whereJoinOnly
EOD
);
// Output
$out = array(
'draw' => intval( $data['draw'] ),
'data' => array(),
'recordsFiltered' => intval($filterCount['COUNT'][0]),
'recordsTotal' => intval($fullCount['COUNT'][0])
);
for ( $i=0, $ien=count($dataOut['RNUM']) ; $i<$ien ; ++$i ) {
$row = array();
for ( $j=0, $jen=count($data['columns']) ; $j<$jen ; ++$j ) {
$row[] = $dataOut[ dt_oci_field( $query, $j ) ][$i];
}
$out['data'][] = $row;
}
return $out;
}
/**
* Get a field property for a query
* @param array $query Query information
* @param integer $idx Field index
* @param string $type `name` or `select`
* @return string column name
*/
function dt_oci_field ( $query, $idx, $type='name' ) {
if ( is_array( $query['fields'][$idx] ) ) {
return $query['fields'][$idx][$type];
}
return $query['fields'][$idx];
}
/**
* Perform a SQL command, returning the full result set
* @param resource $dbh Connection from `oci_connect`
* @param array $bindings Binding information to use
* @param string $query SQL query
* @return array Results
*/
function dt_oci_exec( $dbh, $bindings, $query )
{
try {
$stmt = $dbh->prepare($query);
foreach ($bindings as $key => $value) {
if ( strpos( $query, $key) ) {
$stmt->bindParam(":$key", $value);
}
}
$stmt->execute();
$data = $stmt->fetchAll();
$stmt = null;
return $data;
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
I have sat and looked at both code for a number of hours now and as far as I can tell I have converted it to use the correct PDO commands etc.
Upvotes: 0
Views: 1079
Reputation: 360672
Wrong quotes:
$stmt->bindParam(':$key', $value);
^-----^--
'
-quoted strings do not interpolate variable values, so you're binding a placeholder with the literal name $
, k
, e
, etc... which doesn't exist in your query. So the bind fails, and since you have no error handling in your code, you never see the error messages PDO could be giving you.
NEVER assume success. Always assume failure, check for that failure, and treat success as a pleasant surprise.
Try
$stmt->bindParam(":$key", $value);
^-----^---
instead.
Upvotes: 1