Home > OS >  Display Results from CSV based on users selection from HTML table in PHP
Display Results from CSV based on users selection from HTML table in PHP

Time:12-03

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 = "&nbsp;";
            }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.

  • Related