Solved!!
Thanks, guys. This was my first question on here. Let me know if I'm not formatting this correctly or something. Here's my finished code:
Answer:
$sql = 'SELECT a.*, GROUP_CONCAT(t.name) as track_name FROM albums AS a LEFT JOIN tracks AS t ON a.album_id = t.album_id GROUP BY a.album_id';
foreach ($conn->query($sql) as $row) { ?>
<div class="container">
<div class="row">
<div class="col-6">
<img src="../images/<?= $row['album_cover']?>" alt="Card image cap" style="width:100%;">
<!--shadow-->
<div class="shadow-lg p-3 mb-5 bg-white rounded">
<div class="card-body" style="padding-left:10px;">
<h4 class="card-title"><?= $row['album_name'] ?></h4>
<b><?= print_r($row['album_name'] . ' (' . $row['record_label'] . ') (' . $row['year_released'] . ')', true); ?><br><br></b>
<ul class="list-group list-group-flush">
<?php
$tracks = explode(",", $row['track_name']);
$numTracks = count($tracks);
$i = 0;
while ($i < $numTracks) { ?>
<li class="list-group-item">
<?php
echo $tracks[$i];
$i++;
?>
</li>
<?php } ?>
</ul>
</div>
</div>
</div>
</div>
</div>
<?php } ?>
Question (Solved): I am working on a project for school. I have to revamp an existing discography site (Queen) using php. The part I'm stuck on now is pulling album info from a database and using it to populate the page with each album along with the track names for the album. I have my album info in one table called albums, and all the tracks for every album in another table called tracks, with album_id as a foreign key.
I can get to the point where it's generating the album title from the album table in my database, but I have no idea how to get the tracks for each album.
This is my SQL query:
$sql = '
SELECT a.album_id
, a.album_name
, a.year_released
, a.record_label
, a.album_cover
, t.name
, t.album_id
FROM albums AS a
LEFT
JOIN tracks AS t
USING (album_id)
';
And here is the part in that is supposed to generate the albums:
<?php
foreach ($conn->query($sql) as $row) { ?>
<div class="col-6">
<img src="../images/<?= $row['album_cover']?>" alt="Card image cap" style="width:100%;">
<!--shadow-->
<div class="shadow-lg p-3 mb-5 bg-white rounded">
<div class="card-body" style="padding-left:10px;">
<h4 class="card-title"><?= $row['album_name'] ?></h4>
<b><?= print_r($row['album_name'] . ' (' . $row['record_label'] . ') (' . $row['year_released'] . ')', true); ?><br><br></b>
<ul class="list-group list-group-flush">
<li class="list-group-item">Innuendo</li> <!-- these are just placeholders for the tracks because I don't know what to do here! -->
<li class="list-group-item">I'm Going Slightly Mad </li>
<li class="list-group-item">Headlong</li>
<li class="list-group-item">I Can't Live With You</li>
<li class="list-group-item">Don't Try So Hard </li>
<li class="list-group-item">Ride The Wild Wind</li>
<li class="list-group-item">All God's People</li>
<li class="list-group-item">These Are The Days Of Our Lives</li>
<li class="list-group-item">Delilah</li>
<li class="list-group-item">The Hitman</li>
<li class="list-group-item">Bijou</li>
<li class="list-group-item">The Show Must Go On </li>
</ul>
</div>
</div>
</div>
<?php
}
?>
As it stands, my page is being populated by the same album info over and over because the foreach is iterating through every row in both tables. How do I generate specific tracks based on unique albums?
Try using ON instead of USING:
$sql = 'SELECT * FROM albums AS a LEFT JOIN tracks AS t ON a.album_id = t.album_id';
This should join the two tables correctly. If there are multiple tracks for each album you will need to either query them separately or join the tracks into a group using GROUP_CONCAT. Here would be the query to accomplish this:
$sql = 'SELECT a.*, GROUP_CONCAT(t.name) as track_name FROM albums AS a LEFT JOIN tracks AS t ON a.album_id = t.album_id GROUP BY a.album_id';
Just as a side note I HIGHLY recommend using PDO for all sql related things. Here is a link to set it up and use it for safer sql queries: https://www.w3resource.com/php/pdo/php-pdo.php
ADDED TO LOOP THROUGH TRACKS
First you would need to take the variable and explode it into an array (place inside your loop):
$tracks = explode(',',$row['track_name']);
foreach($tracks as $track_name){
echo $track_name;
}
Now you should be able to do anything you want with these tracks. You could easily place them in a table or in a div.
You call $conn->query($sql) every loop which will return the whole result set again. Also, use while loop like below, not foreach loop since $conn->query() return a mysqli_reuslt object, not an array.
$sql = 'SELECT a.album_id, a.album_name, a.year_released, a.record_label, a.album_cover, t.name, t.album_id
FROM albums AS a LEFT JOIN tracks AS t USING (album_id)';
$result = $conn->query($sql) // return a mysqli_result object
while($row = $result->fetch_assoc()) {
// Your loop content
}
If you insist on using foreach loop:
$result = $conn->query($sql) // return a mysqli_result object
$rows=$result->fetch_all(MYSQLI_ASSOC); //return an array
foreach($rows as $row) {
//content
}
Two ways in which you could approach this problem:
Have 2 loops - the first looping through a simple query to the albums table (no joins), then within that loop perform a second query to the database to get all the tracks. (The downside being that you will be making more queries to the database)
Alternatively, change your query so you are selecting from the tracks table and then the join is on the albums table. To have it so the album title is only printed once for each album, you would need to sort the tracks by album, and then have an if statement to check when the loop has started processing a different album.
You must change your design a little.
First you get the first row get the album data and the first track
After that you grap the rest of the track and close the html tags
$sql = 'SELECT a.album_id, a.album_name, a.year_released, a.record_label
,a.album_cover, t.name, t.album_id
FROM albums AS a LEFT JOIN tracks AS t USING (album_id)';
$result = $conn->query($sql) // get a result from the mysql server
$row = $result->fetch_assoc();
?>
<div class="col-6">
<img src="../images/<?= $row['album_cover']?>" alt="Card image cap" style="width:100%;">
<!--shadow-->
<div class="shadow-lg p-3 mb-5 bg-white rounded">
<div class="card-body" style="padding-left:10px;">
<h4 class="card-title"><?= $row['album_name'] ?></h4>
<b><?= print_r($row['album_name'] . ' (' . $row['record_label'] .
') (' . $row['year_released'] . ')', true); ?><br><br></b>
<ul class="list-group list-group-flush">
<li class="list-group-item"><?= $row['name']?></li>
<?php
//get the rest of teh tracks
while($row = $result->fetch_assoc()) {?>
<li class="list-group-item"><?= $row['name']?></li>
<?php
} //end if While
?>
</ul>
</div>
</div>
</div>
Related
I'm stuck on a query.
My goal is to get the information of that data and all the information belonging to the category of that data in a single query.
I have a usable code but the function is faulty. The error is that how many categories there are, the same data as the number of categories.
rotate
My fault: https://prnt.sc/OzPLaGHFMGP5
My table where I store my data: https://prnt.sc/PEqSq2mM5NKM
My table where I keep my categories: https://prnt.sc/WK7n8kAGoUWD
here is my code to pull my data into the page:
if (!isset($_GET['url']) || empty($_GET['url'])){
header('Location:404.php');
}
$datas = $db->prepare('SELECT * FROM post WHERE url = ?');
$datas->execute([
$_GET['url']
]);
$data = $data->fetch(PDO::FETCH_ASSOC);
if (!$data){
header('Location:404.php');
exit;
}
here is my code where I pull the data category:
<?php $categories = $db->query('SELECT Categories.*, COUNT(posts.id) as totalCategory FROM categories
LEFT JOIN posts ON FIND_IN_SET(categories.id, posts.category_id)
GROUP BY Category.id DESC')->fetchAll(PDO::FETCH_ASSOC); ?>
<?php foreach ($category as $category): ?>
<div class="container mt-4">
<div class="row">
<div class="col-md-12">
<div class="card mb-3">
<div class="card title">
<i class="bi-folder"></i> Category: <?=$category[ ' category_name']?>
<a class="Date"><?=$data['date']?> <i class="bi-clock"></i></a>
</div>
<div class="card body">
<?=htmlspecialchars_decode($data['content'])?>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
So what is wrong with my query, what would you suggest?
So assuming your tables are called "categories" and "posts".
Based upon what you've currently given me within your question, i made the following query:
SELECT
categories.*,
COUNT(`posts`.`id`) AS `totalPosts`
FROM `categories`
LEFT JOIN `posts` ON `posts`.`category_id` = `categories`.`id`
ORDER BY `categories`.`id` DESC
It basically gets everything from categories and a count of how many posts are within that category. Then we do a left join to get the information that corresponds to the category id, and then we descend it based upon category id DESC (so going downwards).
Correct me if i'm mistaken in what you were asking
I am making a system and I need to see information for each student. When I click the button, I need to know the student's code and open a page (seeStudent.php) with the student's information. Can someone help me?
<?php
$sql = $conn->query("SELECT * from tb_coordinator inner join tb_teacher
on tb_coordinator.cd_coord = tb_teacher.cd_coord
inner join teacher_class on
tb_teacher.cd_teacher = teacher_class.cd_teacher
inner join tb_teacher on
teacher_class.cd_class = tb_class.cd_class
inner join tb_student on
tb_class.cd_class = tb_student.cd_class
where tb_teacher.cd_cpf = '$cpf' and nm_class = '3a1' order by cd_number asc");
while($row = mysqli_fetch_array($sql)){
$nm_student = $row['nm_student'];
$cd_number = $row['cd_number'];
?>
<ul class="list-group list-group-flush" style="width: 50%; margin-top: 2%;">
<div id="load_student">
<li class="list-group-item"><?php echo $cd_number . " - " . $nm_student;?>
Get Information</button></li>
</div>
</ul>
</div>
<?php }?>
You need a bit modification in your prepared HTML. Add your required parameters to the anchor href which might help you to get student details from database in seeStudent.php page.
<ul class="list-group list-group-flush" style="width: 50%; margin-top: 2%;">
<div id="load_student">
<li class="list-group-item"><?php echo $cd_number . " - " . $nm_student;?>
<a href="seeStudent.php?cd_number=<?=$cd_number?>&nm_student=<?=$nm_student?>" >
<button type="button" class="btn btn-outline-info" style="margin-left: 90%;">Get Information</button>
</a>
</li>
</div>
</ul>
If you click Get Information button, it will be taken you to seeStudent.php with two $_GET parameters (cd_number, nm_student).
Now the final task. In seeStudent.php page take the parameter from $_GET array and do other query to get student details from database and to display.
seeStudent.php
<?php
$cd_number = isset($_GET['cd_number']) ? $_GET['cd_number'] : '';
$nm_student= isset($_GET['nm_student']) ? $_GET['nm_student'] : '';
// .... code stuff, possibly query and display
?>
This is my first question and I tried to make it clear enough so you guys/girls can understand it. If I am missing something or doing something wrong please let me know! Its my first question.
What I want:
I want it to show the voornaam out of the table Klanten to show next to the other ones out of the table onderwerpen. For example I want the voornaam to show next to the henk and koken. So I expect it to show the data out 2 different tablesin the block you can see on the pic.
I tried using a foreach loop with 2 conditions but that it not possible. So I was wondering what the solution in this case needs to be. Because It works with 1 condition in the foreach but it is not possible to do this with 2 conditions.
What I have tried:
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Onderwerpen</h3>
</div><!-- /.box-header -->
<div class="box-body">
<?php
$onderrwerp = $app->get_onderwerpen();
$klantten = $app->get_klanten();
foreach($onderrwerp as $onderwerp and $klantten as $klant){
echo '<div class="well well-sm">';
echo '' . $onderwerp['voornaam'].'';
echo '<h3>'.$onderwerp['naam'].'</h3><br>';
echo '' .$onderwerp['naam'].'';
echo '</div>';
}
?>
The code:
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Onderwerpen</h3>
</div><!-- /.box-header -->
<div class="box-body">
<?php
$onderrwerp = $app->get_onderwerpen();
foreach($onderrwerp as $onderwerp){
echo '<div class="well well-sm">';
echo '<h3>'.$onderwerp['naam'].'</h3><br>';
echo '' .$onderwerp['naam'].'';
echo '</div>';
}
?>
The functions:
public function get_onderwerpen(){
$getOnderwerp = $this->database->query("SELECT * FROM onderwerpen ORDER BY id ASC");
$onderwerpen = $this->database->resultset();
return $onderwerpen;
}
public function get_klanten(){
$getKlant = $this->database->query("SELECT * FROM klanten ORDER BY punten DESC");
$klanten = $this->database->resultset();
return $klanten;
}
So you have two tables. they are connected using the ledenpagina_id field I assume looking at your data.
What you are looking for is to JOIN the two tables so that with one query you can fetch the data you want and then do a loop to show the data:
SELECT *
FROM klanten JOIN onderwerpen
ON klanten.lendenpagina_id = onderwerpen.lendenpagina_id
You can then add WHERE clause, ORDER_BY and so on.
Below is the code in question. I'm trying to get a simple division from two columns, but in an already existing (and functioning) php query set up. I can not seem to get it to work no matter what I do. I am not a strong coder by any means. The code outputs a capital S.
<?php
include("db_reader.php");
$data = '';
$query = "SELECT * FROM users WHERE team like 'Replay%'";
if (!$result = mysql_query($query)) {
exit(mysql_error());
}
if(mysql_num_rows($result) > 0)
{
$number = 1;
while($row = mysql_fetch_assoc($result))
{
$kdresult = "SELECT (kills / deaths) AS kdresult FROM users WHERE team like 'Replay%'";
$data .= '
<div class="col-xs-12 col-sm-12 col-md-3">
<div id="memberCard-1" class="card">
<div class="face front">
<div class="panel panel-default text-center" style="border: 1px solid red;">
<div class="panel-heading" style="background-color:#000;color:#ff0000;">
<h3 class="panel-title">'.$row['name'].'</h3>
</div>
<ul class="list-group">
<li class="list-group-item">Position</li>
<li class="list-group-item">Info</li>
<li class="list-group-item"></li>
<li class="list-group-item">Kills: '.$row['kills'].'</li>
<li class="list-group-item">Deaths: '.$row['deaths'].'</li>
<li class="list-group-item">KD: '.$kdresult['kdresult'].'</li>
It looks like your $kdresult is a query but it's not being run anywhere.
Could you change your $query to be:
$query = "SELECT kills, deaths, kills/deaths AS kdresult FROM users WHERE team like 'Replay%'";
It's better practice to specify the columns you actually need in a SELECT statement rather than SELECT *. This also means your data is in a single query and not in two queries.
What I'm trying to do: Where category (projects) matches id (markets) echo category (markets).
Table 1 Sample (projects table)
Table 2 Sample (markets table)
Sample of PHP Code
$num_rec_per_page=5;
if (isset($_GET["page"])) { $page = $_GET["page"]; } else { $page=1; };
$start_from = ($page-1) * $num_rec_per_page;
function GET($key) {
return isset($_GET[$key]) ? $_GET[$key] : null;
}
$category= GET('category');
if ($category !== null) {
$sql = "SELECT * FROM projects WHERE category='$category' LIMIT $start_from, $num_rec_per_page";
} else {
$sql = "SELECT * FROM projects LIMIT $start_from, $num_rec_per_page";
}
$sql_query = mysql_query($sql);
$post = $sql_query;
$sql1 = "SELECT * FROM markets";
$sql_query1 = mysql_query($sql1);
$marketsinfo = mysql_fetch_array($sql_query1);
In my code below, I've tried putting a while loop within the main while loop since we have to find out what category its in then display it for each blog post.
It only worked for the first result, and then I did some research online and found that it is very poor design to do this.
Where I'm currently at with displaying the result (see code in between hyphens):
<!-- Blog - Start -->
<?php while ($post = mysql_fetch_array($sql_query)) {?>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 blog blog_altered blog_left">
<div class="row">
<!-- Blog Image - Start -->
<div class=" col-lg-6 col-md-6 col-sm-10 col-xs-12 pic inviewport animated delay1" data-effect="fadeIn">
<img alt="blog-image" class="img-responsive" src="<?php echo $post['imageoutside'] ?>">
</div>
<!-- Blog Image - End -->
<!-- Blog Info - Start -->
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12 inviewport animated delay1" data-effect="fadeIn">
<div class="info">
----------------------------------------------------------------------
<span class="date">
<?php
if($post['category'] === $marketsinfo['id']){
echo $marketsinfo['category'];
}
?>
</span>
----------------------------------------------------------------------
<h4 class="title"><?php echo $post['title'] ?></h4>
<p><?php echo $post['summary'] ?></p>
<a class="btn btn-primary text-on-primary" href="projects/readmore.php?job=<?php echo $post['job'] ?>">Read More</a>
</div>
</div>
<!-- Blog Info - End -->
</div>
</div>
<?php } ?>
<!-- Blog - End -->
Hope I've been thorough enough without being confusing. How can a noob accomplish this? I'll take any pointers you have!!
If you use a join, you can get the category text in one query and avoid all the looping in PHP.
A LEFT Join will return all records from Projects and only those records which match from markets. So if a projects category doesn't exist in markets, a NULL value will be returned.
If you used a INNER JOIN, only records which have corresponding values in BOTH tables would be returned.
Rule of thumb: get the data you need from the database in 1 trip when you need it. Format in PHP, Datagrab in SQL. Don't get more than you need, and don't get less.
SELECT P.Job, M.ID as Markets_ID, M.Category, P.Title
FROM projects P
LEFT JOIN Markets M
on P.Category =M.ID
WHERE P.category='$category'
LIMIT $start_from, $num_rec_per_page"
Note: you will need to put a table alias on category in the where clause. I'm assuming your passing in the ID so P.Category was used.
do you want join table projects with tables market by category?
may be u can do this
SELECT p.id as id
, m.category as category
from projects as p
left
join markets as m
on p.category = m.id
WHERE m.category='$category'
LIMIT $start_from
, $num_rec_per_page