PHP/MySQL news archive - php

I'm a bit stuck trying to get my code to output correctly, see below. It all works ok, but rather than displaying all news items, it only shows one for each month. What I need to do is group all news for a selected month with the month/year heading for that month. Hope this makes sense.
Any help greatly appreciated.
SS
$theQuery="Select * from isnews WHERE active = '1' GROUP BY YEAR(date) DESC, MONTH(date) ORDER BY YEAR(date) DESC, MONTH(date) DESC";
$newsQuery=mysql_query($theQuery);
if(mysql_num_rows($newsQuery)>0) {
while ($newsResult=mysql_fetch_array($newsQuery)) {
$newDate = $newsResult['date'] ;
echo '<div class="date">' . date('F Y ',strtotime($newDate)) . '</div>';
echo '<ul class="press">';
echo '<li>
<img src="'.$wwwUrl.'images/news/'.$newsResult['image'].'" width="'.$newsResult['tnWidth'].'" height="'.$newsResult['tnHeight'].'" title="'.$newsResult['title'].'" alt="'.$newsResult['title'].'" />
<h3>'.$newsResult["title"].'</h3>
'.substr($newsResult['descrip'],0,100).'
<p>Read more</p>
</li>';
}
echo '</ul>';
} else {
echo 'We currently have no press releases available';
}

There are two problems that I can see. First of all, GROUP BY is an aggregate function, so it is used to combine multiple rows into one row in your result (for instance, if you wanted to see how many news items were written for a given month and year). Secondly, even if you were getting multiple records per time period, you are outputting a date header for every record that you pull from the database (ie. you would get duplicate headers if you have multiple news items from the same month and year).
A better solution would be to collect all your active news items (without the GROUP BY clause), and then build an array which you can then iterate over to output your page:
$query = "SELECT *
FROM isnews
WHERE active = '1'
ORDER BY YEAR(date) DESC, MONTH(date) DESC";
$resultSet = mysql_query($query);
if (mysql_num_rows($resultSet))
{
$newsArray = array();
while ($newsResult = mysql_fetch_array($resultSet))
{
// The time period is what you will output as your header
$timePeriod = intval(date("F Y", $newsResult['date']));
if (!isset($newsArray[$timePeriod]))
{
// Create a subarray if needed
$newsArray[$timePeriod] = array();
}
$newsArray[$timePeriod][] = $newsResult;
}
foreach ($newsArray as $timePeriod => $newsItems)
{
echo '<div class="date">' . $timePeriod . '</div>';
echo '<ul class="press">';
foreach ($newsItems as $item)
{
echo '<li>';
// ... do your news item outputting
echo '</li>';
}
echo '</li>';
echo '</div>';
}
}
else
{
echo 'We currently have no press releases available';
}

Many thanks for the help.
I've tried adapting the code from Daniel a little in order to create a sidebar-type archive list showing years, then the months and their corresponding news results. The end result being an accordion type menu where the years dropdown to show the months, then the months dropdown to display the news items. I can get it to work as far as the years go but can't seem to get the months working properly.
Any pointers/help more than greatly appreciated. (code below)
SS
$query = "SELECT * FROM isnews WHERE active = '1' ORDER BY YEAR(date) DESC, MONTH(date) DESC";
$resultSet = mysql_query($query);
if (mysql_num_rows($resultSet))
{
$newsArray = array();
echo '<ul>' . PHP_EOL;
echo '<li><strong>Press releases:</strong></li>' . PHP_EOL;
while ($newsResult = mysql_fetch_array($resultSet))
{
$newDate = $newsResult['date'] ;
$timePeriod = date('F Y ',strtotime($newDate));
$timePeriodY = date('Y',strtotime($timePeriod));
$timePeriodM = date('F',strtotime($timePeriod));
if (!isset($newsArray[$timePeriodY]))
{
$newsArray[$timePeriodY] = array();
}
$newsArray[$timePeriodY][] = $newsResult;
}
foreach ($newsArray as $timePeriodY => $newsItems)
{
echo '<li><em>' . $timePeriodY . '</em>' . PHP_EOL;
echo '<ul>' . PHP_EOL;
foreach ($newsItems as $item)
{
echo '<li>';
echo ''.$item["title"].'';
echo '</li>' . PHP_EOL;
}
echo '</ul>' . PHP_EOL;
echo '</li>' . PHP_EOL;
}
echo '</ul>' . PHP_EOL;
}
else
{
echo 'We currently have no press releases available';
}

it only shows one for each month
That's correct, your GROUP BY isn't correct. All columns (see the * ) should be in your GROUP BY because all of them are in the SELECT and you don't use any aggregate function. MySQL has very strange behaviour and now only returns the first record it can find.
If you want all records, just drop the entire GROUP BY, and ORDER BY the month and year to get the correct sort order. In youw PHP you can make some groups, but that has nothing to do with SQL.
You might consider ONLY_FULL_GROUP_BY, this helps to prevent strange/false results.

Related

PHP : How to get a specific value of an array

I would like to get the id of a specific value in my phpmyadmin table.
So, I have got a table with 'id_cal' as an A.I. id, 'mois' representing the month with numbers (e.g 1 for january) and 'annee' representing the year. (see calendar table)
I am trying to set php variable for the month and the year and if they match the current month and year, I want to get this specific id.
I commented the php code where I am having my trouble, here it is :
<?php
include_once('config.php');
$m = idate('n');
$y = idate('Y');
echo $m; echo "\t"; echo $y; echo "<br>"; echo "<br>"; // The result of this is 7 2019
$reponse = $bdd->query('SELECT * FROM calendrier');
while($donnees= $reponse->fetch()){
$mois = $donnees['mois'];
$year = $donnees['annee'];
$id_cal = $donnees['id_cal'];
echo $id_cal;
echo "\t";
echo $mois;
echo "\t";
echo $year;
echo "<br>";
}
// What I am trying to do :
if (($m = $mois) && ($y = $year)){ // If the month and the year are the current month/year
$i = $id_cal; // I want to put the id refering to the current month/year (in my phpmyadmin table) into a new variable
echo "<br>"; // and echo this variable (or use it in other ways)
echo $i; // BUT what I am echoing is 24 representing the number of values in my array
} // How can I only get 7 ? (in this exemple, since we are the 7/2019)
Here is what I am getting in my localhost : echo
I really don't understand why am I not having 7.
Also, I tried this instead of my while:
$donnees= $reponse->fetch();
$mois = $donnees['mois'];
$year = $donnees['annee'];
$id_cal = $donnees['id_cal'];
// But in this cas I am having $i = 1, so it's the same problem.
Many thanks in advance for your response I am quite struggling with this.
It is because id_cal gets overwritten with the new value of id_cal in each iteration of your while statement.
To get the result you want, you could put the if inside the while statement...
while($donnees= $reponse->fetch()){
$mois = $donnees['mois'];
$year = $donnees['annee'];
$id_cal = $donnees['id_cal'];
echo $id_cal;
echo "\t";
echo $mois;
echo "\t";
echo $year;
echo "<br>";
if (($m == $mois) && ($y == $year)){
$my_var_to_use_elsewhere = $id_cal;
}
}
echo "<br>";
echo $my_var_to_use_elsewhere;

php - get second row until last row in mysql

Using while loop, i can get all the result in the table and echo it into a html table.
But, i want to skip the first row, and echo the result starting from second row.
How can i do that?
This is my code.
$sql2="select * from table where year = '2015' and month = '2' order by month desc";
$result2=mysqli_query($conn,$sql2);
echo '<table>';
while($row2=mysqli_fetch_assoc($result2))
{
echo '<tr>';
echo '<th>'.$row2['acc_sth_date'].'</th>';
echo '<th>'.$row2['acc_sth_med_ori'].'</th>';
echo '<th>'.$row2['acc_sth_med_new'].'</th>';
echo '<th>'.$row2['acc_sth_operator'].'</th>';
echo '</tr>';
}
echo '</table>';
Help me please master. Thanks
You can achieve that in two ways.
You could use LIMIT statement in your sql query :
$sql2="select * from table where year = '2015' and month = '2' order by month desc LIMIT 1,100";
1 = Start at the 2nd row
100 = Returns a maximum of 100 rows
Add a condition in your while loop :
$firstRow = true;
while ($row2 = mysqli_fetch_assoc($result2))
{
if (true === $firstRow)
{
$firstRow = false;
continue;
}
// ... Rest of your code ...
}
You need to add a variable that is tested and set to true to not allow skipping next time:
$FirstRun=true;
while($row2=mysqli_fetch_assoc($result2))
{
if ($FirstRun){
$FirstRun = false;
}else {
echo '<tr>';
echo '<th>'.$row2['acc_sth_date'].'</th>';
echo '<th>'.$row2['acc_sth_med_ori'].'</th>';
echo '<th>'.$row2['acc_sth_med_new'].'</th>';
echo '<th>'.$row2['acc_sth_operator'].'</th>';
echo '</tr>';
}
}
Use the following code
$sql2="select * from table where year = '2015' and month = '2' order by month desc";
$result2=mysqli_query($conn,$sql2);
$row2=mysqli_fetch_assoc($result2);
$count = count($row2);
$i = 1;
echo '<table>';
while(i>=$count)
{
echo '<tr>';
echo '<td>'.$row2[i]['acc_sth_date'].'</td>';
echo '<td>'.$row2[i]['acc_sth_med_ori'].'</td>';
echo '<td>'.$row2[i]['acc_sth_med_new'].'</td>';
echo '<td>'.$row2[i]['acc_sth_operator'].'</td>';
echo '</tr>';
$i++;
}
echo '</table>';
It will display all rows except the first row.

PHP & MySQL Query results are confusing

Working on a quick script to display recent activity of a customer in my database - I have the script outputting results but what it's out putting is confusing me.
<?php
//Search for customer recent history
$q = "SELECT * FROM txn_log WHERE customer_no = $customer_no ORDER BY datetime DESC LIMIT 3";
$r = mysql_query($q) or die(mysql_error());
while($row = mySQL_fetch_array($r)) {
$recent_history = '';
$str .= '<a href="#" class="list-group-item">';
$str .= ' <span class="badge">' . gmdate("Y-m-d\TH:i:s\Z", $row['datetime']) . '</span>';
$str .= ' <i class="fa fa-check"></i> ' . $row['txn_id'] . ': ' . $row['txn_type'] . ' ' . $row['amount_dif'];
$str .= '</a>';
echo $str;
}
?>
In my database I have one test customer with three records associated with them, starting at ID 2.
My query above SHOULD be outputting only the three records in order of the UNIX timestamp used,
which should produce the three records in the following order => ID2, ID3, ID4
What it IS doing is outputting the following => ID2, ID2, ID3, ID2, ID3, ID4
I don't understand what I did wrong to get it to produce the first three (ID2, ID2, ID3) in addition to the correct results. Each time I run the query, the results are the same.
You are using $str.=
so on the
first iteration of your loop, the $str being echoed is ID2
second iteration, $str being echoed is ID2 + ID3
third iteration, $str being echoed is ID2 + ID3 + ID4
In the end, it will look like ID2, ID2, ID3, ID2, ID3, ID4
Hope that helps!
To Fix this, try declaring the variable as $str = "" at the start of your loop, and then your echo will only echo each ID once.
Reset $str for each loop iteration.
Add:
$str="";
After $recent_history = '';
You need to use mysql_fetch_assoc, and echo outside the loop
Few things to keep in mind,
security has to be your top priory, check for SQL injection characters and always enclose your variables with single quotes in the query. see below
<?php
//Search for customer recent history
$customer_no = str_replace("'", '', $customer_no);
$q = "SELECT * FROM txn_log WHERE customer_no = '$customer_no' ORDER BY datetime DESC LIMIT 3";
$r = mysql_query($q) or die(mysql_error());
while($row = mySQL_fetch_assoc($r)) {
$recent_history = '';
$str .= '<a href="#" class="list-group-item">';
$str .= ' <span class="badge">' . gmdate("Y-m-d\TH:i:s\Z", $row['datetime']) . '</span>';
$str .= ' <i class="fa fa-check"></i> ' . $row['txn_id'] . ': ' . $row['txn_type'] . ' ' . $row['amount_dif'];
$str .= '</a>';
}
echo $str;
?>
Woops... found it..
Derp in my While()
I was clearing the wrong string!
$recent_history = ''; should have been $str = '';
EDIT:
Thanks all, I didn't see you guys posting until I submitted my correction.
I'm definitely going to be securing the script, I'm just making sure that i can do what I want it to do :)

multiple dates datetime

I am trying to display a table with PHP MYSQL where the FIELD is the DATE and rows are TIME from a MySQL database with unknown/infinite records, one with different TIMES for the same DATE, by querying it for the DateTime.
My mysql date stores the dateTime in the same column, but I am splitting this and trying to display them seperately. BUT I cannot seem to display the date only once and the time multiple times, it is just both.
$sql_result = mysqli_query($connection, "SELECT DATE(date_time) AS date_part, TIME(date_time) AS time_part FROM $table WHERE date_time LIKE '$date_input%'");
if (mysqli_num_rows($sql_result) == 0)
{
echo "<p>No bookings exist.</p>";
}
else {
echo "<h3>Results for booked " . $table . " Appointments:</h3>";
echo "<h3>" . $formattedDate ."</h3>";
while ($row = mysqli_fetch_array($sql_result))
{
echo $row['date_part'];
$array_time = array($row['time_part']);
foreach ($array_time as $time_output)
{
echo $time_output;
}
}
}
My output is like this:
2013-12-0809:00:002013-12-0810:00:002013-12-0811:00:002013-12-0812:00:002013-12-0814:00:002013-12-0815:00:002013-12-0816:00:002013-12-0817:00:002013-12-0909:00:002013-12-0809:00:00
But I would like it like this:
2013-12-08 09:00:0010:00:0011:00:0012:00:0014:00:0015:00:0016:00:0017:00:0009:00:000
2013-12-09 9:00:00
Hrrmm. Theres a bit of logic problem here:
while ($row = mysqli_fetch_array($sql_result))
{
echo $row['date_part'];
$array_time = array($row['time_part']); // HERE
foreach ($array_time as $time_output)
{
echo $row['time_part'];
}
}
$array_time will always have only one value, since $row['time_part'] only refers to ONE row (each iteration of while ($row = mysqli_fetch_array($sql_result)) reassigns a single row to $row)
try doing this first pass to define a workable array
while ($row = mysqli_fetch_array($sql_result))
{
$array[$row['date_part']][$row['time_part']] = 1; // the value assigned doesn't matter, all we wish is a definite hierarchy
}
this will give you an array like:
['2013-12-08']['9:08'] = 1
['12:30'] = 1
[23:17] = 1
['2013-12-09']['10:00'] = 1
[14:20] = 1
THEN! you can foreach through your result
foreach ($array as $date_part => $array_time)
{
echo $date_part . ' ';
foreach ($array_time as $time_part => $i) // again our $i is not used
{
echo $time_part;
}
echo '<br>'; // here it breaks line after all times for the date has been echoed
}
You need to GROUP in your query:
SELECT DATE(date_time) AS date_part, TIME(date_time) AS time_part
FROM $table
WHERE date_time LIKE '$date_input%'
GROUP BY date_part
I think I understand what you're trying to say, however, MySQL won't create a multidimensional array. You should try something like this:
$dates = array();
while ($row = mysqli_fetch_array($sql_result)) {
$dates[$row['date_part']][] = $row['time_part']
}
Then you could have something like this:
foreach ($dates as $key => $value) {
echo $key.'<br />';
foreach ($value as $time) {
echo $time.' - ';
}
echo '<br />';
}
which should look something like:
2013-09-01
09:00 - 09:30 - 10:20 - 11:00
2013-09-02
10:12 - 11:00 - 12:24 //etc
Hope this helps!
Two comments. First, it seems like you need an order by time so as to order your records.
SELECT DATE(date_time) AS `date_part`, TIME(date_time) AS `time_part`
FROM $table
WHERE date_time LIKE '$date_input%'
ORDER BY date_time ASC
Second, if I read your question correctly, it seems like you want to output your data into two columns, one with date and the other with all times for that date. You might consider using GROUP_CONCAT() to do this in SQL, making your output easy.
SELECT DATE(date_time) AS `date_part`, GROUP_CONCAT(TIME(date_time)) AS `times`
FROM $table
WHERE date_time LIKE '$date_input%'
GROUP BY `date_part`
ORDER BY date_time ASC
This would give output like
date_part times
2013-12-08 11:22:33,11:33:44,12:44:55
2013-12-09 12:00:00
With this approach, there would be no need to build a multi-dimensional array in PHP, as the data would come out of the database just the way you need it. That also means that you don't need to load the entire result set into memory in order to work with it (as you would have to do if creating multi-dimensional array).

How to add a seperator between menu items in PHP but not on the end

I'm trying to put an image as a separator between menu items but not on the outside and I'm not sure how to do this.. So it would end up being something like this:
HOME | ABOUT | CONTACT
unfortunately my code puts one after every entry including the last one.
mysql_select_db($database_db_connection, $db_connection);
$query_rsMenu = "SELECT * FROM menu WHERE online = 1 ORDER BY position ASC";
$rsMenu = mysql_query($query_rsMenu, $db_connection) or die(mysql_error());
echo "<ul class='MenuBarVertical'>\n";
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
echo (" <li>" . $row_rsMenu['menuName'] . " <img src='SiteFiles/Site/separator.jpg' /> </li>\n");
}
echo "</ul>\n";
mysql_free_result($rsMenu);
Thanks
You could also build an array and use implode when you print it out. This also separates the database model from the view a little better.
mysql_select_db($database_db_connection, $db_connection);
$query_rsMenu = "SELECT * FROM menu WHERE online = 1 ORDER BY position ASC";
$rsMenu = mysql_query($query_rsMenu, $db_connection) or die(mysql_error());
$array = array();
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
$array[] = "<li>" . $row_rsMenu['menuName'] . "</li>\n";
}
mysql_free_result($rsMenu);
echo "<ul class='MenuBarVertical'>\n";
echo implode(' <img src="SiteFiles/Site/separator.jpg" /> ', $array);
echo "</ul>\n";
Of course the tags end up between the li instead of inside, but since you are making the li inline I think it will work.
The easy solution is to special case either the last iteration or the first one. The first one is usually easier: set $first = true outside the loop, inside the loop: if (!$first) { print 'separator'; }.
$count = 0;
$dbRows = mysql_num_rows($rsMenu);
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
$count++;
echo (" <li><a href=\"../" . $row_rsMenu['menuURL'] . "\">" . $row_rsMenu['menuName'];
if($count < $dbRows)
echo ("</a> <img src='SiteFiles/Site/separator.jpg' /> </li>\n");
}
You could use mysql_num_rows() to get the number of rows from the result set, and build some logic against the result.
Yet another answer :
for ($i = 1; $i <= mysql_num_rows($rsMenu); $i++) {
$row_rsMenu = mysql_fetch_assoc($rsMenu);
// do something;
if ($i == mysql_num_rows($rsMenu) - 1) {
// this is the last element, do something;
}
}

Categories