Fetching inside if statement using PDO - php

Will fetch twice from the same table in same function cause problems?
Im trying to fetch all "items" from the logged user, if the user has no items the function should return false, else, it should return false and echo "nothing", if there are items in the database from the logged user it should return true and echo all the itemnames.
Everything works except the first item gets cutted off, so if user X, has items One, Two, Three, Four, the output will be: TwoThreeFour.
I guess its because im using the Fetch twice from the table, if so, how can i fix it so it works?
Heres the function:
public function myitems() {
$user_user_id = $_SESSION['userSession'];
$stmt = $this->db->prepare("SELECT * FROM item WHERE user_user_id=:user_user_id");
$stmt->execute(array(":user_user_id" => $user_user_id));
if ($itemRow = $stmt->fetch(PDO::FETCH_ASSOC) == 0) {
echo "nothing";
return false;
} else {
while ($itemRow = $stmt->fetch(PDO::FETCH_ASSOC)) {
$item_item_id = $itemRow['item_id'];
$stmt2 = $this->db->prepare("SELECT * FROM picture WHERE item_item_id=:item_item_id");
$stmt2->execute(array(":item_item_id" => $item_item_id));
$imgRow = $stmt2->fetch(PDO::FETCH_ASSOC);
echo $itemRow['itemname'];
}
return true;
}
}

When you fetch once, your pointer will move by one row. So you will not get the first row when iterating by while. You can better fetch all row into a array and count the array to know if data exists. Also I would suggest a JOIN instead of running multiple queries for each item_id. So it can be like this:
$stmt = $this->db->prepare("SELECT * FROM item JOIN picture ON item.item_id = picture.item_item_id WHERE item.user_user_id=:user_user_id");
$stmt->execute(array(":user_user_id" => $user_user_id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (count($rows) == 0) {
echo "nothing";
return false;
} else {
foreach ($rows as $itemRow) {
$item_item_id = $itemRow['item_id'];
//You can get your picture details also from $itemRow
echo $itemRow['itemname'];
}
return true;
}
Note: Use LEFT OUTER JOIN in place of JOIN, if you expect some items which will not have any entry in picture table and you want to get the data for the item at least in that case. (Image fields will provide NULL value here)

Related

echoing a result from the database with php only returns 1 result

I'm trying to get results from a database and return the data to my page.
I have 2 files, findtask, and functions.
In functions I have some code that grabs all my data from the table.
I then used a while loop to grab the stuff if I echo the results from the functions script it returns as it should id 1 2 and 3, my issue starts when trying to get the result from findtask script that only gets last result.
<?php
public function ShowOpenTasks ()
{
//i leave usersemail blank, because i only want tasks to show on this page if there not assigned.
$query = "SELECT * FROM `tasks` WHERE `usersemail` = ''";
if(!$result = mysqli_query($this->db, $query)) {
exit(mysqli_error($this->db));
}
$data = [];
if(mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) {
$data = $row;
echo $data['id'];
}
}
return $data;
}
?>
My findtask page is
require __DIR__ . '/lib/functions.php';
$app = new FunctionClass();
$task = $app->ShowOpenTasks();
echo $task['id'] //id being the name of the id table of the task.
This one will only turn the last id for some reason.
What is wrong and how can this be fixed?
It will only return last id since you are setting data to equal row
$data = $row;
So each row you replace it with the last one.
I guess you want an array instead, so you could do:
$data[] = $row;
then to print out all tasks:
$task = $app->ShowOpenTasks();
print_r($task);
This would give you an array of results.

Pushing values and keys to an multidimensional array from the database inside a foreach loop without repetitions

I'm trying to combine two tables from a database, and based on my first one, I want to retrieve some value from the other one, and add them to an array.
Here's my problem:
My first database looks like that:
FIRST TABLE:
id, credit_type, association_name, address, city, province, postal_code, country, cycle_type, cycle_begin, cycle_months
My second database instead looks like that:
SECOND TABLE:
id, association_id, designation_name
The id in my first table matches the association_id in my second table so I don't need an INNER JOIN.
My approach is the following:
<?php
public function my_function()
{
$sql = ee()->db->select('*')->from('first_table')->get();
$data['database'] = [];
if ($sql->num_rows() > 0)
{
foreach($sql->result_array() as $row)
{
$id[] = $row['id'];
$data['database'][] = $row;
}
}
foreach ($data['database'] as $key => $value) {
$association_query = ee()->db->query("SELECT * FROM second_table WHERE id = $id");
foreach($association_query->result_array() as $row_two)
{
if ($association_query->num_rows() > 0)
{
$data['database'][$key]['associations'][] = $row_two['designation_name'];
}
}
}
return ee()->load->view('index', $data, true);
}
?>
The sintax ee()->db->select('*') is a prepared statment from expression engine and it's equal to SELECT * FROM first_table (sanitaized).
So as you can see, I try to pass the value $id, which is an array, to my query. The thing is that as soon as I push the value like that $id[] = $row['id'] I create a nice array, but when I loop through my foreach loop, it multiplies my array in many other arrays so I'm not able to run my query, even if I'm technically in a foreach loop.
Plus, as soon as I try to push the result of my query in my array, let's say changing the id in a static id for instance id=3, I obtain a really weird result, like so many arrays repeated with 1 value, 2 value, 3 value and so on, when I'd like to push my key 'association' only where it is presented in the other table.
If you won't do it on SQL, at least don't execute the second query so many times.
<?php
public function my_function()
{
$assocs = array();
$data = array('database' => array());
$association_query = ee()->db->query("SELECT * FROM second_table");
if ($association_query->num_rows() > 0) {
foreach($association_query->result_array() as $row) {
$assocs[$row['association_id'][] = $row['designation_name'];
}
}
$sql = ee()->db->select('*')->from('first_table')->get();
if ($sql->num_rows() > 0) {
foreach($sql->result_array() as $row) {
$id_check = $row['id'];
if (isset($assocs[$id_check])) {
$row ['associations'] = $assocs[$id_check] ;
}
$data['database'][] = $row;
}
}
return ee()->load->view('index', $data, true);
}
?>
Regards

PDO Foreach fetch loop returns first row with specific id and rest as false

I have problem where function is returning objects as false. This function first fetches list of all users in specific group then uses that array to fetch every message that each user has posted and should return all messages as one big message array. Feel free to correct title.
public function listMessages($group_id){
$db = initDb();
$getGroupUsers = $db->prepare("SELECT user_id FROM in_group WHERE group_id = :group_id");
$getGroupUsers->bindParam(":group_id", $group_id, PDO::PARAM_INT);
$getGroupUsers->execute();
$users = $getGroupUsers->fetchAll(PDO::FETCH_ASSOC);
$messages = array();
foreach ($users as $item) {
$getMessage = $db->prepare("SELECT * FROM task_messages WHERE user_id = :user_id ORDER BY visited ASC");
$getMessage->bindParam(":user_id", $item['user_id'], PDO::PARAM_INT);
$getMessage->execute();
if($getMessage->rowCount() > 0){
$message = $getMessage->fetchObject();
array_push($messages, $message);
}
}
return json_encode($messages);
}
But for some reason it only fetches one message per each user. I tested this by adding 3 messages from same user and the calling this function.
But if I add message from another user
Here is my database shown as image below
The docs say for PDOStatement::fetchObject:
Returns an instance of the required class with property names that correspond to the column names or FALSE on failure.
Saying it returns an instance of a class (stdclass in your case) but nothing about multiple instances or an array. You probally would have to loop over the result set till false is returned by fetchObject. Or use fetchAll like you do in the query above.
http://php.net/manual/en/pdostatement.fetchobject.php
Okay, I figured it out! All I had to do is to loop users messages array once they were fetched and then push each of those separately into another array that got returned in the end.
while($row = $getMessage->fetchObject()){
array_push($messages, $row);
}
Here is the complete function.
public function listMessages($group_id){
$db = initDb();
$getGroupUsers = $db->prepare("SELECT user_id FROM in_group WHERE group_id = :group_id");
$getGroupUsers->bindParam(":group_id", $group_id, PDO::PARAM_INT);
$getGroupUsers->execute();
$users = $getGroupUsers->fetchAll(PDO::FETCH_ASSOC);
$messages = array();
foreach ($users as $item) {
$getMessage = $db->prepare("SELECT * FROM task_messages WHERE user_id = :user_id ORDER BY visited ASC");
$getMessage->bindParam(":user_id", $item['user_id'], PDO::PARAM_INT);
$getMessage->execute();
if($getMessage->rowCount() > 0){
while($row = $getMessage->fetchObject()){
array_push($messages, $row);
}
}
}
return json_encode($messages);
}
Now returned array looks like this:

PHP array not updating

There is probably something dumb I am doing wrong here.
public function get_scores($id)
{
$results = array();
$sql = "SELECT * FROM scores WHERE comp_id = $id";
$rows = $this->db->query($sql)->result();
foreach($rows as $row) {
if($row->confirmed_id) {
$results[$row->uid] += $row->score;
}
}
sort($results);
return $results;
}
So basically what I am trying to do is add all of the users scores in the database and return them in order of rank. confirmed->id is just a check to make sure the score has been confirmed (and thus is addable to their total score). I am basically trying to just make an associative array where the key is the users ID, and the score of each question they have in the database is added on. The query works fine, and $row-uid and $row->score both return the correct thing for every row, but $results[] never has anything added to it. If I even change it just to something silly like $results[3] = 0 at top, and then $results[3]++ or += 1 in the for loop, it doesn't add anything to $results[3].
EDIT: Problem solved. Indeed was something dumb -- confirmed_id was set to null by my partner when he reran our database after I had previously set it all to 1. Thanks guys :)
You are adding to $results[something] before it exists. You need to create it in the first case and then only increment it once it exists.
You need to remove the "+=" operation from the code. Check with this.
public function get_scores($id)
{
$results = array();
$sql = "SELECT * FROM scores WHERE comp_id = $id";
$rows = $this->db->query($sql)->result();
foreach($rows as $row)
if($row->confirmed_id)
$results[$row->uid] = $row->score;
sort($results);
return $results;
}
Your previous operation is similar to
$results[$row->uid] = $results[$row->uid] + $row->score;
So it will not add values to your row.

Can't print all rows and columns from table

This might be one easy question.
I have this table:
Table Image
bairro = neighborhood / preco = price
This is a reference table with prices.
I'm trying to print a table with the neighborhood and the price, but it's not happening as I'd like:
ProblematicTable
As you guys can see, each value is being printed 3 times!
The code is this:
function getInfo()
{
$this->sql = "SELECT * FROM deliverypricestable";
$this->query = $this->mysqli->query($this->sql);
while($this->result = $this->query->fetch_assoc())
{
foreach ($this->result as $key)
{
echo "<tr><td>".$this->result["bairro"]."</td>";//neighborhood
echo "<td>".$this->result["preco"]."</td></tr>";//price
}
}
I know this problem is probably related with the numbers of column on the deliverypricestable, but I'm just learning to code, and lil lost, please help me!
function getInfo()
{
$query = "SELECT * FROM deliverypricestable";
if ($result = $mysqli->query($query)) {
/* fetch associative array */
while ($row = $result->fetch_assoc()) {
echo "<tr><td>".$query->result["bairro"]."</td>";//neighborhood
echo "<td>".$query->result["preco"]."</td></tr>";//price);
}
/* free result set */
$result->free();
}
/* close connection */
$mysqli->close();
}
You might find - http://php.net/manual/en/mysqli.query.php - useful for documentation on what you are trying to do.
There's no reason to loop twice. The while loop will execute while there is a new row. This new row is stored in $this->result.
function getInfo()
{
$this->sql = "SELECT * FROM deliverypricestable";
$this->query = $this->mysqli->query($this->sql);
while($this->result = $this->query->fetch_assoc()) {
echo "<tr><td>".$this->result["bairro"]."</td>";//neighborhood
echo "<td>".$this->result["preco"]."</td></tr>";//price
}
}
What your code is doing is looping through all the rows and then for each row, you're looping through all the keys (columns) belonging to the row. You have 3 columns and so for each row, you print the values 3 times.

Categories