2

In my home page, I have a search bar with a button at the top of my page and I displayed all my songs using their title from my database underneath that.

The search bar is working fine since every song title I typed, it took me to the correct detail page.

I'm just wondering how can I also click on the song title and take me to each song detail page.

Home page

<?php
require_once '../config.php';
$sql = 'SELECT title FROM song ORDER BY title ASC;';
$stmt = $conn->prepare($sql);
$stmt->execute(['title' => $title]);
// fetch all rows
$songTitle = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>


//Search bar

<form action="chord/details.php" method="post" class="p-3">
  <div class="input-group">
            <input type="text" name="search" id="search" class="form-control form-control-lg rounded-0 border-primary width =250px;" placeholder="Search..." autocomplete="off" required>
            <div class="input-group-append">
              <input type="submit" name="submit" value="Search" class="btn btn-primary rounded-right">
            </div>
   </div>
</form>



// Here I display all my songs from the database using their title
<?php 
    foreach ($songTitle as $song) {

      // I'm not sure how to modify here.
     echo "<a href='chord/details.php'>{$song['title']} <br> </a>";
} ?>

Details page

//This is working fine with Search Bar
<?php
require_once '../config.php';
if (isset($_POST['submit'])) {
  $title = $_POST['search'];
  $sql = 'SELECT * FROM song WHERE title = :title';
  $stmt = $conn->prepare($sql);
  $stmt->execute(['title' => $title]);
  $row = $stmt->fetch();

} else {
  header('location: .');
  exit();
}
?>

//Display the song lyrics here
<div>Original Key: <?= ucfirst($row['chord']) ?></div><br>
<pre data-key=<?= ucfirst($row['chord']) ?> id="pre">
              <?= ucfirst($row['lyrics']) ?>
</pre>

ziico
  • 449
  • 8
  • 23
  • If you aren't actually adding any placeholders to a prepared statement, then there is nothing to bind -- so there shouldn't be any parameters fed into `execute()`. If you have nothing to bind, then you don't need a prepared statement at all; just query normally without the overhead of a prepared statement. You are effectly asking several questions. How to use `http_build_query()` to form a query string? and How to query your database for an id? These are basic questions that have already been answered many times on Stack Overflow. – mickmackusa Mar 11 '22 at 01:55
  • Related: https://stackoverflow.com/questions/42833952/how-get-data-from-mysql-database-by-specific-id-in-url , https://stackoverflow.com/q/32462526/2943403 – mickmackusa Mar 11 '22 at 02:05
  • https://stackoverflow.com/questions/12097334/getting-mysql-id-from-url-to-display-information-on-page , https://stackoverflow.com/q/41799274/2943403 – mickmackusa Mar 11 '22 at 02:14
  • "I'm not sure how to modify here." - what do you want to achieve? What have you tried so far? Is this a HTML problem, a PHP problem, or an SQL problem? I doubt that the problem itself is really related to all three technologies – Nico Haase Mar 11 '22 at 08:19

2 Answers2

2

You can use the get HTTP method to send the id of the song to the details.php page and query to the database on that id.

And it's always a good practice to use the GET HTTP method for searching actions. As mickmackusa said in the comment:

$_POST is most appropriate when "writing" data server-side. $_GET is most appropriate when "reading" data server-side.

So change the code on the Home page as below:

<?php
require_once '../config.php';
// query changed to fetch id as well
$sql = 'SELECT id , title FROM song ORDER BY title ASC;';
$stmt = $conn->prepare($sql);
$stmt->execute(['title' => $title]);
// fetch all rows
$songTitle = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>


<!-- here we change the method to get -->
<form action="chord/details.php" method="get" class="p-3">
  <div class="input-group">
            <input type="text" name="search" id="search" class="form-control form-control-lg rounded-0 border-primary width =250px;" placeholder="Search..." autocomplete="off" required>
            <div class="input-group-append">
              <input type="submit" name="submit" value="Search" class="btn btn-primary rounded-right">
            </div>
   </div>
</form>


<?php 
    foreach ($songTitle as $song) {
        // we add the id to the link
        echo "<a href='chord/details.php?id={$song['id']}'>{$song['title']} <br> </a>";
    } 
?>

And change the detail.php like below:

<?PHP
//This is working fine with Search Bar
require_once '../config.php';

if (isset($_GET['search']) OR isset($_GET['id'])) {

    $condition = "";
    $value = "";
    if (!empty($_GET['id'])) {
        $condition = "id = :value";
        $value = $_GET['id'];
    }
    elseif (!empty($_GET['search'])) {
        $condition = "title = :value";
        $value = $_GET['search'];
    }

    $sql = 'SELECT * FROM song WHERE ' . $condition;
    $stmt = $conn->prepare($sql);
    $stmt->execute(['value' => $value]);
    $row = $stmt->fetch();


} else {
    header('location: .');
    exit();
}

?>

//Display the song lyrics here
<div>Original Key: <?= ucfirst($row['chord']) ?></div><br>
<pre data-key=<?= ucfirst($row['chord']) ?> id="pre">
              <?= ucfirst($row['lyrics']) ?>
</pre>

It's also a good idea to use LIKE for searching in the title like below:

if (!empty($_POST['search'])) {
    $condition = "title LIKE :value";
    $value = "%" . $_POST['search'] . "%";
}
sajjad rezaei
  • 945
  • 1
  • 10
  • 23
  • `isset(..) and !empty(...)` is an antipattern that should not exist in any code for any reason. [Why check both isset() and !empty()](https://stackoverflow.com/a/4559976/2943403) To comply with PSR-12 coding standards, `else if` should always be `elseif`. `$_POST` is most appropriate when "writing" data server-side. `$_GET` is most appropriate when "reading" data server-side. All of these actions are only reading, so `$_GET` should be used consistently. – mickmackusa Mar 11 '22 at 01:59
  • @sajjadrezaei I just noticed that some reason my Search bar searching is not able to fetch anymore. any idea why it might be? – ziico Mar 11 '22 at 02:31
  • @mickmackusa yes I know `empty` check to be `isset` as well but I don't know I mostly check both, I think it's kind of an obsession for me. Thank you for your guide I update the answer. – sajjad rezaei Mar 11 '22 at 07:58
  • @ziico Sorry my bad. I messed up with the keys in `detail.php` I did use the `submit` key as a value that I should use the `search` key. I update the answer based on comments. – sajjad rezaei Mar 11 '22 at 08:00
0

Assuming you have an id column in the song table. You could do something like this:

<?php
require_once '../config.php';
$sql = 'SELECT id, title FROM song ORDER BY title ASC;';
$stmt = $conn->prepare($sql);
$stmt->execute();
// fetch all rows
$songTitle = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>


//Search bar

<form action="chord/details.php" method="post" class="p-3">
  <div class="input-group">
            <input type="text" name="search" id="search" class="form-control form-control-lg rounded-0 border-primary width =250px;" placeholder="Search..." autocomplete="off" required>
            <div class="input-group-append">
              <input type="submit" name="submit" value="Search" class="btn btn-primary rounded-right">
            </div>
   </div>
</form>



// Here I display all my songs from the database using their title
<?php 
    foreach ($songTitle as $song) {

      // I'm not sure how to modify here.
     echo "<a href='chord/details.php?id=".$song['id]."'>{$song['title']} <br> </a>";
} ?>

Details page

//This is working fine with Search Bar
<?php
require_once '../config.php';
if (isset($_POST['submit'])) {
  $title = $_POST['search'];
  $sql = 'SELECT * FROM song WHERE title = :title';
  $stmt = $conn->prepare($sql);
  $stmt->execute(['title' => $title]);
  $row = $stmt->fetch();

} elseif (!empty($_REQUEST['id'])) {
  $sql = 'SELECT * FROM song WHERE id = :id';
  $stmt = $conn->prepare($sql);
  $stmt->execute(['id' => $_REQUEST['id']]);
  $row = $stmt->fetch();
} else {
  header('location: .');
  exit();
}
?>

//Display the song lyrics here
<div>Original Key: <?= ucfirst($row['chord']) ?></div><br>
<pre data-key=<?= ucfirst($row['chord']) ?> id="pre">
              <?= ucfirst($row['lyrics']) ?>
</pre>
imtheman
  • 4,713
  • 1
  • 30
  • 30