i have this function below. that i used to run on a MySQL DB. I had to move to a SQL Server 2008, easy thing.
But, after that, the rowCount() keeps returning -1, I've never had this happen before. I'm sure that my SQL query is returning the results, because if I do a print_r() on my return (the $rows var), everything gets printed.
So, if anyone had this issue, please help me to figure this out.
Sorry for any grammatical mistake.
public function listar(){
$retorno = array();
$sql = "SELECT m.id, m.descricao, m.link, m.categoria, m.icone FROM menus AS m, grupos AS g, permissoes AS p WHERE (g.id = p.idgrupo AND m.id = p.idmenu) AND (p.status = :pstatus AND g.status = :gstatus AND m.status = :mstatus) AND g.id = :gid ORDER BY m.ordem ;";
$vars = array(":pstatus"=>1,":gstatus"=>1,":mstatus"=>1,":gid"=>$_SESSION['group']);
$stmt = $this->pdo->prepare($sql);
foreach($vars as $index => $value){
$stmt->bindValue($index,$value);
}
if($stmt->execute()){
$count = $stmt->rowCount();
$rows = $stmt->fetchAll(PDO::FETCH_OBJ);
$rows['msg'] = '1';
$rows['length'] = $count;
$i = 0;
while($i < $count){
foreach($rows[$i] as $index => $value){
$rows[$i]->$index = utf8_encode($value);
}
$i++;
}
return $rows;
} else {
return array("msg" => '0');
}
}
Got it guys.
The prepare() statement should receive one more parameter. array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL) .
$stmt = $this->pdo->prepare($sql,array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
After that the rowCount() should work fine.
Thanks for the answer #Rasclatt.
I think you may be running into the gotcha on the PDO rowCount() function. As stated in the PHP manual. The second sentence is the gotcha...:
"If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. However, this behavior is not guaranteed for all databases and should not be relied on for portable applications."
Instead, you should use a COUNT(*) sql statement.
Related
This question already has answers here:
PHP - Using PDO with IN clause array
(9 answers)
Closed 24 days ago.
I did have this code working but it was not secure from SQL injection so I tried to update it. The user submit filter requirements which come from check boxes, I take them from post, and replace them with ?, I then implode, and bind them back together for the IN clause.
I feel like I am a couple of lines of code away from getting this. What am I doing wrong? I have echoed out after implode and it shows the right amount of ? corresponding to the selections. Is the problem in my execute statement?
if(isset($_POST['songgenre'])){
$songgenre = $_POST['songgenre'];
$placeholderssonggenre = array_fill(1, count($songgenre), '?');
$songgenrefilter = implode(',', $placeholderssonggenre);
}else{
$songgenre ='';
$genreempty = '';
}
$sql = "SELECT * FROM music_db WHERE songgenre IN ($songgenrefilter)";
$stmt = $conn->prepare($sql);
$res = $stmt->execute($songgenre);
if ($res !== FALSE) {
$results = $res->rowCount();
echo($results);
} else {
echo "Code Failed";
}
I know really how frustrating it could be. Well, it seems that following things are missing there. Try it:
When you're using the IN clause, you need to pass an array of values to the execute() method, not a single variable. This means that you should be passing $songgenre directly to the execute() method, instead of using it to create the $placeholderssonggenre variable.
You should bind the parameters to the statement before executing it, not after. You can use the bindValue() method to bind the values to the placeholders in the query.
When you execute the statement, you should use the fetchAll() method to retrieve the rows, instead of rowCount().
Here's the correct code:
if(isset($_POST['songgenre'])){
$songgenre = $_POST['songgenre'];
$placeholders = array_fill(0, count($songgenre), '?');
$placeholders = implode(',', $placeholders);
} else {
$songgenre ='';
$placeholders = '';
}
$sql = "SELECT * FROM music_db WHERE songgenre IN ($placeholders)";
$stmt = $conn->prepare($sql);
foreach ($songgenre as $i => $value) {
$stmt->bindValue($i + 1, $value);
}
$stmt->execute();
$results = $stmt->fetchAll();
Another option more elegant
if(isset($_POST['songgenre'])){
$postfilter = [
'songgenre' => ['filter' => FILTER_SANITIZE_STRING] // always sanitize
];
$filter_post_array = filter_var_array($_POST, $postfilter);
$filtered = $filter_post_array['songgenre'];
} else {
$filtered = [];
}
$sql = "SELECT * FROM music_db WHERE songgenre IN (:songgenrefilter)";
$stmt = $conn->prepare($sql);
$stmt->bindValue(':songgenrefilter',implode(',',$filtered);
$stmt->execute();
$result = $stmt->fetchAll();
I have query in which I would like to pass the result of a MS SQL statement to a variable. Not sure how to do this.
My query:
if($view->id() == 'program_search' &&
!empty($searched_miles_value) &&
!empty($searched_zip_value) &&
($searched_miles_value != 'any')) {
$connection = \Drupal\Core\Database\Database::getConnection();
$result = $connection->query("SELECT to_zip FROM zipmaster_xref WHERE from_zip = '".$searched_zip_value."' AND miles = '".$searched_miles_value."'")-> fetchAll();
$target_zips = $result ; //this line is not working
foreach($result as $zip) {
$target_zips[] = $zip->to_zip;
}
$query->addWhere('new_group', 'node__field_zip.field_zip_value', $target_zips, 'IN');
I want to pass the $result array into $target_zips and loop through it. Can any one help me to fix this?
Thanks!
before fetch your data you have to execute the query for example :
$result = $connection->query("SELECT to_zip FROM zipmaster_xref WHERE from_zip = '".$searched_zip_value."' AND miles = '".$searched_miles_value."'")->execute()->fetchAll();
But this usage is not correct at all.Passing variable to the query directly causing SQL Injection be avoid from this you should use placeholders read the documentations first please.
An example for placeholders :
$query = $database->query("SELECT id, example FROM {mytable} WHERE created > :created", [
':created' => REQUEST_TIME - 3600,
]);
Drupal 8 static query documentation can be found at : https://www.drupal.org/docs/8/api/database-api/static-queries
Sorry if this is a duplicate, I have tried searching but cannot seem to find an answer. I may just have the piece of code in the wrong place.
I have counted the duplicate values input from various select boxes, which were sent over via $_GET. Using these duplicates, if more than (whatever the set amount is) then it will run through a mysql query. This is all working fine.
The issue is that I need to remove duplicates that are returned from the mysql query. Here is my code:
if ($countGearSelected >= 2) {
$gearSets = array_keys(array_filter(array_count_values($_GET['gearPiece']), function($v) {
return $v > 1;
}));
foreach ($gearSets as $gearSetKey => $gearSetValue) {
$result = mysqli_query($con,"SELECT twoPieceBonus FROM sets WHERE setName='".$gearSetValue."';");
while($row = mysqli_fetch_array($result)){
$twoPieceBonus .= urldecode($row['twoPieceBonus']).'</br></br>';
}
$twoPieceBonus = implode(',',array_unique(explode(',', $twoPieceBonus)));
$twoSelected = substr($twoPieceBonus, 0, -10);
}
}else{
$twoSelected = '';
}
As you can see, I have tried the array_unique option on various other posts on SE but it doesn't appear to be working. I think I may be using it incorrectly?
Using DISTINCT doesn't work in the mysql query, as a few of the "sets" that are being queried have the same result (if that makes sense?).
Any help is very much appreciated.
First: your code is vulnerable to SQL injection: use prepared statements to avoid this.
Secondly, it is often a bad idea to execute a query in each iteration of a loop. And in this case it can be avoided. Instead of an equality comparison in your where clause, you could use the in operator and compare to all gear sets in one go.
This will also solve the matter of getting distinct values. With only one query executing, you can use distinct now.
Here is how the code would look like. I could not test this, but I expect mistakes (if any) can be easily fixed:
$twoSelected = '';
if ($countGearSelected >= 2) {
$gearSets = array_keys(array_filter(
array_count_values($_GET['gearPiece']), function($v) {
return $v > 1;
}
));
// Create comma separated list of question marks
$placeHolders = implode(",", array_fill(0, count($gearSets), "?"));
// Prepare SQL statement with it
$stmt = mysqli_prepare($con,
"SELECT DISTINCT twoPieceBonus
FROM sets
WHERE setName IN ($placeHolders);");
// All gearSet values are strings:
$types = str_repeat("s", count($gearSets));
// Turn the gearSets into references
$gearSetRefs = [];
foreach ($gearSets as $i => $_) {
$gearSetRefs[] = &$gearSets[$i];
}
// Bind arguments
mysqli_stmt_bind_param($stmt, $types, ...$gearSetRefs); // the splat operator
// Now we are all set to (safely) execute the query
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
// Let the result of the URL decoding still be an array
$twoPieceBonus = [];
while ($row = mysqli_fetch_array($result)) {
$twoPieceBonus[] = urldecode($row['twoPieceBonus']);
}
mysqli_stmt_close ($stmt);
// ... and then use implode to insert those HTML breaks
$twoSelected = implode("</br></br>", $twoPieceBonus);
}
I am not familiar in this style of coding syntax but I want to use this for my project.
I have a question on how to integrate this query:
SELECT max(id) FROM assignment_billing WHERE assignment_id = 37
into this syntax.
public function fetchBillingByParentId($db,$id) {
$select = $db->select()->from('assignment_billing')->where('assignment_id = '.$id);
$stmt = $select->query();
$result = $stmt->fetchAll();
return $result;
}
I want to use max to get the highest id on that table but my syntax doesn't work.
public function fetchBillingByParentId($db,$id) {
$select = $db->select('max(id)')->from('assignment_billing')->where('assignment_id = '.$id);
$stmt = $select->query();
$result = $stmt->fetchAll();
return $result;
}
Did I forgot something? the first syntax is working though. But in the second syntax it doesn't return any value? I think I have an error in 'select('max(id)')->' line. What might be the proper arrangement in this kind of syntax?
Anytime you use an aggregate you must alias the column.
$select = $db->select('max(id) AS balloon')->from('assignment_billing')->where('assignment_id = '.$id);
You would then reference balloon as the column.
I'm currently learning PHP and MySQL. I'm just wrote a class that handles all the MySQL traffic, but I'm encountering some errors.
function table_exists($tablename){
// check if table exists
$stmt = $this->db->prepare("SHOW TABLES LIKE '?'");
$stmt->bind_param("s", $tablename); //This is line 24.
$stmt->execute();
$ar = $stmt->affected_rows;
$stmt->close();
if ($ar > 0){
return true;
} else {
return false;
}
}
This is the code with the problem, and the error i'm getting is
Generates Warning:
mysqli_stmt::bind_param()
[mysqli-stmt.bind-param]: Number of
variables doesn't match number of
parameters in prepared statement in
C:\xampp\htdocs\mail\datahandler.php
on line 24
Ideas?
Thanks
No need to use quotes when working with prepared statements.
$stmt = $this->db->prepare("SHOW TABLES LIKE ?");
Also, instead of SHOW TABLES, you might want to use information_schema views, which give you a bit more flexibility.
You also have to use a number as first parameter for bind_param()
$stmt->bind_param(1, $tablename);
See here: http://php.net/manual/pdostatement.bindparam.php
For strings you can also just pass an array into execute().
private function table_exists($tablename){
// check if table exists
$stmt = $this->db->query("SHOW TABLES");
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$arr[]=$row;
}
$ar=0;
foreach($arr as $val){
foreach($val as $value){
if($value==$tablename) $ar=1;
}
}
unset($stmt);
if ($ar == 1){
return true;
} else {
return false;
}
}