Database data in PHP array - php

I have a table in phpmyadmin that stores an 'id' (auto inc), 'title' and a 'date'.
I have a webpage where I display the 10 latest items (I simply order by ID).
On that page I print the title and the date. My wish is to also display the number of the posted item, so the first posted item is 1, the second is 2, etc. I cannot simply print the ID from the database because if I delete a row, the numbers aren't straight anymore.
My idea was to put all the data in an array but I have no clue what the best way to do this is and how I could print that item number. So for example when I want to display the 54th item I can easily print $items[54][id] or something and it will show me the number 54 and to display the title I print $items[54][title].
I don't know if there are simpler methods, plus arrays always start at 0, but my items must start at 1.
Besides this page that shows the 10 latest items, there is another page where it gets the title of the item out of the URL. How will I be able to search the title in the array and display the data the same way but only for that requested title?
Thanks in advance!

"SELECT COUNT(id) as cnt FROM mytable";
you can select the count of all database entries.
and then assign it to your iterator
$i = $row['cnt']; // this will hold the ammount of records e.g. 21
// other query
while($row = mysql_fetch_assoc($result)) {
echo $i;
$i--; // this will decrement on every iteration 21, 20 , 19, and so on.
}

First off. I would add a timestamp field to the database and order by that instead as it feels overall more reliable and gives you additional details which may prove handy later.
To create the multidimensional array I would do something like:
$result = mysql_query(...);
$items = array();
while($item = mysql_fetch_assoc($result)) {
$items[] = $item;
}
Now $items[12] for example would give you item number 13 (since it's 0-indexed).
Lastly, to select only the item with a specific title I would use a query which included a WHERE clause, like
"SELECT ... FROM ... WHERE title = '".$title."'"
It's very important to sanitize this variable before using it in the query though.
You can read more about MySQL on a lot of places. A quick googling gave me this: http://www.tutorialspoint.com/mysql/index.htm

You should learn PHP before starting to program in PHP ;) Read and work through the PHP manual and some tutorials!
As to your question it is a simple loop you want to do. One way of doing it as an example.
Fetch the 10 last items from the database in any way you like, following some code, partly pseudo-code.
$markup = '';
for ($i=1; $i<=count($items); $i++)
{
$markup .= 'Item ' . $i . ': ' . $items['date'] . ' - ' . $items['title'];
$markup .= 'read more';
$markup .= PHP_EOL;
}
echo $markup;

I don't know how you print out your data exactly, but I assume there is a loop in there. Simply set a counter that increments by one at every row and print its value.
As for the title search, you'll have to run another query with a WHERE title = '$title' condition, but beware of SQL injection.

Related

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.

What is my last row_number in mysql query?

I have a query like this:
$sql = "SELECT * FROM doctors WHERE city ='$city' LIMIT 10 ";
$result = $db->query($sql);
And I show the result like this :
while($row = $result->fetch_object()){
echo $row->city;
}
The Problem :
Mysql , will search through my database to find 10 rows which their city field is similar to $city.
so far it is OK;
But I want to know what is the exact row_number of the last result , which mysql selected and I echoed it ?
( I mean , consider with that query , Mysql selected 10 rows in my database
where row number are:
FIRST = 1
Second = 5
Third = 6
Forth = 7
Fifth = 40
Sixth = 41
Seventh = 42
Eitghth = 100
Ninth = 110
AND **last one = 111**
OK?
I want to know where is place of this "last one"????
)
MySQL databases do not have "row numbers". Rows in the database do not have an inherent order and thereby no "row number". If you select 10 rows from the database, then the last row's "number" is 10. If each row has a field with a primary id, then use that field as its "absolute row number".
You could let the loop run and track values. When the loop ends, you will have the last value. Like so:
while($row = $result->fetch_object()){
echo $row->city;
$last_city = $row->city;
}
/* use $last_city; */
To get the row number in the Original Table of the last resultant (here, tenth) row, you could save the data from the tenth row and then, do the following:
1. Read whole table
2. Loop through the records, checking them against the saved data
3. Break loop as soon as data found.
Like So:
while($row = $result->fetch_object()){
echo $row->city;
$last_row = $row;
}
Now, rerun the query without filters:
$sql = "SELECT * FROM doctors";
$result = $db->query($sql);
$rowNumber = 0;
while($row = $result->fetch_object()) {
if($row == $last_row) break;
$rowNumber++;
}
/* use $rowNumber */
Hope this helps.
What you can do is $last = $row->id; (or whatever field you want) inside your while loop - it will keep getting reassigned with the end result being that it contains the value of the last row.
You could do something like this:
$rowIndex = 0;
$rowCount = mysqli_num_rows($result);
You'd be starting a counter at zero and detecting the total number of records retrieved.
Then, as you step through the records, you could increment your counter.
while ( $row = $result->fetch_object() ) {
$rowIndex++;
[other code]
}
Inside the While Loop, you could check to see whether the rowIndex is equal to the rowCount, as in...
if ($rowIndex == $rowCount) {
[your code]
}
I know this is a year+ late, but I completely why Andy was asking his question. I frequently need to know this information. For instance, let's say you're using PHP to echo results in a nice HTML format. Obviously, you wouldn't need to know the record result index in the case of simply starting and ending a div, because you could start the div before the loop, and close it at the end. However, knowing where you are in the result set might affect some styling decisions (e.g., adding particular classes to the first and/or last rows).
I had one case in which I used a GROUP BY query and inserted each set of records into its own tabbed card. A user could click the tabs to display each set. I wanted to know when I was building the last tab, so that I could designate it as being selected (i.e., the one with the focus). The tab was already built by the time the loop ended, so I needed to know while inside of the loop (which was more efficient than using JavaScript to change the tab's properties after the fact).

Parsing one col of multiple rows php

I have e.g. the following data returned from a query, each name is an item:
id name comment
1 FF hey
1 FF hey back!
2 LL
3 PP i think its great!
3 PP me too
3 PP I'm not sure
4 TT
5 II
6 KK yesterday is the new tomorrow
When I display it, each 'item' has an id and are displayed in DIVs use LI.
As you can see though there are multiple comments sometimes for an 'item', each on a separate line
What I want to do is display each item and then show comments under each item if there are any. So, i can't group by anything at query stage as the comment section is unique, but need to group at display stage
So currently have:
while ($row = mysql_fetch_array($result)){
echo '<li><div class=className><div class=itemName>'.$row[name].'</div>';
if($row[comment]){
echo '<div class=newRow>'.$row[comment].'</div>';
}
echo '</div></li>';
}
Now, this is no good because this will produce multiple displays for the same item with one comment under each.
Can I do this or should I bring in the data differently?
The ideal result is e.g.
FF LL PP etc etc etc
hey i think its great!
hey back! me too
I'm not sure
You can use GROUP_CONCAT() on your mysql query to group all the comments together for each name
SELECT id, name
GROUP_CONCAT(comment) AS comment
FROM table
GROUP BY name;
then explode() the $row[comment] in your php code
while ($row = mysql_fetch_array($result)){
echo '<li><div class=className><div class=itemName>'.$row['name'].'</div>';
if($row['comment'] != ""){
$comments = explode(",",$row['comment']);
foreach($comments as $comment){
echo '<div class=newRow>'.$comment.'</div>';
}
}
echo '</div></li>';
}
Edit
Thanks to #CBroe, I now know that GROUP_CONCAT() has a group_concat_max_len default of 1024. You will want to increase this before running the GROUP_CONCAT() query -
SET [GLOBAL | SESSION] group_concat_max_len = 10240; // must be in multiples of 1024
SELECT id, name
GROUP_CONCAT(comment) AS comment
FROM table
GROUP BY name;
you will also need to be aware of max_allowed_packet as this is the limit you can set var_group_concat_max_len to.
note: mysql_query() does not allow multiple queries, so you will need to do 2 mysql_query(), and you can use SET SESSION ... so that all queries in your current session have that max_len. It would be better to change from mysql_ functions (which are depreciated) and change to mysqli_ or PDO as they offer multiple query option. also check out - http://php.net/manual/en/mysqlinfo.api.choosing.php
Don't confuse data access with output and you will have an easier time attacking this sort of problem.
//Fetch and Sort
$data = array();
while ($row = mysql_fetch_array($result)){
$item = $row['item'];
if(!isset($data[$item]) {
$data[$item] = array():
}
$data[ = $data[$item][] = $row['comment'];
}
//Output
foreach($data as $item => $comments) {
echo '<li><div class=className><div class=itemName>'.$item.'</div>';
foreach($comments as $comment) {
echo '<div class=newRow>'.$comment.'</div>';
}
echo '</div></li>';
}
If you are not getting the data back sorted by id already, add to the end of your query:
ORDER BY name
which will retrieve the same list ordered by id. Then in your while loop, add a variable that keeps track of the last item name that you saw. If it changes, add a new li, otherwise, add the comment on to the end of your current list.

PHP - Nested List Broken into Even Columns (fix and updates)

I have a follow-up to a previous thread/question that I hope can be solved by relatively small updates to this existing code. In the other thread/question, I pretty much solved a need for a nested unordered list. I needed the nested unordered list to be broken up into columns based on the number of topics.
For example, if a database query resulted in 6 topics and a user specified 2 columns for the layout, each column would have 3 topics (and the related news items below it).
For example, if a database query resulted in 24 topics and a user specified 4 columns for the layout, each column would have 6 topics (and the related news items below it).
The previous question is called PHP - Simple Nested Unordered List (UL) Array.
The provided solution works pretty well, but it doesn't always divide
correctly. For example, when $columns = 4, it only divides the
columns into 3 groups. The code is below.
Another issue that I'd like to solve was brought to my attention by
the gentleman who answered the question. Rather than putting
everything into memory, and then iterating a second time to print it
out, I would like to run two queries: one to find the number of
unique TopicNames and one to find the number of total items in the
list.
One last thing I'd like to solve is to have a duplicate set of
code with an update that breaks the nested unordered list into columns
based on the number of news items (rather than categories). So, this
would probably involve just swapping a few variables for this second
set of code.
So, I was hoping to solve three issues:
1.) Fix the division problem when relying on the number of categories (unordered list broken up into columns based on number of topics)
2.) Reshape the PHP code to run two queries: one to find the number of unique TopicNames and one to find the number of total items in the list
3.) Create a duplicate set of PHP code that works to rely on the number of news items rather than the categories (unordered list broken up into columns based on number of news items)
Could anyone provide an update or point me in the right direction? Much appreciated!
$columns = // user specified;
$result = mysql_query("SELECT * FROM News");
$num_articles = 0;
// $dataset will contain array( 'Topic1' => array('News 1', 'News2'), ... )
$dataset = array();
while($row = mysql_fetch_array($result)) {
if (!$row['TopicID']) {
$row['TopicName'] = 'Sort Me';
}
$dataset[$row['TopicName']][] = $row['NewsID'];
$num_articles++;
}
$num_topics = count($dataset);
// naive topics to column allocation
$topics_per_column = ceil($num_topics / $columns);
$i = 0; // keeps track of number of topics printed
$c = 1; // keeps track of columns printed
foreach($dataset as $topic => $items){
if($i % $topics_per_columnn == 0){
if($i > 0){
echo '</ul></div>';
}
echo '<div class="Columns' . $columns . 'Group' . $c . '"><ul>';
$c++;
}
echo '<li>' . $topic . '</li>';
// this lists the articles under this topic
echo '<ul>';
foreach($items as $article){
echo '<li>' . $article . '</li>';
}
echo '</ul>';
$i++;
}
if($i > 0){
// saw at least one topic, need to close the list.
echo '</ul></div>';
}
UPDATE 12/19/2011: Separating Data Handling from Output Logic (for the "The X topics per column variant"):
Hi Hakre: I've sketched out the structure of my output, but am struggling with weaving the two new functions with the old data handling. Should the code below work?
/* Data Handling */
$columns = // user specified;
$result = mysql_query("SELECT * FROM News LEFT JOIN Topics on Topics.TopicID = New.FK_TopicID WHERE News.FK_UserID = $_SESSION[user_id] ORDER BY TopicSort, TopicName ASC, TopicSort, NewsTitle");
$num_articles = 0;
// $dataset will contain array( 'Topic1' => array('News 1', 'News2'), ... )
$dataset = array();
while($row = mysql_fetch_array($result)) {
if (!$row['TopicID']) {
$row['TopicName'] = 'Sort Me';
}
$dataset[$row['TopicName']][] = $row['NewsID'];
$num_articles++;
}
/* Output Logic */
function render_list($title, array $entries)
{
echo '<ul><li>', $title, '<ul>';
foreach($entries as $entry)
{
echo '<li>', $entry['NewsID'], '</li>';
}
echo '</ul></li></ul>;
}
function render_column(array $topics)
{
echo '<div class="column">';
foreach($topics as $topic)
{
render_list($topic['title'], $topic['entries']);
}
echo '</div>';
}
You have not shown in your both questions what the database table is, so I can not specifically answer it, but will outline my suggestion.
You can make use of aggregation functions in mysql to obtain your news entries ordered and grouped by topics incl. their count. You can do two queries to obtain counts first, that depends a bit how you'd like to deal with your data.
In any case, using the mysql_... functions, all data you selected from the database will be in memory (even twice due to internals). So having another array as in your previous question should not hurt much thanks to copy on write optimization in PHP. Only a small overhead effectively.
Next to that before you take care of the actual output, you should get your data in order so that you don't need to mix data handling and output logic. Mixing does make things more complicated hence harder to solve. For example if you put your output into simple functions, this gets more easy:
function render_list($title, array $entries)
{
echo '<ul><li>', $title, '<ul>';
foreach($entries as $entry)
{
echo '<li>', $entry['NewsID'], '</li>';
}
echo '</ul></li></ul>;
}
function render_column(array $topics)
{
echo '<div class="column">';
foreach($topics as $topic)
{
render_list($topic['title'], $topic['entries']);
}
echo '</div>';
}
This already solves your output problem, so we don't need to care about it any longer. We just need to care about what to feed into these functions as parameters.
The X topics per column variant:
With this variant the data should be an array with one topic per value, like you did with the previous question. I would say it's already solved. Don't know which concrete problem you have with the number of columns, the calculation looks good, so I skip that until you provide concrete information about it. "Does not work" does not qualify.
The X news items per column variant:
This is more interesting. An easy move here is to continue the previous topic with the next column by adding the topic title again. Something like:
Topic A Topic A Topic B
- A-1 - A-5 - B-4
- A-2 Topic B - B-5
- A-3 - B-1 - B-6
- A-4 - B-2
- B-3
To achieve this you need to process your data a bit differently, namely by item (news) count.
Let's say you managed to retrieve the data grouped (and therefore sorted) from your database:
SELECT TopicName, NewsID FROM news GROUP BY 1;
You can then just iterate over all returned rows and create your columns, finally output them (already solved):
$itemsPerColumn = 4;
// get columns
$topics = array();
$items = 0;
$lastTopic = NULL;
foreach ($rows as $row)
{
if ($lastTopic != $row['TopicName'])
{
$topic = array('title' => $row['TopicName']);
$topics[] = &$topic;
}
$topic['entries'][] = $row;
$items++;
if ($items === $itemsPerColumn)
{
$columns[] = $topics;
$topics = array();
$lastTopic = NULL;
}
}
// output
foreach($columns as $column)
{
render_column($column);
}
So this is actually comparable to the previous answer, but this time you don't need to re-arrange the array to obtain the news ordered by their topic because the database query does this already (you could do that for the previous answer as well).
Then again it's the same: Iteration over the returned result-set and bringing the data into a structure that you can output. Input, Processing, Output. It's always the same.
Hope this is helpful.

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++;
}

Categories