Оператор ==
для объектов в Javascript проверяет, являются ли объекты одной и той же ссылкой на фактический объект, а не если они представляют собой два отдельных объекта, которые содержат одно и то же содержимое. Нет встроенного оператора для проверки того, содержат ли они одно и то же содержимое. Вам нужно будет написать функцию, чтобы выполнить подобное сравнение.
Преобразование строк является одним из способов сравнения двух массивов, если элементы массива содержат только примитивные значения (а не другие объекты). Если элементы массива могут содержать другие элементы, тогда вам нужно будет убедиться, что сами эти объекты также были преобразованы в репрезентативные строки.
И преобразование в строку не различало бы элемент массива, содержащий "4"
против единицы, которая содержит 4
, поскольку оба преобразуются в "4"
в строчном представлении.
Пробовал следующий код
$db = new PDO("mysql:host={$dbhost};dbname={$dbname};charset=utf8", $dbuser, $dbpass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
Тогда
try {
$db->query('SET NAMES gbk');
$stmt = $db->prepare('SELECT * FROM 2_1_paidused WHERE NumberRenamed = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));
}
catch (PDOException $e){
echo "DataBase Errorz: " .$e->getMessage() .'<br>';
}
catch (Exception $e) {
echo "General Errorz: ".$e->getMessage() .'<br>';
}
И получил
DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '/*' LIMIT 1' at line 1
Если добавлено $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
после $db = ...
Затем появилась пустая страница
Если вместо этого SELECT
попытался DELETE
, то в обоих случаях была получена ошибка, подобная
DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '* FROM 2_1_paidused WHERE NumberRenamed = '¿\' OR 1=1 /*' LIMIT 1' at line 1
Итак, мой вывод о том, что инъекции невозможно ...
Быстрый и грязный подход:
function exec_sql_from_file($path, PDO $pdo) {
if (! preg_match_all("/('(\\\\.|.)*?'|[^;])+/s", file_get_contents($path), $m))
return;
foreach ($m[0] as $sql) {
if (strlen(trim($sql)))
$pdo->exec($sql);
}
}
Разбивается на разумные конечные точки оператора SQL. Проверка ошибок отсутствует, защита от инъекций отсутствует. Поймите свое использование перед использованием. Лично я использую его для загрузки необработанных файлов миграции для тестирования интеграции.
По прошествии половины дня с этим выяснилось, что PDO имеет ошибку, где ...
-
//This would run as expected:
$pdo->exec("valid-stmt1; valid-stmt2;");
-
//This would error out, as expected:
$pdo->exec("non-sense; valid-stmt1;");
-
//Here is the bug:
$pdo->exec("valid-stmt1; non-sense; valid-stmt3;");
Он выполнил бы "valid-stmt1;"
, остановился на "non-sense;"
и никогда не выдавал ошибку. Не будет запускать "valid-stmt3;"
, возвращать true и лежать в том, что все работает хорошо.
Я ожидал бы, что это ошибка на "non-sense;"
, но это не так.
Здесь где я нашел эту информацию: Недопустимый запрос PDO не возвращает ошибку
Вот ошибка: https://bugs.php.net/bug.php ? id = 61613
Итак, я попытался сделать это с помощью mysqli и на самом деле не нашел твердого ответа на то, как он работает, поэтому я думал, что просто оставлю его здесь для тех, кто хотите использовать ..
try{
// db connection
$mysqli = new mysqli("host", "user" , "password", "database");
if($mysqli->connect_errno){
throw new Exception("Connection Failed: [".$mysqli->connect_errno. "] : ".$mysqli->connect_error );
exit();
}
// read file.
// This file has multiple sql statements.
$file_sql = file_get_contents("filename.sql");
if($file_sql == "null" || empty($file_sql) || strlen($file_sql) <= 0){
throw new Exception("File is empty. I wont run it..");
}
//run the sql file contents through the mysqli's multi_query function.
// here is where it gets complicated...
// if the first query has errors, here is where you get it.
$sqlFileResult = $mysqli->multi_query($file_sql);
// this returns false only if there are errros on first sql statement, it doesn't care about the rest of the sql statements.
$sqlCount = 1;
if( $sqlFileResult == false ){
throw new Exception("File: '".$fullpath."' , Query#[".$sqlCount."], [".$mysqli->errno."]: '".$mysqli->error."' }");
}
// so handle the errors on the subsequent statements like this.
// while I have more results. This will start from the second sql statement. The first statement errors are thrown above on the $mysqli->multi_query("SQL"); line
while($mysqli->more_results()){
$sqlCount++;
// load the next result set into mysqli's active buffer. if this fails the $mysqli->error, $mysqli->errno will have appropriate error info.
if($mysqli->next_result() == false){
throw new Exception("File: '".$fullpath."' , Query#[".$sqlCount."], Error No: [".$mysqli->errno."]: '".$mysqli->error."' }");
}
}
}
catch(Exception $e){
echo $e->getMessage(). " <pre>".$e->getTraceAsString()."</pre>";
}
Попробуйте эту функцию: несколько запросов и вставка нескольких значений.
function employmentStatus($Status) {
$pdo = PDO2::getInstance();
$sql_parts = array();
for($i=0; $i<count($Status); $i++){
$sql_parts[] = "(:userID, :val$i)";
}
$requete = $pdo->dbh->prepare("DELETE FROM employment_status WHERE userid = :userID; INSERT INTO employment_status (userid, status) VALUES ".implode(",", $sql_parts));
$requete->bindParam(":userID", $_SESSION['userID'],PDO::PARAM_INT);
for($i=0; $i<count($Status); $i++){
$requete->bindParam(":val$i", $Status[$i],PDO::PARAM_STR);
}
if ($requete->execute()) {
return true;
}
return $requete->errorInfo();
}