1

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 class="menu">
    <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 class="main">
  <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 class="right">
    <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

6
  • If your data is simple enough, and/or you don't have a lot of rows, you could just stash the additional columns as custom HTML attributes on the row, and then retrieve them using JavaScript. Another option is to just use the row $variable as the index to pass to the next page, and repeat your same process to "find" that row. If possible, I'd also encourage you to look into a database. Commented Dec 1, 2022 at 20:13
  • @ChrisHaas my table is 5 columns and as infite rows as the user creates. would that still work, Oh yes i have achieved this using sql database but the assignment im workin on explicitly mentions csv and "implementation using database will not be marked" Commented Dec 1, 2022 at 21:40
  • Assignments often have arbitrary limits in place, often going against best practices (and I get why), so it is also hard to know what other "good ideas" they might not allow. But I understand your given constraint. Are you using pagination in anyway? If not, then for an infinite amount of records I'd argue that performance isn't a major issue and I think that storing the additional data in an attribute is totally fine, HTTP compression should do a good job helping. The alternatives are the previously mentioned index, or just passing the title to the lookup page if it is unique. Commented Dec 2, 2022 at 13:55
  • @ChrisHaas negative, just simply listing them as the come, I highly doubt it would be filled with more than 10 records anyways, I was also thinking my previous while loop traverses the csv by column then displaying all the rows for that column and moving on to the next, if i were to switch it to traverse rows first i could limit the number of rows displayed by setting a variable to that number. thoughts? Commented Dec 2, 2022 at 16:06
  • Unless I'm misunderstanding, you are traversing by row already? fgetcsv gets you each row. Commented Dec 2, 2022 at 16:51

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Appreciate the time and effort on this! thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.