I have a table which looks something like the following (first row is columns):
|section | col1 | col2 |
|----------------------|
|bananas | val | val2 |
|----------------------|
|peaches | val | val2 |
With some code to check if a section value matches up with one of the values in an array:
$sectionscope = Array('bananas', 'apples');
$sections = mysql_query("SELECT section FROM table WHERE col1=val AND col2=val2");
if (mysql_num_rows($sections)) {
$i = 0;
while ($row = mysql_fetch_array($sections)) {
if (in_array($row[$i], $sectionscope)) {
$section = $sectionscope[array_search($row[$i], $sectionscope)];
$section_is_valid = 1;
}
$i++;
}
}
If I echo the output from the while loop using echo $row[$i], it gives me: bananas
Doing the select from PHPmyadmin works fine
Can you tell me what I'm doing wrong here?
Thanks,
SystemError
Why are you incrementing $i in the while loop. Your query will return two rows and when you loop through the results, you can access the section value using $row[0] each time.
while ($row = mysql_fetch_array($sections)) {
echo $row[0];
}
This will print bananas and peaches.
In your code, when you enter the while loop second time, you are trying to retrieve section value using $row[1] (since your $i has incremented to 1), which will be null since your query result only contains one column.
Related
I am a newbie to PHP and I am stuck at a certain point. I tried looking up a solution for it however, I didn't find exactly what I need.
My goal is to create a leaderboard, in which the values are displayed in descending order plus the rank and score are displayed. Furthermore, it should also display whether or not a tie is present.
The database should look like this:
+---------+------+----------------+-------+------+
| user_id | name | email | score | tied |
+---------+------+----------------+-------+------+
| 1 | SB | sb#gmail.com | 1 | 0 |
+---------+------+----------------+-------+------+
| 2 | AS | as#web.de | 2 | 0 |
+---------+------+----------------+-------+------+
| 3 | BR | br#yahoo.com | 5 | 1 |
+---------+------+----------------+-------+------+
| 4 | PJ | pj#gmail.com | 5 | 1 |
+---------+------+----------------+-------+------+
And the outputted table should look something like this:
+------+-------------+-------+------+
| rank | participant | score | tied |
+------+-------------+-------+------+
| 1 | BR | 5 | Yes |
+------+-------------+-------+------+
| 2 | PJ | 5 | Yes |
+------+-------------+-------+------+
| 3 | AS | 2 | No |
+------+-------------+-------+------+
| 4 | SB | 1 | No |
+------+-------------+-------+------+
I managed to display the rank, participant and the score in the right order. However, I can't bring the tied column to work in the way I want it to. It should change the value, whenever two rows (don't) have the same value.
The table is constructed by creating the <table> and the <thead> in usual html but the <tbody> is created by requiring a php file that creates the table content dynamically.
As one can see in the createTable code I tried to solve this problem by comparing the current row to the previous one. However, this approach only ended in me getting a syntax error. My thought on that would be that I cannot use a php variable in a SQL Query, moreover my knowledge doesn't exceed far enough to fix the problem myself. I didn't find a solution for that by researching as well.
My other concern with that approach would be that it doesn't check all values against all values. It only checks one to the previous one, so it doesn't compare the first one with the third one for example.
My question would be how I could accomplish the task with my approach or, if my approach was completely wrong, how I could come to a solution on another route.
index.php
<table class="table table-hover" id="test">
<thead>
<tr>
<th>Rank</th>
<th>Participant</th>
<th>Score</th>
<th>Tied</th>
</tr>
</thead>
<tbody>
<?php
require("./php/createTable.php");
?>
</tbody>
</table>
createTable.php
<?php
// Connection
$conn = new mysqli('localhost', 'root', '', 'ax');
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// SQL Query
$sql = "SELECT * FROM names ORDER BY score DESC";
$result = $conn->query("$sql");
// Initalizing of variables
$count = 1;
$previous = '';
while($row = mysqli_fetch_array($result)) {
$current = $row['score'];
$index = $result['user_id']
if ($current == $previous) {
$update = "UPDATE names SET tied=0 WHERE user_id=$index";
$conn->query($update);
}
$previous = $current;
?>
<tr>
<td>
<?php
echo $count;
$count++;
?>
</td>
<td><?php echo $row['name'];?></td>
<td><?php echo $row['score'];?></td>
<td>
<?php
if ($row['tied'] == 0) {
echo 'No';
} else{
echo 'Yes';
}
?>
</td>
</tr>
<?php
}
?>
I think the problem is here
$index = $result['user_id'];
it should be
$index = $row['user_id'];
after updating tied you should retrieve it again from database
So I solved my question by myself, by coming up with a different approach.
First of all I deleted this part:
$current = $row['score'];
$index = $result['user_id']
if ($current == $previous) {
$update = "UPDATE names SET tied=0 WHERE user_id=$index";
$conn->query($update);
}
$previous = $current;
and the previous variable.
My new approach saves the whole table in a new array, gets the duplicate values with the array_count_values() method, proceeds to get the keys with the array_keys() method and updates the database via a SQL Query.
This is the code for the changed part:
// SQL Query
$sql = "SELECT * FROM names ORDER BY score DESC";
$result = $conn->query("$sql");
$query = "SELECT * FROM names ORDER BY score DESC";
$sol = $conn->query("$query");
// initalizing of variables
$count = 1;
$data = array();
// inputs table into an array
while($rows = mysqli_fetch_array($sol)) {
$data[$rows['user_id']] = $rows['score'];
}
// -- Tied Column Sort --
// counts duplicates
$cnt_array = array_count_values($data);
// sets true (1) or false (0) in helper-array ($dup)
$dup = array();
foreach($cnt_array as $key=>$val){
if($val == 1){
$dup[$key] = 0;
}
else{
$dup[$key] = 1;
}
}
// gets keys of duplicates (array_keys()) and updates database accordingly ($update query)
foreach($dup as $key => $val){
if ($val == 1) {
$temp = array_keys($data, $key);
foreach($temp as $k => $v){
$update = "UPDATE names SET tied=1 WHERE user_id=$v";
$conn->query($update);
}
} else{
$temp = array_keys($data, $k);
foreach($temp as $k => $v){
$update = "UPDATE names SET tied=0 WHERE user_id=$v";
$conn->query($update);
}
}
}
Thank you all for answering and helping me get to the solution.
instead of the update code you've got use something simular
$query = "select score, count(*) as c from names group by score having c > 1";
then you will have the scores which have a tie, update the records with these scores and your done. Make sure to set tie to 0 at first for all rows and then run this solution
UPDATE for an even faster solution sql based:
First reset the database:
$update = "UPDATE names SET tied=0";
$conn->query($update);
All records have a tied = 0 value now. Next update all the records which have a tie
$update = "update docs set tied = 1 where score IN (
select score from docs
group by score having count(*) > 1)";
$conn->query($update);
All records with a tie now have tied = 1 as we select all scores which have two or more records and update all the records with those scores.
I have a dynamic Matrix box where users can unlimited drugs, the data comes through like this:
[addindividuals] => [{"Drug":"Calpol","Strength":"100mg","Form":"Liquid","Quantity":"1"},{"Drug":"Paracetamol","Strength":"200mg","Form":"Tablet","Quantity":"16"}]
What I'm trying to achieve is to have each line inserted into a new row (MySQL) and inserts into their relevant columns like so:
Columns: | Drug | Strength | Form | Quantity
Row1 | Calpol | 100mg | Liquid | 1
Row2 |Paracetamol | 200mg | Tablet | 16
I'm guessing its using the exploded function> (I'm a novice) and then sql to insert the strings?
If you have the values as a json string collection, First you need to explode then the string then use a for each to loop through each string then use another for each to make single row. Please have a below code this may help you.
$addindividuals = '{"Drug":"Calpol","Strength":"100mg","Form":"Liquid","Quantity":"1"},{"Drug":"Paracetamol","Strength":"200mg","Form":"Tablet","Quantity":"16"}';
$exploded_array = explode('},',$addindividuals);
$final_query = "INSERT INTO `table_name` (`Drug`,`Strength`,`Form`,`Quantity`) VALUES ";
$exploded_array[0] = $exploded_array[0].'}';
foreach($exploded_array as $exploded_element)
{
$single_row = '(';
$json_decode = json_decode($exploded_element,true);
foreach($json_decode as $key => $value)
{
$single_row .= "'$value',";
}
$single_row = substr($single_row,0,-1);
$single_row .= '),';
$final_query .= $single_row;
}
$final_query = substr($final_query,0,-1);
echo $final_query;
Mytable:
+-----+-----------+
| id | word |
|-----|-----------|
| 1 | test1 |
| 2 | test2 |
| 3 | test3 |
+-----+-----------+
Mysql:
while($end = mysql_fetch_assoc($result)){
echo $end["word"].' - ';
}
output:
test1 - test2 - test3
PDO:
$result = $sth->fetchAll();
print_r($result);
output: It is two nested arrays, and if I want to select one record, I should do something like this:
echo $result[0][word]; // output=test1
echo $result[1][word]; // output=test2
echo $result[2][word]; // output=test3
Now I want to know, Is there any trick to let me echo all records of a column in PDO ?
Edit:
How can I echo my data as not manually. There is manually:
echo $result[0][word]; // output=test1
echo $result[1][word]; // output=test2
echo $result[2][word]; // output=test3
So what should I do for 1000 rows ? Surely I should not do this:
echo $result[0][word]; // output=test1
echo $result[1][word]; // output=test2
.
.
.
echo $result[999][word]; // output=test1000
Any offer?
PDO equivalent of mysql_fetch_assoc is fetch: http://php.net/manual/en/pdostatement.fetch.php
fetchAll does something like:
$result = array();
while($end = mysql_fetch_assoc($result)){
$result[] = $end;
}
print_r($result);
So your code in PDO will look like this:
while($end = $sth->fetch()) {
echo $end["word"].' - ';
}
fetch() returns ONE row of data, which will be an array of fields.
fetchAll() returns ALL rows of data, so you get an array of arrays of fields.
The keys represent the rows(zero based) and the subarray hold the column values with column name as the key.
I have an array like this.
$array[0] = 'email1';
$array[1] = 'email2';
$array[2] = 'email3';
$array[3] = 'mobile1';
$array[4] = 'mobile2';
$array[5] = 'mobile3';
$array[6] = 'email1_c';
$array[7] = 'email2_c';
$array[8] = 'email3_c';
$array[9] = 'mobile1_c';
$array[10] = 'mobile2_c';
$array[11] = 'mobile3_c';
Now i want to dispay a table like this
--------------------------------
email1 | email1_c
email2 | email2_c
email3 | email3_c
mobile1 | mobile1_c
mobile2 | mobile2_c
mobile3 | mobile3_c
Now when i loop through the array i get this
--------------------------------
email1 | email2
email3 | mobile1
mobile2 | mobile3
email1_c | email2_c
email2_c | mobile1_c
mobile1_c | mobile3_c
Now this is not what i want and i know simple looping wont do what i want.
So is there any alternative way to achieve this.
Note : The data given is only sample data. I am actually working in a pre-defined
template in wordpress and wordpress simply throw me an object so i can use it. In
the backend i have tried everything even sorting but i get the data like above.
I need alternative so i can change easily and i dont want to modify default files.
It appears that it depends on an offset value. As you have it shown that value would be six:
$html = "<table>\n";
$offset = 6;
for ($i=0; $i<=5; $i++){
$html .= "<tr><td>".$array[$i]."</td><td>".$array[$i + $offset]."</td></tr>\n";
}
$html .= "</table>\n";
Depending on what you need you might need to dynamically calculate the offset. For example:
$offset = count($array)/2;
For example I have the following MySQL table:
parent_id | child_id
---------------------
1 | 4
1 | 3
1 | 5
2 | 8
3 | 7
I want to print out the parent and all its children in a format like below:
parent | child
---------------------
| 4
1 | 3
| 5
---------------------
2 | 8
---------------------
3 | 7
Basically I just want to display the parent ONCE(Distinct) and list out all its children with PHP. Is it possible to retrieve the above result with just ONE SQL query? I can get the above result if I first query the parents and then recursively query the children using the parent ids but that would be alot more SQL queries hitting the DB.
Or, do I retrieve the result containing every parent_id & children_id and achieve the above result in PHP by using arrays. If so, please tell me how.
Yes. Select normally and use the parents as keys in an array.
//Query normally
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$result[$row["parent_id"]][] = $row["child_id"];
}
Or something similar.
EDIT
The display part would look something like this:
<?php
$result = array(
1 => array(4, 3, 5),
2 => array(8),
3 => array(7)
); //Assuming you get a resultset like this.
$rowIsOpened = false; //Indicates whether a row is currently opened.
//I'm using $rowIsOpened because the row immediately after the rowspanned cell shouldn't be closed.
echo <<<HTML
<table>
<thead>
<tr>
<th>Parent</th>
<th>Children</th>
</tr>
</thead>
<tbody>
HTML;
//Echo a bunch of HTML before actually looping
foreach ($result as $parent => $children) {
echo "<tr>";
echo "<td rowspan=";
echo count($children); //Span over <how many children are> rows
echo ">$parent</td>";
$rowIsOpened = true; //Row is opened
foreach ($children as $child) {
if (!$rowIsOpened) {
echo "<tr>";
} //Only open a row if row is not opened
echo "<td>$child</td>";
echo "</tr>";
$rowIsOpened = false; //Row is now closed. Ready for next iteration.
}
}
//Close the table tags etc.
echo <<<HTML
</tbody>
</table>
HTML;