I have a basic website that pulls the data from a .csv file and displays only the first column, I am having trouble in creating a way that will let you select one of those values in the first column, to then open a new table of only that entire row's contents.
the table displayed looks like this:
Title |
---|
Book1 |
Book2 |
.... |
Book n |
maybe a dropdown or something that will let you select Book1
and when you click a button will open a new html/php page with the remaining column entries for the Book1
row, as such that table looks like:
Title | Author | Year |
---|---|---|
Book1 | Author1 | 2020 |
Here is the code for the Book Displaying table:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./css/styles.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Book Submission</title></
</head>
<body style="font-family:Verdana;color:#aaaaaa;">
<div style="background-color:#e5e5e5;padding:15px;text-align:center;">
<h1>View Publications</h1>
</div>
<div style="overflow:auto">
<div >
<a href="./index.php">HOME</a>
<a href="./CV.php">CV</a>
<a href="./forecast.php">Weather</a>
<?php session_start();
if(!isset($_SESSION['loggedin']))echo "<a href='./session.php'>Log in</a>";
else {echo "<a href='./session.php'>Admin Panel</a>";}
?>
</div>
<div >
<h2>All Publications on File</h2>
<?php
$row = 1;
if (($handle = fopen("publications.csv", "r")) !== FALSE) {
echo '<table border="1">';
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
if ($row == 1) {
echo '<thead><tr>';
}else{
echo '<tr>';
}
$c=0;
if(empty($data[$c])) {
$value = " ";
}else{
$value = $data[$c];
}
if ($row == 1) {
echo '<th>'.$value.'</th>';
}else{
echo '<td>'.$value.'</td>';
}
if ($row == 1) {
echo '</tr></thead><tbody>';
}else{
echo '</tr>';
}
$row ;
}
echo '</tbody></table>';
fclose($handle);
}
?>
</div>
<div >
<h2>Users </h2>
<?php if(isset($_SESSION['loggedin']))echo "<p> You Are Logged in as an admin</p>";
else {echo "<p> No Admins Logged in!!</p>";}
?>
</div>
</div>
<div style="background-color:#e5e5e5;text-align:center;padding:10px;margin-top:7px;">#STUDENT NUMBER</div>
</body>
</html>
I understand that by modifiying the $c
in the <php>
tag, into a for loop will traverse each column to display a full table, my issue is filtering where row = book chosen by user
CodePudding user response:
Given the constraints that we talked about in the comments, here's one way that I would generally do this.
First, for demo purposes I've removed the CSV file and I'm instead working with an in-memory equivalent, however the fgetcsv
logic is 100% the same.
Second, I broke things into functions. This isn't needed, and now that it has been done you can decompose them back to inline code, but I think this makes it more readable. There's a function to show the table, which calls another function to show the rows, which calls another function to show the individual cells.
Third, I decided to pass the book title in the query string to identify the thing that the person selected. If a book title is duplicated, this will cause both entries to be shown when selected which may or may not be correct. The CSV row index could be used instead of this as discussed in the comments, too.
I think (and hope) that the comments in the code make sense.
function showCell($cell, $isHeader, $selectedTitle)
{
echo '<td>';
if ($selectedTitle || $isHeader) {
echo htmlspecialchars($cell);
} else {
echo sprintf('<a href="?title=%1$s">%1$s</a>', htmlspecialchars($cell));
}
echo '</td>', PHP_EOL;
}
function showRow($cellsToShow, $isHeader, $selectedTitle)
{
if ($isHeader) {
echo '<thead>', PHP_EOL;
}
echo '<tr>', PHP_EOL;
foreach ($cellsToShow as $cell) {
showCell($cell, $isHeader, $selectedTitle);
}
echo '</tr>', PHP_EOL;
if ($isHeader) {
echo '</thead>', PHP_EOL;
}
}
function showTable($handle, $selectedTitle)
{
$idx = 0;
echo '<table>', PHP_EOL;
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
// If we're on the first row which holds titles, always show.
// Also, if the user selected a title, and it matches this row's title, show it.
if(0 !== $idx && $selectedTitle && $row[0] !== $selectedTitle){
continue;
}
// cellsToShow is always an array. If we're showing based on a selection, it is everything.
// Otherwise, it will be an array of just the first cell. This last seems weird, but it
// allows the showRow method to not concern itself with higher level logic.
$cellsToShow = $selectedTitle ? $row : [$row[0]];
showRow($cellsToShow, $idx === 0, $selectedTitle);
}
echo '</table>', PHP_EOL;
}
// Mock a CSV file in memory for demo purposes
$handle = fopen('php://memory', 'rb ');
fwrite($handle, "Title,Author,Year\nBook 1,Alice,2020\nBook 2,Bob,2019\nBook 3,Charlie,1980");
rewind($handle);
// Grab the title from the query string, default to null if not found
$selectedTitle = $_GET['title'] ?? null;
showTable($handle, $selectedTitle);
fclose($handle);
A partial online demo is here (https://3v4l.org/33ose), however that doesn't include clickable links.
I'll also note that although I'm partially encoding things, better care should probably be taken, specifically for things in the URL.