このクエリは、phpMyAdminに5つの結果を返します。
SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT 0,5
そして、これはphpMyAdminでcount = 12を返します(12のレコードがあるので問題ありません):
SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT 0,5
この関数は、2つの変数(offset、display)を追加する前は正常に機能していましたが、現在は機能していません。変数を出力すると、offset = 0、display = 5になります(それでもLIMIT 0,5
)。
function getProducts($offset, $display) {
$sql = "SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT ?,?;";
$data = array((int)$offset, (int)$display);
$rows = dbRowsCount($sql, $data);
logErrors("getProducts(".$offset.",".$display.") returned ".$rows." rows.");
if ($rows > 0) {
dbQuery($sql, $data);
return dbFetchAll();
} else {
return null;
}
}
私のdbRowsCount(...)
メソッドが空の文字列(stupid PDOStatement::fetchColumn
)を返していたために機能していなかったので、カウントを返すように変更し、PDO::FETCH_ASSOC
count=0を返しました。
行数をカウントする関数は次のとおりです。
function dbRowsCount($sql, $data) {
global $db, $query;
$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/is';
if (preg_match($regex, $sql, $output) > 0) {
$query = $db->prepare("SELECT COUNT(*) AS count FROM {$output[1]}");
logErrors("Regex output: "."SELECT COUNT(*) AS count FROM {$output[1]}");
$query->setFetchMode(PDO::FETCH_ASSOC);
if ($data != null) $query->execute($data); else $query->execute();
if (!$query) {
echo "Oops! There was an error: PDOStatement returned false.";
exit;
}
$result = $query->fetch();
return (int)$result["count"];
} else {
logErrors("Regex did not match: ".$sql);
}
return -1;
}
私のエラーログは私にプログラムからのこの出力を与えます:
正規表現の出力:SELECT COUNT(*)AS count FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT?、?;
getProducts(0,5)は0行を返しました。
ご覧のとおり、SQLの形式は正しくなく、メソッドの入力変数は予想どおり0と5でした。
何がうまくいかなかったのか誰か知っていますか?
アップデート
提案に従って、クエリを直接実行しようとしましたが、正しい結果が返されました。
function dbDebugTest() {
global $db;
$stmt = $db->query("SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update LIMIT 0,5;");
$result = $stmt->fetch();
$rows = (int)$result["count"];
logErrors("dbDebugTest() returned rows=".$rows);
}
出力:
> dbDebugTest() returned rows=12
別の提案に従って、!= nullを!== nullに変更し、$data配列も出力しました。
logErrors("Data: ".implode(",",$data));
if ($data !== null) $query->execute($data); else $query->execute();
出力:
> Data: 0,5
ただし、dbRowsCount($ sql、$ data)は、このクエリに対して0行を返します。
アップデート2
値がバインドされた後にクエリを出力できるカスタムPDOStatementクラスを実装するためのアドバイスに従って、$ query-> execute($ data)の後で関数が停止するため、出力は出力されないことがわかりました。カスタムクラスは、私のプログラムの他のすべてのクエリに対して機能します。
更新されたコード:
function dbRowsCount($sql, $data) {
global $db, $query;
$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/is';
if (preg_match($regex, $sql, $output) > 0) {
$query = $db->prepare("SELECT COUNT(*) AS count FROM {$output[1]}");
logErrors("Regex output: "."SELECT COUNT(*) AS count FROM {$output[1]}");
$query->setFetchMode(PDO::FETCH_ASSOC);
logErrors("Data: ".implode(",",$data));
$query->execute($data);
logErrors("queryString:".$query->queryString);
logErrors("_debugQuery():".$query->_debugQuery());
if (!$query) {
echo "Oops! There was an error: PDOStatement returned false.";
exit;
}
$result = $query->fetch();
return (int)$result["count"];
} else {
logErrors("Regex did not match: ".$sql);
}
return -1;
}
出力:
正規表現の出力:SELECT COUNT()AS count FROM tbl_product_category WHERE id = ?;
データ:5
queryString:SELECT COUNT()AS count FROM tbl_product_category WHERE id = ?;
_debugQuery():SELECT COUNT(*)AS count FROM tbl_product_category WHERE id = ?;正規表現の出力:SELECT COUNT(*)AS count FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT?、?;
データ:0,5
//関数が停止し、_debugQueryを出力できませんでした
アップデート3
getProducts(...)
カスタムPDOStatementクラスを取得して出力を取得できなかったため、代わりに名前付きプレースホルダーを使用してパラメーターをバインドするようにクラスを書き直したいと思いました。
function getProducts($offset, $display) {
$sql = "SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT :offset, :display;";
$data = array(':offset'=>$offset, ':display'=>$display);
$rows = dbRowsCount($sql, $data);
logErrors("getProducts(".$offset.",".$display.") returned ".$rows." rows.");
if ($rows > 0) {
dbQuery($sql, $data);
return dbFetchAll();
} else {
return null;
}
}
出力:
正規表現の出力:SELECT COUNT(*)AS count FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT:offset、:display;
データ:0,5
// $ query-> execute($ data)の後もクラッシュするため、出力logErrors("getProducts(".$offset."...))
されませんでした
アップデート4
このdbDebugTestは、以前はSQL文字列で直接制限値0,5を宣言することで機能していました。これで、パラメーターを適切にバインドするように更新しました。
function dbDebugTest($offset, $display) {
logErrors("Beginning dbDebugTest()");
global $db;
$stmt = $db->prepare("SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update LIMIT :offset,:display;");
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->bindParam(':display', $display, PDO::PARAM_INT);
if ($stmt->execute()) {
$result = $stmt->fetch();
$rows = (int)$result["count"];
logErrors("dbDebugTest() returned rows=".$rows);
} else {
logErrors("dbDebugTest() failed!");
}
}
関数がクラッシュし、これだけが出力されます。
dbDebugTest()の開始
アップデート5
エラーをオンにする(デフォルトではオフになっている)という提案に従って、私はこれを行いました:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
それ自体が、Update 4のdbDebugTest()を機能させました。
dbDebugTest()の開始dbDebugTest()はrows=12を返しました
そして今、私のウェブサーバーのログにエラーが生成されます:
[警告]mod_fcgid:stderr:PHP致命的なエラー:
キャッチされない例外'PDOException'とメッセージ'SQLSTATE [42000]:
構文エラーまたはアクセス違反:1064SQL構文にエラーがあります。 /home/linweb09/b/example.com-1050548206/user/my_program/database/ の1行目の「0」、「5」の近く
で使用する正しい構文については、MySQLサーバーのバージョンに対応するマニュアルを確認してください。dal.php:36
36行目dbRowsCount(...)
はメソッドを示し、行は$query->execute($data)
です。
したがって、他の方法getProducts(...)
は、データをバインドするこの方法を使用し、パラメーターが「0」と「5」に変わるため、まだ機能しません(これはバグですか?)。少し面倒ですが、dal.phpに新しいメソッドを作成して、より厳密な方法でparamsをバインドできるようにする必要がありbindParam
ます。
特に@Travesty3と@eggyalの助けに感謝します!! どうもありがとうございました。