loop through column of a single row - php

I have a table that holds user data in a single row and it looks like this
What I am trying to do is list them in order of their priority so the outcome looks like this
Everything (because its priority is 1)
Something (Because its priority is 2)
Anything (Because its priority is 3)
At present to achieve this I am using else if statement and it is working fine for example
if (Data1_Priority == '1'){
echo Data1
}elseif{
.....
}
I was wondering if it is possible to display the data in order of their priority using some loop rather than if else
I will really appreciate any assistance on how to achieve this.

Do you want to unpivot them and sort them?
select d.*
from (select data1 as data, data1priority as priority from table union all
select data2 as data, data2priority as priority from table union all
select data3 as data, data3priority as priority from table
) d
order by priority;
As a note: having similar column names that only differ by a number is a sign of poor database design. It is usually better to have fewer columns and more rows.

As mentioned by others, you should be doing this in the database (probably with a redesign), but for a php solution, you can create a temporary array indexed by priority, sort on the key, then iterate it:
$row = [
'data1'=>'something',
'data1_priority'=>2,
'data2'=>'anything',
'data2_priority'=>3,
'data3'=>'everything',
'data3_priority'=>1,
];
$temp=[];
for($i=1; $i<(count($row)/2)+1; $i++){
$temp[$row['data'.$i.'_priority']]=$row['data'.$i];
}
ksort($temp);
foreach($temp as $element)
echo $element . '<br>';
Live example: http://codepad.viper-7.com/O3D54e

for ($pri = 1; $pri<=3; $pri++)
{
for($d == 1; $d<=3; $d++)
{
if ($r["Data".$d."_Priority"] == $pri)
{
echo $r["Data".$d];
}
}
}
Untested, but a point in the right direction?

Related

Sums data from an array that has the same id

I have a query about this project that I am doing, I make a query to my two tables and the data that I call in this case is a quantity number for both, the data displayed is the one that has the same id for both tables.
The problem occurs when I pass two identifiers and to those two identifiers I want to add their current amount with the amount obtained from the other table
In general, what I want to do is add the amounts obtained, this is my code that I am working with, I would really appreciate if you can help me solve it or guide me.
$id_servis = [1077,1078];
$sum_quantity_add = Servis_tareas::where('servis_id',$id_servis)->get();
foreach($sum_quantity_add as $sum_add){
$quantity_two[] = $sum_add->quantity;
}
$quantity_actual = Servis::wherein('id',$id_servis)->get();
foreach($quantity_actual as $quantity_act){
$quantity_one[] = $quantity_act->quantity_final;
}
dd($id_servicios,$quantity_one, $quantity_two);
//ERROR
$total[] = $quantity_one + $quantity_two;
//ERROR
if(is_numeric($total) < 0 ){
Servis::wherein('id',$id_servis)->update(['quantity_final' => 0]);
}else{
Servis::wherein('id',$id_servis)->update(['quantity_final' => $total]);
}
In MySql/SQL there is SUM query which handles the addition and they are called Aggregation Functions, and in Laravel there is a Eloquent equivalent of these Laravel Aggregates, using these methods you will be able to count, max, min, avg on the query end rather than in the PHP end.
So, your code will look like
$id_servis = [1077, 1078];
$sum_quantity_add = Servis_tareas::where('servis_id', $id_servis)->SUM('quantity');
$quantity_actual = Servis::wherein('id', $id_servis)->SUM('quantity_final');
$total = $sum_quantity_add + $quantity_actual;
What you are trying is treating array as numeric value and adding it, which is wrong, + operator behaves totally different while you are using with array, it merges the two array, it is different than array_merge too, so i recommend giving this answer a read + operator for array in PHP
UPDATED:
I still don't understand if you want to replace with the SUM from Servis_tareas in the Servis Table or sum the each others quantity and save it, Code below sum the data from both table and save it.
$id_servis = [1077, 1078];
$servisTareas = Servis_tareas::selectRaw("SUM(`quantity`) as total, `servis_id` ")
->where('servis_id', $id_servis)
->groupBy('servis_id')
->having('total', '>', 0)
->get();
$foundId = [];
$servisTotal = Servis::query()->whereIn('id', $id_servis)->pluck('quantity_final', 'id')->toArray();
foreach ($servisTareas as $servisTarea) {
$foundId[] = $servisTarea->servis_id;
$total = $servisTarea->total + ($servisTotal[$servisTarea->servis_id] ?? 0)
Servis::where('id', $servisTarea->servis_id)->update(['quantity' => $total]);
}
if (!empty($foundId)) {
Servis::whereNotIn('id', $foundId)->update(['quantity' => 0]);
}

PHP displays only the first value in a for() loop insinde another foreach() loop

I have small issue with a for() loop that displays values inside another foreach() loop in a dynamic way.
A small background of the code:
The output table is created dynamically based on the values obtain from one mysql query SELECT (which is the 1st select) from 1 column (that has name "coloane") in a table called "categories";
The values stored in the column "coloane" are actually the name of some columns from another table called "articles"
The first mysql select is to obtain the values from the column "coloane" so I can create the second.
After the second table returns rows (num_rows() > 0) I start to create the table.
The table has 2 static columns that are always present, and the rest of the columns are added dynamically based on different criteria.
The plot:
I explode the values obtained from the first select - from the column "coloane" - to make the [th]'s for the table header;
this explode I store it under the variable "$rows_th";
to make the [th]'s for the table header, i use a foreach() loop (and here I also remove any underscores);
after that I proceed to create the [tbody] and the [td]'s using another foreach(), only that this foreach is done for the values of the second select;
inside this foreach() I create another loop, using the for() function on the variable "$rows_th" so the table has the same length;
here the values are combined like this:
'<td id="'.$i.'">'.$values_td[$rows_th[$i]].'</td>';
The main issue is that, using the format listed above, it will only display the first value!
When I tried to verify the "$values_td[$rows_th[$i]]" using the is_string() function, I discovered that the first value is a string, and after that, every other value is not a string...
The test performed:
if (is_string($values_td[$rows_th[$i]]))
print '<td id="'.$i.'">Value found!!!</td>';
} else {
print '<td id="'.$i.'">No luck...</td>';
}
Any ideas on what might be going wrong ?
I know I'm missing something, but I just can't seem to figure it out :-/
The entire code is listed here: http://pastebin.com/4MFifh92
In the mean time, with the help from a friend, I finally found what was going wrong.
The variable turns from string to number because in the table called "categories", the column named "coloane" has the values inside devided by a "," (comma) and a " " (space), like so
------------------------------------------
| coloane |
------------------------------------------
make, model, location, comments, status
------------------------------------------
To fix this, I found out that I can try to do a str_replace in a simple foreach() loop :)
Something like this:
$i=0;
foreach($rows_th as $values_th) {
$i++;
$cols_td = str_replace(' ', '', $values_th);
$actual_value = $values_td->$cols_td;
print '<td id="'.$i.'">'.$actual_value.'</td>';
}
And this did the trick :)
Hope this will help others that came across with issues similar to this :)
Best regards,
Mike
Can't you just do something like:
SELECT * FROM results_query_header_by_cat WHERE `id` = 3;
Then:
SELECT * FROM results_query_content_by_cat WHERE `id_category` = 3;
Then with the results:
echo '[thead]';
foreach ( $results as $result ){
foreach( $result['coloane'] as $header ){
echo '[th]'.$header.'[/th]';
}
}
echo '[/thead][tbody]';
foreach ( $records as $record ){
echo '[tr][td]' .
$result['producator'] . '[/td][td]' .
$result['model'] . '[/td][td]' .
$result['imei'] . '[/td][td]' .
$result['locatie'] . '[/td][/tr]';
}
echo '[/tbody]';
Is that what you're looking for?
e: I haven't tried this but I'd imagine it's something like that. Just:
get the headers by category ID
get the records by category ID.
Echo the first result set as headers with a loop,
echo the second result set as table rows with columns in a loop.

Creating a Chart with PHP and MySql

I have a database with the following table:
id value
-----------
1 yes
2 no
3 no
4 maybe
I'm using some simple php to log the choices entered on a poll website. The user selects a radio box and it is entered into the above table. However, I want to make this a little more flexible. I created a simple backend that allowed an admin user to add or delete poll choices. What would I do to show on the frontend the number of votes for each individual choice, when the number of choices is not constant? I know I could do this easily if the poll choices were static but since the backend user will be changing the choices, how could I dynamically display the results?
I am not really sure what you are asking. Is it COUNT you're looking for?
Don't worry about the choices or the number of choices, grab all the votes/choices and iterate through them and add them to an array indiscriminately: http://codepad.org/LWPyuTqj
$total = array();
$votes = array(1=>'yes',2=>'no',3=>'no',4=>'maybe');
foreach($votes as $vote) {
if (!isset($total[$vote]))
$total[$vote] = 1;
else
$total[$vote] += 1;
}
print_r($total);
I would recommend google graph API for this. It is really easy!
http://code.google.com/apis/chart/interactive/docs/gallery/piechart.html
Generate the code dynamically, using the first example on the link above. First select the values. This assuming there is a question ID so you can relate to the question. In this case id 1.
$result = mysql_query('SELECT value,COUNT(*) as num FROM choises WHERE question_id = 1 GROUP BY value');
Then with PHP loop through the data
$results = array();
while ($row = mysql_fetch_assoc($result)){
$results[$row['value']] = $num;
}
With this you can generate the graph:
echo 'data.addRows('.count($results).');';
$i = 0;
foreach ($results as $value => $num){
echo'
data.setValue('.$i.', 0, "'.$value.'");
data.setValue('.$i.', 1, '.$num.');
';
$i++;
}

How to make a "distinct" detection on a foreach loop

At this time I have this very complex query that I loop through and I get something like this:
List of Challenges:
TEAM A
- Challenge 1
TEAM A
- Challenge 4
TEAM A
- Challege 6
And I want to change to something like:
TEAM A
- Challenge 1
- Challenge 4
- Challenge 6
My question is, since the query is a very complex one, maybe I could do this inside the loop but, if that's the case, how can we achieve something like that?
Can I ask an example case so that I can use, in order to solve this issue?
Thanks a lot,
MEM
UPDATE:
The query is something like this:
Translated:
public function listachallengesPendentes()
{
$select = $this->getAdapter()->select();
$select->from(array("e"=>"teams"),array('name'));
$select->join(array("de"=>"challengeperteam"),"e.cod_team = de.cod_teamFk",array());
$select->join(array("d"=>"challenges"),"d.cod_challenge = de.cod_challengeFk",array('title'));
$select->columns(array("e.cod_team"
,"name_team"=>"e.name"
,"d.cod_challenge"
,"name_challenge"=>"d.title"
,"d.details"
,"d.score"
,"category"=>"d.cod_categoryFk"
,"de.proof"
,"de.date_concluded"
,"de.cod_challenge_team"
));
$select->where("de.status = 0");
$select->order(array('e.cod_team DESC', 'de.cod_challenge_team DESC'));
return $this->getAdapter()->fetchAll($select);
}
So I need to add a distinct some part :s :D ?
The foreach actually is pretty basic:
foreach ($challenges as $d){
//display the name:
echo $d['name_team'];
...
}
UPDATE 2
The clean query (not tested):
SELECT e.name
,d.cod_team
,d.cod_challenge
,d.title
,d.details
,d.score
,de.proof
,de.date_concluded
,de.cod_challenge_team
FROM teams e
INNER JOIN challengeperteam de ON de.cod_teamFk = e.cod_team
INNER JOIN challenges d ON d.cod_challenge = de.cod_challengeFk
WHERE de.status = 0
ORDER BY e.cod_team DESC, de.cod_challenge_team DESC;
Something along the lines of:
$current_team = null;
foreach($challenges as $challenge){
if($current_team != $challenge->team){
$current_team = $challenge->team;
echo $current_team, "\n";
}
echo $challenge->challenge_name, "\n";
}
At a very basic level, ie in the loop, you can just detect if the TEAM A variable is equal to the current (previous) value, and if so, don't print it a second time. This relies on the result set being sorted on the TEAM A column.
However, you can also do this in the SQL query, so if you can provide the current SQL Query, I can explain how you'd update it.
you could store the array results in a multi-dimensional array like so:
$query_Challenges = "SELECT `Team`,`Challenges` FROM YourTable";
$Challenges = mysql_query($query_Challenges, $dbconnection) or die(mysql_error());
$row_Challenges = mysql_fetch_assoc($Challenges);
$challengeResults = array();
do{
if(!array_key_exists($row_Challenges['cod_team'])){
$challengeResults[$row_Challenges['cod_team']] = array();
}
$challengeResults[$row_Challenges['cod_team']][] = $row_Challenges['cod_challenge_team'];
}while($row_Challenges = mysql_fetch_assoc($Challenges));
EDIT
looking at your query statement, the data should be already sorted properly by your ORDER clause, so if you just need not repeatedly print the team as shown in codeblock 2, then something like:
$team = '';
do {
if($team != $row_Challenges['cod_team']){
echo "TEAM $row_Challenges['cod_team']<br/>";
$team = $row_Challenges['cod_team'];
}
echo " - $row_Challenges['cod_challenge_team']<br />";
}while($row_Challenges = mysql_fetch_assoc($Challenges));
you could easily substitute a foreach for the do loop, as long as there is a variable used as the "current team" and an if statement used to say "dont print the next team name unless its different than the current team name"

Creating a tiered commenting system (efficiently with PHP and MySQL [1 table])

I would like to have a comment section with replies to comments. The replies will only go one level. For example.
Parent Comment
-- Here is a reply
-- Here is another reply
-- It won't go further than this one tier
My MySQL looks like this:
comment_id, comment, parents_id
if parents_id is 0, it is the parent. if it has a number, that number will correspond to the comment_id, as it will be its child.
now, i've done this crappy code below, but it seems the second loop messes it up and only displays the first div correctly with its children. i believe it is because i'm calling mysql_fetch_row twice...
$query_show_comments = "SELECT * FROM article_comments WHERE article_id = '$article_id'";
$results_show_comments = mysql_query($query_show_comments);
$num_rows_comments = mysql_num_rows($results_show_comments);
for ($i = 0; $i < $num_rows_comments; $i++) {
$comment = mysql_fetch_row($results_show_comments);
echo "<p>comment_id: $comment[0]</p>";
if ($comment[5] == 0) {
echo <<<_HTML
<div class="dispArticle">
<p><strong>Commenter Name commented # 11/22/10 10:10:10pm</strong></p>
<p>$comment[2]</p>
_HTML;
for ($j = 0; $j < $num_rows_comments; $j++) {
$replies = mysql_fetch_row($results_show_comments);
if ($replies[5] > 0 AND $replies[5] == $comment[0]) {
echo <<<_HTML
<div class="comment"><p><strong>Reply Name replied # 11/22/10 10:10:10pm</strong></p>
<p>child_id: $replies[0]</p>
<p>parent_id: $comment[0]</p>
<p>$replies[2]</p>
</div>
<br />
_HTML;
}
}
}
echo "</div>";
}
Been searching for hours and this is what I've found.
Use multiple tables (would like to keep it in one table so less queries)
Use multiple queries (same as above)
Feed into an array first then sort it all out (what if the comments are long and there are a lot? I just did a query AND had to do more server side processing of feeding it into an array, sorting then displaying...)
The problem is that mysql_fetch_row() will always fetch the next row returned by the query, and that could be in any order. For what you are doing to work, you would need a post to be followed immediately by its child comments every time. This is a shaky solution, so I would suggest you use #3 as it is really the same thing as what you are doing.
I also have a couple of suggestions: use mysql_fetch_assoc() over mysql_fetch_row() and use the names of the columns rather than their numbers as this makes the code much more readable and easier to use. You will have to change your query to order by the ascending parent ID to ensure that all parents are set first. Then:
$query = "query";
$result = mysql_query($query);
$comments = array();
while ($row = mysql_fetch_assoc($result)) {
if ($row['parent_id']) {
$comments[$row['parent_id']]['children'][] = $row;
}
else {
$row['children'] = array();
$comments[$row['comment_id']] = $row;
}
}
Now all of the children are associated with parents. Just iterate through the array.
It's not too hard. You should store all comments in one table and have parent_id
parent_id of 0 means it's a comment, parent_id > 0 would point to id of a message in the same table for which it's a reply.
You would also have article_id, just like in your current example.
The trick you need is to do just one SQL select but reference the same table twice.
You sql will be something like this:
SELECT
M.id as id,
M.id as com_mid,
M.post_subject as com_subject,
M.message_body as com_body,
M2.id as rpl_mid,
M2.post_subject as rpl_subject,
M2.message_body as rpl_body,
M2.parent_id
FROM
MESSAGES AS M
LEFT JOIN MESSAGES as M2 on M2.parent_message_id = M.id
WHERE M.article_id = :aid
AND M.parent_id = 0
ORDER BY com_mid ASC,
rpl_mid ASC
Then once you get result of this sql, you will easily figure out how to handle the result array to display messages and replies
You need a second query. Here's an example TRYING to use your code.
$query_show_comments = "SELECT * FROM article_comments WHERE article_id = '$article_id'";
$results_show_comments = mysql_query($query_show_comments);
$num_rows_comments = mysql_num_rows($results_show_comments);
for ($i = 0; $i < $num_rows_comments; $i++) {
$row_comment = mysql_fetch_row($results_show_comments);
echo "<p>comment_id: $row_comment[0]</p>";
if ($row_comment[5] == 0) {
echo <<<_HTML
<div class="dispArticle">
<p><strong>Commenter Name commented # 11/22/10 10:10:10pm</strong></p>
<p>$row_comment[2]</p>
_HTML;
$query_show_replies = "SELECT * FROM article_comments WHERE parent_id = '$article_id'";
$result_replies = mysql_query($query_show_replies);
while( $row_reply = mysql_fetch_row($results_show_comments) ) )
echo "
<div class=\"comment\"><p><strong>Reply Name replied # 11/22/10 10:10:10pm</strong></p>
<p>child_id: $row_reply[0]</p>
<p>parent_id: $row_reply[1]</p>
</div><br />
";
}
}
echo "</div>";
}
You're doing several things in your code that I don't like to do, not saying it can't be don't that way. My advice is to take a more advanced approach to architecting your web applications:
Use while() loops when reading data from queries, it's more error tolerant
don't use the "echo <<<" blocks because it makes code harder to read
technically speaking, you'll want to use htmlspecialchars on all output to a web page, so the <<< shouldn't be used anyways
better yet, use a template system to extricate your markup (view) from your PHP, conside Smarty because it's easy even if performance isn't quite stellar
in fact, while you're at it, consider abstracting your data code into a separate layer
no matter how you get the data, you shouldn't rely on indexed fields when you're using a SELECT *.. because the order could change. What I mean is, instead of using $comment[0] or $comment[1], use $comment['id'] or htmlspecialchars($comment['text'])

Categories