Thank you for reading this and for your help in advance.
I got a simple Book-Catalogue /procedure code/, every visitor can see the book catalogue and click through out the books and check their authors BUT I've got an idea to add a feature that allows the users to write a comment to each book ONLY if they're logged. So I added a session variable $_SESSION['isLogged']. But there is a lot of code blocks that duplicates. What I need is an advice, what to do with this duplicated blocks of code. What the good practice says? And my code below is from one of the 6 files that I got. In everyfile I got this repeating of code.
So here's my code:
if (!isset($_SESSION['isLogged'])) {
echo '<div class="user-navigation">
<a href="register.php" class="user-nav" >Register now</a>
Log in
</div>
<div class="navigation1">
Add book
Add author
</div>';
$booksAndAuthors = mysqli_query($connection, 'SELECT DISTINCT * FROM books LEFT JOIN books_authors ON books.book_id=books_authors.book_id LEFT JOIN authors ON authors.author_id=books_authors.author_id');
$result = array();
while ($resultArr = mysqli_fetch_assoc($booksAndAuthors)) {
$result[$resultArr['book_id']] ['book_name'] = $resultArr['book_title']; // Reodering array
$result[$resultArr['book_id']] ['author'][$resultArr['author_id']] = $resultArr['author_name']; // Reordering array
}
echo '<table class="table"><tr><th>Book name</th><th>Author</th></tr>'; // Open table html table tags
foreach ($result as $k=>$b) { // Foreach the result array to get the book_name
echo '<tr><td>' . $b['book_name'] . '</td><td>';
$data = array(); // Create an empty array in order to fill the data inside
foreach ($b['author'] as $k => $a) { // Foreach the nested array with the authors to get the author_name displayed
$_GET['author_name'] = $a;
$data[] = '' . $a . ''; // Link is chosen by the author_id
}
echo implode(', ', $data); // Add a comma after every record
echo '</td></tr>'; // Close table cell and row
}
exit;
echo '</table>'; // Close html table tag
}
else {
echo '<div class="user-navigation">
My Profile
Log out
</div>
<div class="navigation2">
Add book
Add author
</div>';
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
$booksAndAuthors = mysqli_query($connection, 'SELECT DISTINCT * FROM books LEFT JOIN books_authors ON books.book_id=books_authors.book_id LEFT JOIN authors ON authors.author_id=books_authors.author_id');
$result = array();
while ($resultArr = mysqli_fetch_assoc($booksAndAuthors)) {
$result[$resultArr['book_id']] ['book_name'] = $resultArr['book_title']; // Reodering array
$result[$resultArr['book_id']] ['author'][$resultArr['author_id']] = $resultArr['author_name']; // Reordering array
}
echo '<table class="table"><tr><th>Book name</th><th>Author</th></tr>'; // Open table html table tags
foreach ($result as $k=>$b) { // Foreach the result array to get the book_name
echo '<tr><td>' . $b['book_name'] . '</td><td>';
$data = array(); // Create an empty array in order to fill the data inside
foreach ($b['author'] as $k => $a) { // Foreach the nested array with the authors to get the author_name displayed
$_GET['author_name'] = $a;
$data[] = '' . $a . ''; // Link is chosen by the author_id
}
echo implode(', ', $data); // Add a comma after every record
echo '</td></tr>'; // Close table cell and row
}
echo '</table>'; // Close html table tag
}
*If my question is not properly asked or you have some notices.Please let me know!
* (=
Put this code in a file then include that file at the bottom of all of the pages.
For example put the code in isLogged.php
Then on each page where the code is duplicated replace it with:
include "isLogged.php";
include is what you're looking for.
You should create a file that contains your repeated code. functions.php for example.
Then call it with one of these methods.
include "functions.php"
http://php.net/manual/en/function.include.php
include_once("functions.php")
http://php.net/manual/en/function.include-once.php
require_once("functions.php")
http://php.net/manual/en/function.require-once.php
create a function of repeated block and call when it required or create a file with the set of repeated code and use any of include,include_once,require_once to add the file.for more detail see php manual for these functions.
Related
I've started to code in April 2021 so I'm super new to this. Working on my final exam, I'd need your precious help! I want to generate a dynamic list from a database, containing 2 joined tables (users and interest). The 2 tables both contain "ID_user" which links them as a foreign key. The idea is that one the user is logged in, the profile page displays all the interests the user selected at sign up. At the moment I can only display the last interest selected and not all of them.
Here is my php:
$request2 = "SELECT `interest`.`name_Interest`
FROM `interest`
INNER JOIN `users`
ON `interest`.`ID_user` = `users`.`ID_user`
WHERE `pseudo` = '".$url_pseudo."'
";
$resultat2 = mysqli_query($connexion, $request2) or die (mysqli_error($connexion));
$nb_resultat2 = mysqli_num_rows($resultat2);
if ($nb_resultat2 > 0) {
while ($row = mysqli_fetch_array($resultat2)){
$name_Interest = $row["name_Interest"];
}
}
Here is the HTML displaying the response:
enter image description here
Here is my db:
enter image description here
Any idea why I can get only 1 value?
enter image description here
thanks in advance
Your while loop is writing to the same variable for each iteration of the loop;
while ($row = mysqli_fetch_array($resultat2)){
$name_Interest = $row["name_Interest"];
}
This will leave $name_Interest containing the last value from your database after the loop has completed.
To resolve this, you will need to keep a list of interest names - this can be achieved by using an array. PHP Array Documentation
// Declares the empty array
$interests = [];
// Loop through database results
while ($row = mysqli_fetch_array($resultat2)){
// Add this value to the array
$interests[] = $row["name_Interest"];
}
Now, $interests will hold all of the values from the database!
You will need to print these out differently in your HTML, by looping through all the values in the array and printing one at a time:
(PHP foreach documentation)
<ul>
<?php foreach ($interests as $interest) { ?>
<li><?php echo $interest; ?></li>
<?php } ?>
</ul>
Solution
Simple store all user interests on array and then show in iteration on page.
Code:
$user_interests=array();
while ($row = mysqli_fetch_array($resultat2)){
$user_interests[] = $row["name_Interest"];
}
Now $user_interests array holds all interests of users as a result of join.
At last loop over it
<?php foreach ($user_interests as $interest) { ?>
<p><?php echo $interest; ?></p>
<?php } ?>
on my website I currently have a save to 'favorites' button which saves a recipe to the users favorites and displays their favorites on their dashboard. I have managed to display the favorites on their dashboard with hyperlinks surrounding them. However I can't quite figure out how to actually connect each favorite to its link.
Below is the code to retrieve the favorites stored on the database.
$favs = array();
$links = array();
$sql = "SELECT * FROM recipe WHERE fav='yes'";
$records = mysql_query($sql);
while($result =mysql_fetch_assoc($records)){
$favs[] = $result['recipeName'];
$links[] = $result['url'];
}
I have also saved the url of each recipe on my database, so just need to print out each favorite with the link to their url.
below is the code to display the favourites surrounded by a tags. I have also managed to return the url links from the database but just need to conect them to each recipe.
foreach ($favs as $fav) {
echo '<a href=''>'.$fav.'</a>'.' ';
}
You don't need foreach loop and opening blank arrays here:
while($result =mysql_fetch_assoc($records)){
echo 'Go to '.$result['recipeName'].'';
}
I suggest you put the recipeName and the URL in a single array.
e.g.
$i = 0;
while($result =mysql_fetch_assoc($records)) {
$fav_links[i] = array('recipeName' => $result['recipeName'], 'url' => $result['url']);
}
Then in your foreach:
foreach ($fav_links as $fav) {
echo ''.$fav["recipeName"].''.' ';
}
I have the following query which pulls from 3 tables. I'll end up with 1 family per row but with multiple children for each. I want to be able to show all children ages within the family row. I thought about opening another connection/query, but figured there is a smarter way.
Query:
SELECT
families.*, job.*, children.*, families.first_name AS fam_firstname, children.first_name AS child_firstname
FROM job
LEFT OUTER JOIN families ON job.fam_id = families.fam_id
LEFT OUTER JOIN children ON families.fam_id = children.fam_id
WHERE
job.published = 2
GROUP BY job.job_id
ORDER BY job.created_on DESC
Loop:
if ($result = $mysqli->query($query)) {
$from = new DateTime($row['dob']);
$to = new DateTime('today');
while ($row = $result->fetch_assoc()) {
echo '<tr>';
echo '<td>' .$row['fam_firstname']. '</td>';
echo '<td>' .$row['last_name'].'</td>';
/* Looking to list all children ages. Separate by comma or break */
echo '<td>' . $from->diff($to)->y .'</td>';
echo '</tr>';
}
$result->free();
}
Desired Output:
Family First Name | Family Last Name | Child 1 Age, Child 2 Age
You need to use the mysql group_concat function to achieve this:
SELECT
families.*, group_concat(children.age)
FROM job
LEFT OUTER JOIN families ON job.fam_id = families.fam_id
LEFT OUTER JOIN children ON families.fam_id = children.fam_id
WHERE
job.published = 2
group by families.fam_id
ORDER BY job.created_on DESC
Follow this question: Nested Array from multiple tables.
Refer to the second option in the question, that explains how you subtract your data from the JOIN query.
P.S.
I'ts a question I've asked myself, with an implementation with what your'e trying to do here. If you need more lead on how to implement it here, ask in comments...
Here is a way to implement it in your code (notice you should order your JOIN query by "fam_firstname", for this code to work for you):
/* init temp vars to save current family's data */
$current = null;
$fam_firstname = null;
$children = array();
while ($row = mysql_fetch_assoc($result))
{
/*
if the current id is different from the previous id:
you've got to a new family.
print the previous family (if such exists),
and create a new one
*/
if ($row['fam_firstname'] != $fam_firstname )
{
// in the first iteration,
// current (previous family) is null,
// don't print it
if ( !is_null($current) )
{
$current['children'] = $children;
/*
Here you print the whole line
I'm just dumping it all here, but you can print
it more nicer...
*/
var_dump($current);
$current = null;
$fam_firstname = null;
$children = array();
}
// create a new family
$current = array();
$current['fam_firstname'] = $row['fam_firstname'];
/*
Add more columns value here...
*/
// set current as previous id
$fam_firstname = $current['fam_firstname'];
}
// you always add the phone-number
// to the current phone-number list
$children[] = $row['child_firstname'] . " is " . $row['child_age'] . " years old";
}
}
// don't forget to print the last family (saved in "current")
if (!is_null($current))
/*
Here you print the whole line
I'm just dumping it all here, but you can print
it more nicer...
*/
var_dump($current);
I'm trying to display a company name from a company table, and then loop out news from another table. The two tables are joined. This means that: I want to just pick out one row from one table in the join, and loop out data from the other table in the join. Is this possible? My code below only display two out of three posts in the news table in my loop.
Thanks!
$sql = "SELECT
newID, newTitle, newSummary, newDate,
comID, comName, comImageThumb
FROM
tblNews a RIGHT JOIN tblCompanies b
ON a.newCompanyID = b.comID
ORDER BY newDate DESC";
// Get company name and display
$companyData = mysql_fetch_assoc($result);
$comName = $companyData['comName'];
echo "<a href='#' class='name'>$comName</a>";
// Looping news
while($news = mysql_fetch_assoc($result)) {
// Display news posts
$newTitle = $news['newTitle'];
echo $newTitle;
}
Put everything inside while loop and try :
while($news = mysql_fetch_assoc($result)) {
// Get company name and display
$comName = $news ['comName'];
echo "<a href='#' class='name'>$comName</a>";
// Looping news
// Display news posts
$newTitle[] = $news['newTitle'];
echo $newTitle;
}
You should look at mysql GROUP_CONCAT for more detail.
Easiest solution probably would be to keep track of whether you are in the first iteration:
// query company name and news entries here
$firstRow = true;
while($news = mysql_fetch_assoc($result)) {
if ($firstRow) { echo $news['comName']; }
$firstRow = false;
echo $news['newTitle'];
}
You could also keep your current code and use mysql_data_seek(0) to reset the cursor after extracting the company name first.
And on a side note: Don't use mysql_* functions anymore! Use PDO instead.
Move the fetch operation to the end of the loop:
$companyData = mysql_fetch_assoc($result);
$comName = $companyData['comName'];
echo "<a href='#' class='name'>$comName</a>";
// you've already fetched a news item....
$news=$companyData;
do {
$newTitle = $news['newTitle'];
echo $newTitle;
} while ($news=mysql_fetch_assoc($result));
I'm trying to make a simple alphabetical list to order items in my database. The thing I can't figure out is how to actually list it.
I would like it to be the same format as you have on miniclip.com
Here's an image
I looked around, but couldnt find an answer really.
(I would like it to finish even at the end of each vertical column, except the last one for sure)
Any help would be welcome!
In MySQL:
SELECT * FROM table ORDER BY name ASC
In PHP:
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach ($fruits as $key => $val) {
echo "fruits[" . $key . "] = " . $val . "\n";
}
fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange
Assuming that your result set already is sorted by using the ORDER BY clause, to group the results by their first character you just need to remember the first character of the previous entry and print out the first character of the current entry if they are different. So:
$prevLabel = null;
while ($row = mysql_fetch_assoc($result)) {
$currLabel = strtoupper(substr($row['name'], 0, 1));
if ($currLabel !== $prevLabel) {
echo $currLabel;
$prevLabel = $currLabel;
}
echo $row['name'];
}
This will print the first character as a label for each group that’s members have the same first character.
He doesn't seem to have an issue with the storting, but doing the column format and headers for each new letter.
Suppose $arr contains your alphabetically sorted list with numeric keys. each element has indexes 'name' and 'link'. This should be pretty safe assumption for data from a SQL query.
$firstLetter = -1;
$desiredColumns = 4; //you can change this!
$columnCount = (count($arr)+27)/$desiredColumns+1;
echo "<table><tr><td>";
foreach($arr as $key => $cur)
{
if ($key != 0 && $key % desiredColumns == 0) echo "</td><td>";
if ($cur['name'][0] !== $firstLetter)
{
echo "<strong>$firstLetter</strong> <br />"; $firstLetter = $cur['name'][0];
}
echo "".$cur['name']."<br />";
}
echo "</td><tr></table>";
You'll have to treat numbers as a special case, but this is the idea. If you are using a template engine there are obviously better ways of doing this, but I figure you would have mentioned that. This is a rough sketch, making pretty HTML isn't my thing.
--Query-- get table into $arr. I can't see your tables obviously, Im making assumptions if names nad stuff so you'll need to verify or change them
$sql = "SELECT * FROM table T ORDER BY name";
$conn = //you should have this
$res = mysql_query($sql, $conn);
$arr = array();
while($row = mysql_fetch_assc($res)
$arr[] = $row;
// start above code here. This isn't safe for empty query responses or other error but it works
I presume you're using MySQL (or another SQL) database, in which case you should simply retrieve the data in the required order using a SORT BY clause on the lookup SELECT. (Sorting this PHP is trivial via the sort function, but it makes sense to get the database to do this - that's pretty much what it's for.)
In terms of balancing the output of each of the columns, you could get a COUNT of the required rows in your database (or simply use the count of the resulting PHP array of data) and use this to ensure that the output is balanced.
As a final thought, if this is going to be output on a per-page basis, I'd highly recommend generating it into a static file when the structure changes and simply including this static file as a part of the output - generating this on the fly is needlessly resource inefficient.
The mysql option mentioned above is definitely the best bet. If the data comes out of the DM in order, that's the simplest way to go.
Your next option might be to look at the
asort and ksort functions in PHP to find the exact one you're looking for.
http://www.php.net/manual/en/array.sorting.php
How are you pulling the data?
<?php
$result = mysql_query("SELECT titles FROM gamelist ORDER BY title ASC");
while ($row = mysql_fetch_assoc($result)) {
echo "{$result['title']}<br/>";
}
?>
There are two ways to do it.
You could use your database and use the 'order' clause to pull them by a specific field alphabetically.
You could also use either a key sort or value sort on a PHP array.
The PHP functions are sort($array) and ksort($array).
http://php.net/manual/en/function.sort.php
http://php.net/manual/en/function.ksort.php
<?php
$list = $your_list_array_from_database
//if you need info on how to do this, just let me know
sort($list);
foreach($list as $item) {
echo $item;
}
?>
I found this post and had the same problem. I used the code below to output a list by category name with a header equal to the first letter. In my database table (category) I have name and category_letter. So, name = football and category_list = 'F'.
<section>
<?php
try {
$cats_sql = $dbo->prepare("SELECT name, category_list, FROM category WHERE category_list REGEXP '^[A-Z#]' GROUP BY category_list ASC");
$cats_sql->execute();
$results_cats = $cats_sql->fetchAll();
} catch(PDOException $e) {
include('basehttp/error');
}
$array_cats = $results_cats;
if(is_array($array_cats)) {
foreach($array_cats as $row_cats) {
$cat_var = $row_cats[category_list]; // Each Category list title
?>
<aside>
<h1><a name=""><? echo $cat_var ?></a></h1>
<?php
try {
$search_sql = $dbo->prepare("SELECT name, category_list FROM category WHERE category_list=:cat_var ORDER BY name ASC"); // Pulling a list of names for the category list
$search_sql->bindParam(":cat_var",$cat_var,PDO::PARAM_STR);
$search_sql->execute();
$results_search = $search_sql->fetchAll();
} catch(PDOException $e) {
include('basehttp/error');
}
$array_search = $results_search;
if(is_array($array_search)) { // Output list of names which match category
foreach($array_search as $row_search) {
?>
<h2><?php echo $row_search[name]; ?></h2>
<br class="clear">
<?php
}
}
?>
</aside>
<br class="clear">
<?php
}
}
?>
</section>
Its actually Simple....I did similar thing for my project once. I had to pull out all music albums name and categorize them in alphabetical order.
In my table, "album_name" is the column where names are stored.
$sql= "select * from album_table order by album_name ASC";
$temp_char= ""; // temporary variable, initially blank;
using while loop, iterate through records;
while($row= $rs->fetch_assoc())
{
$album_name= $row['album_name'];
$first_char_of_albm= $album_name[0]; // this will store first alphabet;
$first_char_of_albm= strtoupper($first_char_of_albm); // make uppercase or lower as per your needs
if($temp_char!=$first_char_of_albm)
{
echo $first_char_of_albm;
$temp_char= $first_char_of_albm; // update $temp_char variable
}
}
That's it....
I am posting my answer to this old question for 3 reasons:
You don't always get to write your queries to MySQL or another DBMS, as with a web service / API. None of the other answers address PHP sorting without query manipulation, while also addressing the vertical alphabetical sort
Sometimes you have to deal with associative arrays, and only a couple other answers deal with assoc. arrays. BTW, my answer will work for both associative and indexed arrays.
I didn't want an overly complex solution.
Actually, the solution I came up with was pretty simple--use multiple tags with style="float:left", inside of a giant table. While I was sceptical that having multiple tbody tags in a single table would pass HTML validation, it in fact did pass without errors.
Some things to note:
$numCols is your desired number of columns.
Since we are floating items, you may need to set the width and min-width of parent elements and/or add some <br style="clear: both" />, based on your situation.
for alternative sorting methods, see http://php.net/manual/en/array.sorting.php
Here's my full answer:
function sortVertically( $data = array() )
{
/* PREPARE data for printing */
ksort( $data ); // Sort array by key.
$numCols = 4; // Desired number of columns
$numCells = is_array($data) ? count($data) : 1 ;
$numRows = ceil($numCells / $numCols);
$extraCells = $numCells % $numCols; // Store num of tbody's with extra cell
$i = 0; // iterator
$cCell = 0; // num of Cells printed
$output = NULL; // initialize
/* START table printing */
$output .= '<div>';
$output .= '<table>';
foreach( $data as $key => $value )
{
if( $i % $numRows === 0 ) // Start a new tbody
{
if( $i !== 0 ) // Close prev tbody
{
$extraCells--;
if ($extraCells === 0 )
{
$numRows--; // No more tbody's with an extra cell
$extraCells--; // Avoid re-reducing numRows
}
$output .= '</tbody>';
}
$output .= '<tbody style="float: left;">';
$i = 0; // Reset iterator to 0
}
$output .= '<tr>';
$output .= '<th>'.$key.'</th>';
$output .= '<td>'.$value.'</td>';
$output .= '</tr>';
$cCell++; // increase cells printed count
if($cCell == $numCells){ // last cell, close tbody
$output .= '</tbody>';
}
$i++;
}
$output .= '</table>';
$output .= '</div>';
return $output;
}
I hope that this code will be useful to you all.