PHP issue... output stops after loop - php

ive got this code and somehow it stops after the first entry even though there should be way more.
If i take both foreach loops out, its doing fine. So the issue should be there but im either blind or stupid :(
// Main Agenda
$stmt = $mysqli->prepare("
SELECT
agenda.id,
agenda.title,
agenda.timeStart,
agenda.timeEnd,
agenda.description,
agenda.speakers,
agenda.moderators,
agenda_locations.name,
agenda_days.dayDate,
agenda_categories.name
FROM agenda
LEFT JOIN agenda_locations ON agenda.location = agenda_locations.id
LEFT JOIN agenda_days ON agenda.dayDate = agenda_days.id
LEFT JOIN agenda_categories ON agenda.category = agenda_categories.id
WHERE agenda.active = '1'
AND agenda.deleted = '0'
ORDER BY agenda.timeStart ASC
");
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($agendaId, $agendaTitle, $agendaStart, $agendaEnd, $agendaDescription, $agendaSpeakers, $agendaModerators, $agendaLocation, $agendaDate, $agendaCategory);
while ($stmt->fetch()) {
$speakersText = "";
$moderatorsText = "";
if( strlen($agendaSpeakers)>0 ){
foreach(explode('###', $agendaSpeakers) as $speakerId) {
$stmt = $mysqli->prepare("
SELECT
name
FROM speakers
WHERE id = ?
");
$stmt->bind_param('i', $speakerId);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($speakerName);
$stmt->fetch();
$speakersText .= $speakerName.", ";
}
$speakersText = substr_replace($speakersText, "", -2);
}
if( strlen($agendaModerators)>0 ){
foreach(explode('###', $agendaModerators) as $moderatorId) {
$stmt = $mysqli->prepare("
SELECT
name
FROM speakers
WHERE id = ?
");
$stmt->bind_param('i', $moderatorId);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($moderatorName);
$stmt->fetch();
$moderatorsText .= $moderatorName.", ";
}
$moderatorsText = substr_replace($speakersText, "", -2);
}
$var0 = $agendaId;
$var1 = stripslashes($agendaTitle);
$var2 = strtotime($agendaStart);
$var3 = strtotime($agendaEnd);
$var4 = stripslashes($agendaDescription);
$var5 = $speakersText;
$var6 = $moderatorsText;
$var7 = $agendaLocation;
$var8 = strtotime($agendaDate);
$var9 = $agendaCategory;
$agendaMain[] = array ($var0,$var1,$var2,$var3,$var4,$var5,$var6,$var7,$var8,$var9);
}

You have to rename you $stmt variable in your foreach loops.

Related

Why does the function of two database queries show me only the result of the first query?

The output of the following shows me the result of the first query, but not the second. When I make the queries without function it works.
function builtFooter($catactive, $catlink)
{
global $conn;
$sql = "SELECT catid, catname_de AS name, catlink as link, extern, extlink FROM categories WHERE catactive=? AND catlink!=? ORDER BY catsort";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $catactive, $catlink);
$stmt->execute();
$result = $stmt->get_result();
while ($cat = $result->fetch_assoc()) {
$resArr[] = $cat;
echo '<h3>' . $cat['name'] . '</h3>';
$cities = "SELECT COUNT(a.ad_id) AS ANZ,a.region, b.city, b.citylink FROM ads a, neueorte b WHERE a.zeigen=? AND a.gesperrt=? AND FIND_IN_SET(?, a.portale) AND a.catid=? AND b.po_id=a.region GROUP BY a.region ORDER BY ANZ DESC LIMIT 0,50";
$stmt = $conn->prepare($cities);
$zeigen = 'ja';
$gesperrt = 'no';
$category = $cat['catid'];
$stmt->bind_param("ssss", $zeigen, $gesperrt, $portalnumber, $category);
$stmt->execute();
$result = $stmt->get_result();
while ($city = $result->fetch_assoc()) {
$resArr[] = $city;
echo ' ' . $city['city'] . ' <br />';
}
}
}
builtFooter('yes', 'markt');
This queries are working fine, and I get the result I want:
$catactive = 'yes';
$catlink = 'markt';
$sql = "SELECT catid, catname_de AS name, catlink as link, extern, extlink FROM categories WHERE catactive=? AND catlink!=? ORDER BY catsort";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $catactive, $catlink);
$stmt->execute();
$result = $stmt->get_result();
while ($cat = $result->fetch_assoc()) {
$resArr[] = $cat;
echo '<h3>'.$cat['name'].'</h3>';
$cities = "SELECT COUNT(a.ad_id) AS ANZ,a.region, b.city, b.citylink FROM ads a, neueorte b WHERE a.zeigen=? AND a.gesperrt=? AND FIND_IN_SET(?, a.portale) AND a.catid=? AND b.po_id=a.region GROUP BY a.region ORDER BY ANZ DESC LIMIT 0,50";
$stmt = $conn->prepare($cities);
$zeigen = 'ja';
$gesperrt = 'no';
$category = $cat['catid'];
$stmt->bind_param("ssss", $zeigen, $gesperrt, $portalnumber, $category);
$stmt->execute();
$r = $stmt->get_result();
while ($city = $r->fetch_assoc()) {
$resArr[] = $city;
echo' '.$city['city'].' <br />';
}
}
But when I built a function, I do not get the results of the secode query:
function builtFooter($catactive,$catlink){
global $conn;
$sql = "SELECT catid, catname_de AS name, catlink as link, extern, extlink FROM categories WHERE catactive=? AND catlink!=? ORDER BY catsort";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ss", $catactive, $catlink);
$stmt->execute();
$result = $stmt->get_result();
while ($cat = $result->fetch_assoc()) {
$resArr[] = $cat;
echo '<h3>'.$cat['name'].'</h3>';
$cities = "SELECT COUNT(a.ad_id) AS ANZ,a.region, b.city, b.citylink FROM ads a, neueorte b WHERE a.zeigen=? AND a.gesperrt=? AND FIND_IN_SET(?, a.portale) AND a.catid=? AND b.po_id=a.region GROUP BY a.region ORDER BY ANZ DESC LIMIT 0,50";
$stmt = $conn->prepare($cities);
$zeigen = 'ja';
$gesperrt = 'no';
$category = $cat['catid'];
$stmt->bind_param("ssss", $zeigen, $gesperrt, $portalnumber, $category);
$stmt->execute();
$r = $stmt->get_result();
while ($city = $r->fetch_assoc()) {
$resArr[] = $city;
echo' '.$city['city'].' <br />';
}
}
}
builtFooter('yes','markt');
I have the tables categories, ads, neueorte. I want built footer links, so I want the categorie as a h3 tag and the cities grouped by city where ads are placed. I hope I made it right, I am new to this page.

Handle empty variable in a prepared statement

Sometimes my script receives a $_POST["is_searchfield"] request from a form. Then I want to use this variable as a part of a "Where" clause of a MySQL query. Otherwise this part of the "Where" clause shouldn't afflict the rest of the query.
For the query I use a prepared statement.
If the $_POST["is_searchfield"] has a value the query works as expected, but if no variable is sent the whole query doesn't give me any results.
How can I achieve that an empty variable doesn't destroy the whole query and only this certain part of the "where" clause will be ignored. Also the prepared statement should continue to work.
I tried to check if the variable is set with !empty but it doesn't change this behavoiur.
$conn = new mysqli("localhost", "xxxx", "xxxx", "xxxx");
$conn->set_charset("utf8");
// Variables to bind
$classid = "4";
if(!empty($_POST["is_searchfield"]))
{
$searchfield = $_POST["is_searchfield"];
}
else {
$searchfield= "";
}
$fileid = "10";
$sqlitemsparse = "SELECT * FROM itemSparse INNER JOIN item ON item.id = itemSparse.id";
$sqlitemsparse .= " WHERE item.ClassID = ?";
$sqlitemsparse .= " AND itemSparse.Display_lang = ?";
$sqlitemsparse .= " AND itemSparse.fileid = ?";
$sqlitemsparse2 = " LIMIT 0, 10";
$stmt = $conn->prepare($sqlitemsparse . $sqlitemsparse2);
$stmt->bind_param('sss', $classid, $searchfield, $fileid);
$stmt->execute();
$resultitemsparse = $stmt->get_result();
$rowsitemsparse = $resultitemsparse->fetch_all(MYSQLI_ASSOC);
The idea is to change the query to match the data provided
$conn = new mysqli("localhost", "xxxx", "xxxx", "xxxx");
$conn->set_charset("utf8");
// Variables to bind
$classid = "4";
$fileid = "10";
if(!empty($_POST["is_searchfield"]))
{
$sqlitemsparse = "SELECT *
FROM itemSparse
INNER JOIN item ON item.id = itemSparse.id
WHERE item.ClassID = ?
AND itemSparse.Display_lang = ?
AND itemSparse.fileid = ?
LIMIT 0, 10";
$stmt = $conn->prepare($sqlitemsparse);
$stmt->bind_param('sss', $classid, $_POST["is_searchfield"], $fileid);
} else {
$sqlitemsparse = "SELECT *
FROM itemSparse
INNER JOIN item ON item.id = itemSparse.id
WHERE item.ClassID = ?
AND itemSparse.fileid = ?
LIMIT 0, 10";
$stmt = $conn->prepare($sqlitemsparse);
$stmt->bind_param('ss', $classid, $fileid);
}
$stmt->execute();
$resultitemsparse = $stmt->get_result();
$rowsitemsparse = $resultitemsparse->fetch_all(MYSQLI_ASSOC);

Database Error HY000

My code working fine , but i got this error :
SQLSTATE[HY000]: General error
I searching on google and someone say that it's may SQLi
What is this ? And how can i fix that ?
thanks and sorry for my poor english
try{
$db_con = new PDO("mysql:host={$db_host};dbname={$db_name}",$db_user,$db_pass);
$db_con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Anti Brute Forced
$stmt = $db_con->prepare("
SELECT * FROM users
");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$users_username = $row["users_username"];
$users_password = $row["users_password"];
$users_wrong_password = $row["users_wrong_password"];
if ($users_wrong_password <= 3 && isset($_GET["username"],$_GET["password"]) && $_GET["username"] == $users_username && $_GET["password"] != $users_password){
$u = $users_wrong_password + 1;
$g = 0;
$g = $_GET['username'];
$stmt = $db_con->prepare("
UPDATE users
SET users_wrong_password = $u
WHERE users.users_username = '$g'
");
$stmt->execute();
}
if ($_GET["username"] == $users_username && $users_wrong_password >= 4){
echo "Your Account Was Banned For 1 Hours";
die;
}
}
$g = $_GET['username'];
$stmt = $db_con->prepare("SELECT * FROM users where users_username = '$g'");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$ss = $row["users_wrong_password"];
}
if($ss <= 3){
$g = 0;
$g = $_GET['username'];
$stmt = $db_con->prepare("
UPDATE users
SET users_wrong_password = 0
WHERE users_username = '{$_GET['username']}'
");
$stmt->execute();
}
// Anti Brute Forced
[Solved]
Edit:
$g = $_GET['username'];
$p = $_GET['password'];
$stmt = $db_con->prepare("
SELECT * FROM users where users_username = '$g' and users_password = '$p'
");
I found this problem in a similar another way
"errorInfo":["HY000"]
How does "HY000" error happen?
It happens when you are updating, deleting or inserting data with PDO, and you try to fetch it's result.
The solution, just do not use fetch or fetchAll methods after executing an updating, deleting or inserting. Surely, it does not make sense to fetch it's result!
Example:
$stmt = $db_con->prepare("
UPDATE users SET name = 'Renato' WHERE ID = 0
");
$stmt->execute();
$stmt->fetch(PDO::FETCH_ASSOC); // The mistake is here, just remove this line
$stmt->fetchAll(PDO::FETCH_ASSOC); // It will cause troubles too, remove it
Solving the problem in a loop
The solution is changing the statement variable name inside loop, or fetch all before starting loop:
Solution: Changing variable name
$stmt = $db_con->prepare("
SELECT * FROM users
");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
// ...
// This is another statment
$another_stmt = $db_con->prepare("
UPDATE users
SET users_wrong_password = $u
WHERE users.users_username = '$g'
");
$another_stmt->execute();
}
Solution: Fetch all data from query before loop
$stmt = $db_con->prepare("
SELECT * FROM users
");
$stmt->execute();
// Everything is fetched here
$results = $stmt->fetchAll(PDO::FETCH_ASSOC)
foreach($results as $row){ // Another way to loop through results
$stmt = $db_con->prepare("
UPDATE users
SET users_wrong_password = $u
WHERE users.users_username = '$g'
");
$stmt->execute(); // Be happy with no troubles
}
I think there are multiple preparations of the same query.
Solution Get the query preparation out of the while.
code:
//... your code
$stmt1 = $db_con->prepare("
UPDATE users
SET users_wrong_password = $u
WHERE users.users_username = '$g'
");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$users_username = $row["users_username"];
$users_password = $row["users_password"];
$users_wrong_password = $row["users_wrong_password"];
if ($users_wrong_password <= 3 && isset($_GET["username"],$_GET["password"]) && $_GET["username"] == $users_username && $_GET["password"] != $users_password){
$u = $users_wrong_password + 1;
$g = 0;
$g = $_GET['username'];
$stmt1->execute();
//...
}

Getting call_user_func_array() to work with prepared sql statements

I have to build up a sql statement and the params from a $place object that has a variable number of properties. When I use prepared sql statements by building the sql statement and params the long and bad practice way it works (returns all the rows from the database that it should):
<?
function buildSQLWhereClause($query, $conn, $place) {
if ($place['suburb']){
if($place['city'] && $place['province'] && $place['country']) {
$query .= "s.country = ? and
s.province = ? and
s.city = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ssss", $place['country'], $place['province'], $place['city'], $place['suburb']);
} else if ($place['province'] && $place['country']) {
$query .= "s.country = ? and
s.province = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $place['country'], $place['province'], $place['suburb']);
} else if ($place['city'] && $place['province']) {
$query .= "s.province = ? and
s.city = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $place['province'], $place['city'], $place['suburb']);
} else if ($place['city'] && $place['country']) {
$query .= "s.country = ? and
s.city = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $place['country'], $place['city'], $place['suburb']);
} else if ($place['city']) {
$query .= "s.city = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['city'], $place['suburb']);
} else if ($place['province']) {
$query .= "s.province = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['province'], $place['suburb']);
} else if ($place['country']) {
$query .= "s.country = ? and
s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['country'], $place['suburb']);
} else {
$query .= "s.suburb = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $place['suburb']);
}
//////////////////////////// NO SUBURB ///////////////////////////////////////////////////
} else if ($place['city']) {
if ($place['province'] && $place['country']) {
$query .= "s.country = ? and
s.province = ? and
s.city = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("sss", $place['country'], $place['province'], $place['city']);
} else if ($place['province']) {
$query .= "s.province = ? and
s.city = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['province'], $place['city']);
} else if ($place['country']) {
$query .= "s.country = ? and
s.city = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['country'], $place['city']);
} else {
$query .= "s.city = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $place['city']);
}
//////////////////////// NO SUBURB OR CITY ////////////////////////////////////////////////////////
} else if ($place['province']) {
if ($place['country']) {
$query .= "s.country = ? and
s.province = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $place['country'], $place['province']);
} else {
$query .= "s.province = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $place['province']);
}
//////////////////////////////// NO SUBURB, CITY, OR PROVINCE ///////////////////////////////
} else if ($place['country']) {
$query .= "s.country = ?";
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $place['country']);
}
return $stmt;
}
function queryDbForProducts($conn, $place)
{
$query = "SELECT p.*, s.*
FROM product p
INNER JOIN product_shop ps
ON ps.p_id = p.p_id
INNER JOIN shop s
ON s.s_id = ps.s_id
WHERE ";
$stmt = buildSQLWhereClause($query, $conn, $place);
$stmt->execute();
$meta = $stmt->result_metadata();
while ($field = $meta->fetch_field()) {
$parameters[] =& $row[$field->name];
}
When I use sql prepared statements by building up the sql statement and params the much better way, it doesn't work:
<?
function buildSQLWhereClause($place) {
$query = "SELECT p.*, s.* FROM product p INNER JOIN product_shop ps ON ps.p_id = p.p_id INNER JOIN shop s ON s.s_id = ps.s_id WHERE ";
$queryParams = [];
$queryParamTypes = "";
$i = 0;
$len = count($place);
foreach ($place as $key => $value) {
if ($i == $len - 1) {
$query .= "$key = ?";
$queryParams[] = $value;
$queryParamTypes .= "s";
} else {
$query .= "$key = ? AND ";
$queryParams[] = $value;
$queryParamTypes .= "s";
}
$i++;
}
return array(
"query" => $query,
"queryParams" => $queryParams,
"queryParamTypes" => $queryParamTypes
);
}
function queryDbForProducts($conn, $place)
{
$queryObject = buildSQLWhereClause($place);
$query = $queryObject['query'];
$queryParams = $queryObject['queryParams'];
$queryParamTypes = $queryObject['queryParamTypes'];
// prepare and bind
$stmt = $conn->prepare($query);
$stmt->bind_param($queryParamTypes, $queryParams);
$stmt->execute();
$meta = $stmt->result_metadata();
Hovering over the $stmt in the debugger shows:
affected_rows:-1
insert_id:0
num_rows:0
param_count:4
field_count:13
errno:2031
error:"No data supplied for parameters in prepared statement"
error_list:array(1)
sqlstate:"HY000"
id:1
No data supplied? Hovering over the $queryParams parameter in the debugger shows:
0:"Grey Lynn"
1:"Auckland"
2:"Auckland"
3:"New Zealand"
So I did provide the query parameters to the $stmt->bind_param() function. Did I provide them in the wrong format?
Hovering over $QueryParamTypes shows:
"ssss"
Hovering over $query shows:
"SELECT p.*, s.* FROM product p INNER JOIN product_shop ps ON ps.p_id = p.p_id INNER JOIN shop s ON s.s_id = ps.s_id WHERE suburb = ? AND city = ? AND province = ? AND country = ?"
How come it works when done with the code at the top of the question and it doesn't work when done with the code without all the is statements?
bind_param does not take an array as an argument, it takes varargs. You will need to use call_user_func_array if you want to call it with a dynamic number of arguments.
i.e.
$params = array_unshift($queryParams, $queryParamTypes);
call_user_func_array(array($stmt, "bind_param"), $params);
The params passed to call_user_func_array, parameter 2, need to be referenced.
This is the working solution:
function makeValuesReferenced($arr){
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
$stmt = $conn->prepare($query);
//$stmt->bind_param($queryParamTypes, $queryParams);
call_user_func_array(array($stmt, 'bind_param'), makeValuesReferenced($queryParams));
$stmt->execute();
As per this answer
Not knowing about the reference thing mucked me around for a long time. Hope this helps some people.

PHP PDO wont update database

i try to use PDO but i get 1,1,1 for result but database wont updated. I dont know whats wrong with my code.
try {$db = new PDO("mysql:dbname=$db_name;host=$db_host", $db_user, $db_pass );}
catch(PDOException $e){echo $e->getMessage();}
$title_insert = $db->prepare("UPDATE topics SET topic_title = ? WHERE id = ?");
$title_insert->bindParam(1, $id);
$title_insert->bindParam(2, $topic_title);
$tag_insert = $db->prepare("UPDATE topics SET topic_tags = ? WHERE id = ?");
$tag_insert->bindParam(1, $id);
$tag_insert->bindParam(2, $topic_tags);
$story_insert = $db->prepare("UPDATE topics SET topic_story = ? WHERE id = ?");
$story_insert->bindParam(1, $id);
$story_insert->bindParam(2, $topic_story);
$id = 1;
$topic_title = "title";
$topic_tags = "tags";
$topic_story = "story";
$result_title = $title_insert->execute();
echo $sonuc_title.',';
$sonuc_tag = $tag_insert->execute();
echo $sonuc_tag.',';
$result_story = $story_insert->execute();
echo $result_story;
Thanks for answers...
Have you tried switching the param numbers?
$title_insert = $db->prepare("UPDATE topics SET topic_title = ? WHERE id = ?");
$title_insert->bindParam(1, $topic_title);
$title_insert->bindParam(2, $id);
Good luck!
PDO Bind param
you should affect your variable before the bind statement :
$id = 1;
$topic_title = "title";
$topic_tags = "tags";
$topic_story = "story";
$title_insert = $db->prepare("UPDATE topics SET topic_title = ? WHERE id = ?");
$title_insert->bindParam(1, $id);
$title_insert->bindParam(2, $topic_title);
$tag_insert = $db->prepare("UPDATE topics SET topic_tags = ? WHERE id = ?");
$tag_insert->bindParam(1, $id);
$tag_insert->bindParam(2, $topic_tags);
$story_insert = $db->prepare("UPDATE topics SET topic_story = ? WHERE id = ?");
$story_insert->bindParam(1, $id);
$story_insert->bindParam(2, $topic_story);
$result_title = $title_insert->execute();
echo $sonuc_title.',';
$sonuc_tag = $tag_insert->execute();
echo $sonuc_tag.',';
$result_story = $story_insert->execute();
echo $result_story;

Categories