i'm making a while loop in php and it all goes well but the problem is that
I don't only want to get the id of the user but also some other stuff that is inside another table, so when I go ahead and make a query inside this while loop and select everything from that second table (where the id is equal to the id of the result from the first query), it only returns 1 result...
So this is the code that I currently have:
public function getFriends($id)
{
global $params;
$get = $this->db->select("{$this->DB['data']['friends']['tbl']}", "*",
array(
"{$this->DB['data']['friends']['one']}" => $id
)
);
if($get)
{
while($key = $get->fetch())
{
$query = $this->db->query("SELECT * FROM {$this->DB['data']['users']['tbl']}
WHERE {$this->DB['data']['users']['id']} = :id",
array(
"id" => $key->{$this->DB['data']['friends']['two']}
)
);
while($row = $query->fetch())
{
$params["user_friends"][] = [
"id" => $key->{$this->DB['data']['friends']['two']},
"name" => $row->{$this->DB['data']['users']['username']},
"look" => $row->{$this->DB['data']['users']['figure']}
];
}
}
}
else
{
$params["update_error"] = $params["lang_no_friends"];
}
}
Thanks in advance!
Please help me out!
In the absence of answers, I don't know what db framework you are using behind the scenese...PDO, mysqli_, or (hopefully not) mysql_. But, in any case, the problem might be that your second query stops the first from continuing. I would use PDO->fetchAll() to get them all...but you say you can't do that...so, looping the first and loading those results into an array is the first thing I would do to see if this is the problem:
public function getFriends($id)
{
global $params;
$get = $this->db->select("{$this->DB['data']['friends']['tbl']}", "*",
array(
"{$this->DB['data']['friends']['one']}" => $id
)
);
$firstResults = array();
if( $get ) {
while( $key = $get->fetch() ) {
$firstResults[] = $key;
}
}
else
{
$params["update_error"] = $params["lang_no_friends"];
}
foreach( $firstResults AS $key )
{
$query = $this->db->query("SELECT * FROM {$this->DB['data']['users']['tbl']}
WHERE {$this->DB['data']['users']['id']} = :id",
array(
"id" => $key->{$this->DB['data']['friends']['two']}
)
);
while($row = $query->fetch())
{
$params["user_friends"][] = [
"id" => $key->{$this->DB['data']['friends']['two']},
"name" => $row->{$this->DB['data']['users']['username']},
"look" => $row->{$this->DB['data']['users']['figure']}
];
}
}
}
If this doesn't work, then we need more data...e.g. what is the query generated? When you run it manually does it return more than one result? If you get rid of the inner-query, does this fix it? etc.
The first step when diagnosing PHP and Mysql issues is to add lines to your code that tell you what each line is doing (declare each time a loop is entered; when each mysql query is run, spit out the query string) so you can narrow down where the problem is. Often this makes you feel stupid in retrospect: "Duh, this query didn't return anything because I formatted the record ID wrong" and so forth.
The code snippet you've provided above isn't super helpful to me. I'm a troubleshooter (not a parser) so I need diagnostic data (not straight code) to be of any more help than this.
Related
I am trying to print my data and encode it into JSON. I'm extracting the data from my MySQL database for a quiz. The data that I am trying to extract 1 question, 1 category and 4 options to make a set of quiz. I think I nearly got it how to make it work but I failed to find out how. This was the result check in this link.
Paste the JSON to this link so that you can easily format it. From that JSON data, I want to output like this for each question:
"What is the approximate number of islands that comprise the Philippines?",
"Philippine Geography",
[
{
"quiz_choice_id":"5",
"choice":"7000",
"is_correct_choice":"1"
},
{
"quiz_choice_id":"6",
"choice":"6000",
"is_correct_choice":"0"
},
{
"quiz_choice_id":"7",
"choice":"8000",
"is_correct_choice":"0"
},
{
"quiz_choice_id":"8",
"choice":"9000",
"is_correct_choice":"0"
}
],
This is my code for that:
<?php
/**
* Created by PhpStorm.
* User: Muhammad
* Date: 19/04/2016
* Time: 00:46
*/
require_once('Database_Connect.php');
$questions_query = "SELECT question, quiz_choice_id, choice ,is_correct_choice, category FROM category_question cq, question q, question_choices qc WHERE q.quiz_question_id = qc.quiz_question_id AND q.cat_ques_id = cq.cat_ques_id LIMIT 10";
$questions_query_result = mysqli_query($con, $questions_query) or die("error loading questions");
$questions_results = array();
encode_result($questions_query_result);
function encode_result($result)
{
//$response = array();
$questions = array();
//$choices = array();
while ($r = mysqli_fetch_array($result)) {
//$response[] = $r;
//$questions = array('question' => $r[0]);
$questions[] = $r['question'];
$questions[] = $r[4];
$choices[] = array('quiz_choice_id' => $r[1], 'choice' => $r[2], 'is_correct_choice' => $r[3]);
$questions[] = $choices;
//array_push($questions, $questions['question']);
//array_push($questions_results, $questions);
}
echo json_encode(array('questions'=>$questions));
}
mysqli_close($con);
The design of the database is this:
I can't find a way to make it work because from the database quiz_choice_id,choice, is_correct_choice are in a different table but I combined all into one table as you can see in my SQL statement $questions_query. Please let me know how can I fix this. Thanks in advance.
Do you want the json to look like this?
[ {
"question" : "What is the approximate number of islands that comprise the Philippines?",
"category" : "Philippine Geography",
"choices" : [
{
"quiz_choice_id":"5",
"choice":"7000",
"is_correct_choice":"1"
},
{
"quiz_choice_id":"6",
"choice":"6000",
"is_correct_choice":"0"
},
{
"quiz_choice_id":"7",
"choice":"8000",
"is_correct_choice":"0"
},
{
"quiz_choice_id":"8",
"choice":"9000",
"is_correct_choice":"0"
}
]
},{
..... // next question
}]
You'll have to do something like this, but I have no idea what the results of the query is.
$questions = array();
while ($r = mysqli_fetch_array($result)) {
$key = $r['quiz_question_id']; // you need a key here that is unique to the question, so i think this will do looking at the schema you posted, this will group them in that segment of the array.
if( !isset( $questions[$key] ) ){
//if we never had this question, create the top level in the results
$questions[$key] = array(
'question' => $r['question'],
'category' => $r['category'],
'choices' => array()
);
}
//add in the choices for this question
//on the next iteration, the key is the same so we only do this part
//and append that rows choices to the previous data using $key to match the question
$questions[$key]['choices'][] = array('quiz_choice_id' => $r['quiz_choice_id'], 'choice' => $r['choice'], 'is_correct_choice' => $r['is_correct_choice']);
}
Make sure to add quiz_question_id to your query if this is the questions id, unique identifier. Essentially this will group them together, as this will be the same for each row with that question's choices.
I added string keys to the output, I wouldn't mix using string keys and numbered index. I hope I mapped them out right.
Also I haven't tested this at all, so sorry if there are any syntax errors.
I am trying to expand the functionality of a dictionary I am building by showing definitions for some of the terms (if a definition exists).
I take the data from the two tables as follows:
$query = $db->query("SELECT * FROM ".DICTIONARY_TABLE." " .
"LEFT JOIN ".DICTIONARY_DEFINITIONS." ON ".DICTIONARY_TABLE.".id = ".DICTIONARY_DEFINITIONS.".term_id ".
"WHERE ".DICTIONARY_TABLE.".".$source." LIKE '%".$keyword."%' ".
"AND ".DICTIONARY_TABLE.".theme_id = ".$selected_theme_id." ".
"ORDER BY ".DICTIONARY_TABLE.".id");
After that, in the while loop, I first get the theme name (from another table), then add the query results to an array:
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
// get theme name
$theme_name = "theme_".$lang;
$theme_query= $db->query("SELECT theme_id,".$theme_name." FROM ".DICTIONARY_THEMES." WHERE theme_id = ".$theme_id."");
$theme_row = $theme_query->fetch(PDO::FETCH_ASSOC);
$theme = $theme_row[$theme_name];
// add all results to an array
$results[] = array(
'english' => $row['english'],
'bulgarian' => $row['bulgarian'],
'english_abbr' => $row['english_abbr'],
'bulgarian_abbr' => $row['bulgarian_abbr'],
'theme' => $theme
);
After that, I try to check if the LEFT JOIN has actually returned any results from the definitions table, and if yes, add those to the array as well - but this is where I fail...
// check if definition exists for this term
if(isset($row['bulgarian_definition'])) {
array_push($results['bulgarian_definition'], $row['bulgarian_definition']);
}
if(isset($row['english_definition'])) {
array_push($results['english_definition'], $row['english_definition']);
}
I've tried all ways I could find to first check if the variables have been defined, and then push them to the $results array. Nothing works.
I don't seem to be able to successfully find out of english_definition and/or bulgarian_definition are set. When I run the query itself in PhpMyAdmin, it works just fine.
The only "solution" I can think of is to scrap the idea of having a separate table for the definitions and just expand the main table, but that's not a great approach I know.
Any insight as to what I am doing wrong will be greatly appreciated. Thanks!
EDIT: I've changed the way elements are added to the array:
// check if definition exists for this term
if(isset($row['bulgarian_definition'])) {
$results['bulgarian_definition'] = $row['bulgarian_definition'];
}
if(isset($row['english_definition'])) {
$results['english_definition'] = $row['english_definition'];
}
And this now does the trick. When I dump the $results array outside of the while loop, both definitions have been added.
However, I now get a large number of Warning: Illegal string offset 'theme' in... and 'english' and 'bulgarian' - this happens below, when I run the $results array in a foreach loop to start printing them:
foreach($results as $result) {
if($theme != $result['theme']) {
$theme = $result['theme'];
$search_results .= "<h3>" . $result['theme'] . "</h3>";
}
if($source == "english") {
foreach ($keywords as $keyword) {
$result['english'] = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223\">" . $keyword . "</span>", $result['english']);
}
No idea yet why this happens, will keep looking.
SECOND EDIT: Decided to put the two definitions directly inside the $results array as follows:
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
// get theme name
$theme_name = "theme_".$lang;
$theme_query= $db->query("SELECT theme_id,".$theme_name." FROM ".DICTIONARY_THEMES." WHERE theme_id = ".$theme_id."");
$theme_row = $theme_query->fetch(PDO::FETCH_ASSOC);
$theme = $theme_row[$theme_name];
// add all results to an array
$results[] = array(
'english' => $row['english'],
'bulgarian' => $row['bulgarian'],
'english_abbr' => $row['english_abbr'],
'bulgarian_abbr' => $row['bulgarian_abbr'],
'theme' => $theme,
'bulgarian_definition' => $row['bulgarian_definition'],
'english_definition' => $row['english_definition']
);
}// end while
This now works just fine. When I dump the array, if no definition exists, I have 'english_definition' => null and if a definition exists, it's there. So far so good.
The new problem is that I can no longer group the results by theme - the theme of the last result found is shown. Which is a different problem altogether. What really irks me is that before I added the definitions, everything worked just fine. You can the working website here.
PROBLEM SOLVED!
Decided against pushing values to the array (as shown above).
Got rid of the extra query within the while loop that gets the theme's name, moving it instead to the query that performs the search. Thus the query itself is:
$query = $db->query("SELECT * FROM ".DICTIONARY_TABLE." " .
"JOIN ".DICTIONARY_THEMES." ON ".DICTIONARY_TABLE.".theme_id = ".DICTIONARY_THEMES.".theme_id ".
"LEFT JOIN ".DICTIONARY_DEFINITIONS." ON ".DICTIONARY_TABLE.".id = ".DICTIONARY_DEFINITIONS.".term_id ".
"WHERE ".DICTIONARY_TABLE.".".$source." LIKE '%".$keyword."%' ".
"ORDER BY ".DICTIONARY_TABLE.".theme_id, ".DICTIONARY_TABLE.".id");
And the while loop is:
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
$theme_name = "theme_".$lang;
// add all results to an array
$results[] = array(
'english' => $row['english'],
'bulgarian' => $row['bulgarian'],
'english_abbr' => $row['english_abbr'],
'bulgarian_abbr' => $row['bulgarian_abbr'],
'theme' => $row[$theme_name],
'bulgarian_definition' => $row['bulgarian_definition'],
'english_definition' => $row['english_definition']
);
}// end while
The website link from above will now load the upgraded search functionality, where definitions will be shown (if they exist). One example word for anyone curious is "worm".
As it turns out, sometimes all it takes to fix a problem is to show it to people and then start thinking about it, as sometimes the solution is right in front of you. Thanks to all who participated!
EDITED: Deleted previous answer since it was incorrect. Will update this answer once I have a solution to the problem. Have not deleted this answer since I haven't found the option that does so. Though sometimes it is fun to take up space and feel important :), don't hate the player, hate the game.
I have a query in which I am tring to put the results in an array.
The query returns all data of the two tables: order and orderdetails:
SELECT orders.*, order_details.* FROM `webshop_orders`
LEFT JOIN `order_details`
ON `orders`.`order_id` = `order_details`.`f_order_id`
WHERE `orders`.`f_site_id` = $iSite_id AND `orders`.`order_id` = $iOrder_id;";
I am trying to found out how to return this data an put them in an array of the following format:
$aOrders = array(
0=>array(Orders.parameter1=>value, orders.parameter2=>value, orders.parameter3=>value, 'orderdetails'=>array(
array(Orderdetails.parameter1=>value, orderdetails.parameter2=>value)));
I currently return every result as an associate array and manually split every variable based on its name using 2 key-arrays, but this seems very 'labor-intensive'?
while($aResults = mysql_fetch_assoc($aResult)) {
$i++;
foreach($aResults as $sKey=>$mValue){
if(in_array($sKey, $aOrderKeys){
$aOrder[$i][$sKey] = $mValue;
} else {
$aOrder[$i]['orderdetails'][$sKey] = $mValue;
}
}
}
EDIT: the function above does not take multiple order-details into consideration, but the function is meant as an example!
Is there an easier way or can I use a better query for this?
You can use the following while loop to fill your array:
$data = array();
while ($row = mysql_fetch_assoc($result)) {
if (!isset($data[$row['order_id']])) {
$order = array('order_id' => $row['order_id'],
'order_date' => $row['order_date'],
/* ... */
'orderdetails' => array());
$data[$row['order_id']] = $order;
}
if (isset($row['order_details_id'])) { // or is it "!= null"? don't know...
$details = array('id' => $row['order_details_id'],
'whatever' => $row['order_details_whatever']);
$data[$row['order_id']]['orderdetails'][] = $details;
}
}
This way you can have multiple orderdetails for one order, they get all added to the ['orderdetails'] field.
Additional notes:
Do not use SELECT *, see the question What is the reason not to use select *? and any other website about this topic.
Do not use the mysql_*() functions (even though I did above for showing the while loop), they are deprecated. Use PDO instead.
I'm trying to do the following:
public function checkResult($table, $appends)
{
$append = null;
foreach ($appends as $key => $val)
$append = " AND `{$key}` = '{$val}'";
$result = $this->fetchObj("
SELECT *
FROM :cms_table
WHERE id :append
", array(
":cms_table" => $table
":append" => $append
));
return ($result ? true : false);
}
But I can't get this working because I don't know how to do this in PDO.
Also when I leave the :append my query isn't working either. It looks like I can't execute a table. When I change :cms_table to the cms_pages (table I need) it works correctly.
I couldn't find a thing about such query's in PDO. Anyone who can help me out?
Don't try to outsmart yourself.
You don't need no checkResult() function, as well as no other function of similar structure.
$sql = "SELECT 1 FROM table WHERE field = ? AND col = ?";
$found = $db->fetchObj($sql, array(1,2));
is all you actually need.
i am tying to do this by a function. i want every item found in the db to be echoed out as a list
eg. item1
item2
item3
item4
i know im missing something but it is puzzling me. for now im only seeing one list and upon
refresh another item shows up replacing the other. plz help and thanks
function get_list() {
$id = mysql_real_escape_string(#$_GET['id']);
$get_list = array();
$bar = mysql_query(" SELECT bar.* FROM bar WHERE bar.b_id = '$id' ORDER BY rand()");
while($kpl = mysql_fetch_assoc($bar)){
$get_list[] = array( 'videoid' => $kpl['videoid'],
'name' => $kpl['name'],
'description' => $kpl['description'],
'type' => $kpl['type'],
'bev' => $kpl['bev'],
);
}
foreach ($get_list as $get_list);
return $get_list;
}
?>
<?php
$gkp_list = gkp_list();
foreach ($gkp_list as $gkp_list);
if (empty($gkp_list)){ echo 'no video'; }
else {
echo '<p>$gkp_list['name']. '<br/></p>';}
?>
There are some major syntax problems there.
function get_list() {
$id = mysql_real_escape_string(#$_GET['id']);
$get_list = array();
$bar = mysql_query(" SELECT bar.* FROM bar WHERE bar.b_id = '$id' ORDER BY rand()");
while($kpl = mysql_fetch_assoc($bar)){
$get_list[] = $kpl;
}
return $get_list;
}
$gkp_list = get_list();
if (empty($gkp_list)) {
echo 'no video';
} else {
foreach ($gkp_list as $gkp_item) {
echo '<p>' . $gkp_item['name']. '<br/></p>';
}
}
?>
The purpose of foreach is to loop over an array and do something with each value. Don't use foreach if you're working with the array as a whole (in this case, returning it)
Foreach doesn't have a semicolon at the end, it typically has an opening curly brace ({).
You don't need to manually copy all of the array indexes in the while loop, because all of the indexes are the same.
The string for the output was formatted wrong, you have to be careful. Use a syntax-highlighting editor.
The two variable names in foreach must be different. One refers to the array, and one refers to the value of that key.