-1

Hi,

Before this is marked as a duplicate question, the others do not apply to my situation at all.

So i am making a simple library system using PHP and HTML. My issue at the moment is that when you search for a book, it executes the SQL query fine and it returns correct results. The issue is that to find out more information about the book, you have to click on a button which does some sql queries and what not, and then opens a modal with the information. This, also, works fine but when you do that, because it executes php code, the page refreshes and the search data is gone and you have to search again to get the same results if you need to. Sorry if i explained it badly i will be happy to elaborate if needs be.

I don't want to use AJAX, I can't use node.js so i really have no clue.

The bit that displays the book:

$library = $_COOKIE["userLibrary"];
if(isset($_GET['search'])){
$author = $_GET['author'];
$title = $_GET['booktitle'];
if($author!='' and $title == '' && mysqli_num_rows(mysqli_query($conn,"SELECT * FROM `$library` WHERE Author LIKE '%$author%' ORDER BY Author"))>0){
echo "<table align='center' class='table table-striped table-hover table-bordered'>";
    $allBooks = mysqli_query($conn,"SELECT * FROM `$library` WHERE Author LIKE '%$author%' ORDER BY Author");
    if(mysqli_num_rows($allBooks)>0){
    echo "<td id='book'><strong>Title</td>";
        echo "<td id='book'><strong>Author</td>";
            echo "<td id='book'><strong>More Information</td>";
                while($row = mysqli_fetch_array($allBooks)){
                //list($row['Title']) = explode("::", $row['Title']);
                $currentCode = $row['InternalBarcode'];
                echo "<tr><td id='book'>".$row["Title"]."</td><td id='book'>".$row["Author"]."</td><td id='book'  align='center'> <form method='get'><input type='hidden' name='action' value='submit' /><input type='hidden' name='more' value=".$row['InternalBarcode']." /><input type='image' src='More.png' name='more' value='".$row['InternalBarcode']."'></form></td>";
                }
            echo "</tr></table>";
        }
    }
    else{
    echo "<table align='center' class='table table-striped table-hover table-bordered'>";
        $allBooks = mysqli_query($conn,"SELECT * FROM `$library` ORDER BY Author");
        if(mysqli_num_rows($allBooks)>0){
        echo "<td id='book'><strong>Title</td>";
            echo "<td id='book'><strong>Author</td>";
                echo "<td id='book'><strong>More Information</td>";
                    while($row = mysqli_fetch_array($allBooks)){
                    //list($row['Title']) = explode("::", $row['Title']);
                    $currentCode = $row['InternalBarcode'];
                    echo "<tr><td id='book'>".$row["Title"]."</td><td id='book'>".$row["Author"]."</td><td id='book'  align='center'> <form method='get'><input type='hidden' name='action' value='submit' /><input type='hidden' name='search'><input type='hidden' name='more' value=".$row['InternalBarcode']." /><input type='image' src='More.png' name='more' value='".$row['InternalBarcode']."'></form></td>";
                    }
                echo "</tr></table>";
            }
        }
    }
    else{
    echo "<table align='center' class='table table-striped table-hover table-bordered'>";
        $allBooks = mysqli_query($conn,"SELECT * FROM `$library` ORDER BY Author");
        if(mysqli_num_rows($allBooks)>0){
        echo "<td id='book'><strong>Title</td>";
            echo "<td id='book'><strong>Author</td>";
                echo "<td id='book'><strong>More Information</td>";
                    while($row = mysqli_fetch_array($allBooks)){
                    //list($row['Title']) = explode("::", $row['Title']);
                    $currentCode = $row['InternalBarcode'];
                    echo "<tr><td id='book'>".$row["Title"]."</td><td id='book'>".$row["Author"]."</td><td id='book'  align='center'> <form method='get'><input type='hidden' name='action' value='submit' /><input type='hidden' name='more' value=".$row['InternalBarcode']." /><input type='image' src='More.png' name='more' value='".$row['InternalBarcode']."'></form></td>";
                    }
                echo "</tr></table>";
            }

The PHP code for the search form:

if(isset($_GET['action'])){
$barcode = $_GET['more'];
//unset($_GET['action']);
$bookTitleA = mysqli_query($conn, "SELECT Title FROM `$library` WHERE InternalBarcode = '$barcode'");
$bookTitle = mysqli_fetch_array($bookTitleA)[0];
$desc = mysqli_fetch_array(mysqli_query($conn, "SELECT Description FROM `$library` WHERE Title = '$bookTitle'"))[0];
$onLoanA = mysqli_query($conn, "SELECT OnLoan FROM `$library` WHERE InternalBarcode = '$barcode'");
$onLoanQuery = mysqli_fetch_array($onLoanA)[0];
$onLoanTo = mysqli_fetch_array(mysqli_query($conn, "SELECT username FROM users where id = '$onLoanQuery'"))[0];
$anyOthers = mysqli_query($conn, "SELECT * from `$library` WHERE Title = '$bookTitle' and OnLoan = '0'");
if($onLoanQuery == '0'){
    global $onLoan;
    $onLoan = 'This book is currently not on loan';
}
elseif(mysqli_num_rows($anyOthers)>0){
    global $onLoan;
    $onLoan = "This book is currently on loan to ".$onLoanTo."<br>There are ".mysqli_num_rows($anyOthers)." more coppies available";
}
else{
    global $onLoan;
    $onLoan = 'This book is currently on loan to '.$onLoanTo."<br>There are no more coppies available.";
}
echo "<script>BookModal(`$bookTitle`, `$barcode`, `$desc`, '$onLoan')</script>";    
}
?>

The Search Form:

<h2 align="center">Search:</h2>
<form action="" method="get">
    <div class="form-group">
        <label for="author">Author:</label>
        <input type="text" class="form-control" name="author" id="author" placeholder="Name of Author"/>
    </div>
    <div class="form-group">
        <label for="booktitle">Title:</label>
        <input type="text" class="form-control" name="booktitle" id="booktitle" placeholder="Title of Book"/>
    </div>
    <input class="form-control" type="submit" name="search" id="search" value="Search">
</form>

Heres the JS if you need it:

function ModalOpen(modalName){
    $(modalName).modal('show');
}
function BookModal(title, barcode, description, available){
    document.getElementById('bookTitle').innerHTML=title;
    document.getElementById('barcode').innerHTML=barcode;
    document.getElementById('desc').innerHTML=description;
    document.getElementById('available').innerHTML=available;
    $('#myModal').modal('show');
}
function ModalClose(modalName){
    $(modalName).modal('hide');
}

I appreciate all your help!

Update

I have decided to use AJAX, Which works, sorta. It works fine for the first row in the table, but for the rest, the modal will still pop up but it shows the same data as the book at the top of the table. It doesn't matter which one i click first, it still only shows the data from the first row in the table.

The bit that displays the books (php):

include 'connect.php';
$library = $_COOKIE["userLibrary"];
if(isset($_GET['search'])){
$author = $_GET['author'];
$title = $_GET['booktitle'];
if($author!='' and $title == '' && mysqli_num_rows(mysqli_query($conn,"SELECT * FROM `$library` WHERE Author LIKE '%$author%' ORDER BY Author"))>0){
echo "<table align='center' class='table table-striped table-hover table-bordered'>";
    $allBooks = mysqli_query($conn,"SELECT * FROM `$library` WHERE Author LIKE '%$author%' ORDER BY Author");
    if(mysqli_num_rows($allBooks)>0){
    echo "<td class='book'><strong>Title</td>";
        echo "<td class='book'><strong>Author</td>";
            echo "<td class='book'><strong>More Information</td>";
                while($row = mysqli_fetch_array($allBooks)){
                //list($row['Title']) = explode("::", $row['Title']);
                $currentCode = $row['InternalBarcode'];
                echo "<tr><td id='book'>".$row["Title"]."</td><td id='book'>".$row["Author"]."</td><td id='book'  align='center'> <form method='get'><input type='button' class='more' src='More.png' value='".$row['InternalBarcode']."'></form></td>";
                }
            echo "</tr></table>";
        }
    }
    else{
    echo "<table align='center' class='table table-striped table-hover table-bordered'>";
        $allBooks = mysqli_query($conn,"SELECT * FROM `$library` ORDER BY Author");
        if(mysqli_num_rows($allBooks)>0){
        echo "<td id='book'><strong>Title</td>";
            echo "<td id='book'><strong>Author</td>";
                echo "<td id='book'><strong>More Information</td>";
                    while($row = mysqli_fetch_array($allBooks)){
                    //list($row['Title']) = explode("::", $row['Title']);
                    $currentCode = $row['InternalBarcode'];
                    echo "<tr><td id='book'>".$row["Title"]."</td><td id='book'>".$row["Author"]."</td><td id='book'  align='center'> <form method='get'><input type='button' class='more' src='More.png' value='".$row['InternalBarcode']."'></form></td>";
                    }
                echo "</tr></table>";
            }
        }
    }
    else{
    echo "<table align='center' class='table table-striped table-hover table-bordered'>";
        $allBooks = mysqli_query($conn,"SELECT * FROM `$library` ORDER BY Author");
        if(mysqli_num_rows($allBooks)>0){
        echo "<td id='book'><strong>Title</td>";
            echo "<td id='book'><strong>Author</td>";
                echo "<td id='book'><strong>More Information</td>";
                    while($row = mysqli_fetch_array($allBooks)){
                    //list($row['Title']) = explode("::", $row['Title']);
                    $currentCode = $row['InternalBarcode'];
                    echo "<tr><td id='book'>".$row["Title"]."</td><td id='book'>".$row["Author"]."</td><td id='book'  align='center'> <form method='get'><input type='button' class='more' src='More.png' value='".$row['InternalBarcode']."'></form></td>";
                    }
                echo "</tr></table>";
            }
        }

The PHP code that the AJAX executes:

<?php
if(isset($_POST["barcode"])){
    $library = $_COOKIE["userLibrary"];
    include 'connect.php';
    $barcode = $_POST['barcode'];
    $bookTitleA = mysqli_query($conn, "SELECT Title FROM `$library` WHERE InternalBarcode = '$barcode'");
    $bookTitle = mysqli_fetch_array($bookTitleA)[0];
    $desc = mysqli_fetch_array(mysqli_query($conn, "SELECT Description FROM `$library` WHERE Title = '$bookTitle'"))[0];
    $onLoanA = mysqli_query($conn, "SELECT OnLoan FROM `$library` WHERE InternalBarcode = '$barcode'");
    $onLoanQuery = mysqli_fetch_array($onLoanA)[0];
    $onLoanTo = mysqli_fetch_array(mysqli_query($conn, "SELECT username FROM users where id = '$onLoanQuery'"))[0];
    $anyOthers = mysqli_query($conn, "SELECT * from `$library` WHERE Title = '$bookTitle' and OnLoan = '0'");
    if($onLoanQuery == '0'){
        global $onLoan;
        $onLoan = 'This book is currently not on loan';
    }
    elseif(mysqli_num_rows($anyOthers)>0){
        global $onLoan;
        $onLoan = "This book is currently on loan to ".$onLoanTo."<br>There are ".mysqli_num_rows($anyOthers)." more coppies available";
    }
    else{
        global $onLoan;
        $onLoan = 'This book is currently on loan to '.$onLoanTo."<br>There are no more coppies available.";
    }
    $thing = "BookModal(`$bookTitle`, `$barcode`, `$desc`, '$onLoan'";  
    echo json_encode(['booktitle' => $bookTitle,
        'barcode' => $barcode,
        'desc' => $desc,
        'onloan' => $onLoan], JSON_FORCE_OBJECT);
    exit();
}
?>

The AJAX code:

$(function(){
    $('.more').on('click', function(){
        var barcodeNum = $('input[class="more"]').val();
        $.ajax({
            type: 'post',
            url: '',
            data: {barcode: barcodeNum},
            success: function(data){
                let allVar = JSON.parse(data);
                let booktitle = allVar.booktitle;
                let desc = allVar.desc;
                let onloan = allVar.onloan;
                let barcode = allVar.barcode;
                document.getElementById('bookTitle').innerHTML=booktitle;
                document.getElementById('barcode').innerHTML=barcode;
                document.getElementById('desc').innerHTML=desc;
                document.getElementById('available').innerHTML=onloan;
                $('#myModal').modal('show');
            },
            error: function(data){
                console.log('error');
                alert('error');
            }
        });
    });
})
  • 1
    Ajax seems ideal for this sort of operation. Why would you not want to use it? – El_Vanja Mar 29 '20 at 17:35
  • Well I need something that can access data from a form, perform SQL queries, send that data back to HTML and im not sure if that is possible, and if it is, probably alot of work. If it is possible and it is the only option, then i will try. – Will O'Shaughnesssy Mar 29 '20 at 17:52
  • It's not the only, but it's definitely the cleanest solution for your use case. You don't have to use it for the entire search, but it would fit in really nicely for showing book details. – El_Vanja Mar 29 '20 at 18:29
  • Ok, Ill give it ago. Ill update the post with the status once ive tried – Will O'Shaughnesssy Mar 29 '20 at 18:36
  • Alternatively you could use Javascript to change the URL `window.location.href = window.location.href + '&more=1';`, and/or PHP to track the current search value in order to pass the term to the more process, IE: ``. Though it would be rather obtrusive to the end-user to load the entire page and show another modal, rather than just load the desired more data-set which can be accomplished via AJAX. – Will B. Mar 29 '20 at 18:51
  • So ive got it all to work... except it only takes the barcode number from the book at the top of the table? – Will O'Shaughnesssy Mar 29 '20 at 21:10
  • So the barcode number doesnt change no matter what book you click on – Will O'Shaughnesssy Mar 29 '20 at 21:11
  • Can you edit the question to show current code you're having problems with? – El_Vanja Mar 29 '20 at 21:53
  • Insted of `$('input[class="more"]').val()` try `$(this).val()`. – El_Vanja Mar 30 '20 at 09:46

2 Answers2

1

The fault with your AJAX was using $('input[class="more"]').val(). This always selects the value of the first element with that attribute. Setting it to $(this).val() will get the value of the clicked element (this represents the element that triggered the handler).

I'd like to use this opportunity to point out some improvements that can be made in your code. There's a lot of clutter and duplication.

General advice

1) Don't insert parameters directly into the query. That makes you open to SQL injection. Since you're already using mysqli, you should switch to prepared statements. I am keeping your original unsafe queries in further examples, but you should replace them with a safe version.

2) Same goes for the table name you keep in the cookie (although I don't know why you'd do that). Cookies can be compromised. I suggest you rather place some other unique value in the cookie which you then translate into a table name. For example, if your table name was main_library, you can store main in the cookie and then do a switch in php to get the actual name. If the cookie value cannot be translated, then do nothing.

3) Always check if your query has succeeded. Right now, you only check mysqli_num_rows, but that function expects a mysqli_result as a parameter, but a failed query will be a boolean false, leading to an error.

Concerning your book displaying script:

1) You print a lot of these: <td id='book'>. I assume you meant to make that a class, not an id. Ids should be unique. Furthermore, if all your cells have that class, then they shouldn't have it. Whatever parent structure can encapsulate that style (table row or maybe the table itself) should have the class and then you can style the cells by specifying .book td. That way you don't have to apply the class to each individual cell.

2) When you use get, check if every parameter is set (currently you only check if search is set. So to avoid undefined index notices, do something like this to give your variables a default value:

$author = isset($_GET['author']) ? $_GET['author'] : '';
// or use a shorter equivalent with the null-coalescing operator like this
$author = $_GET['author'] ?? '';

3) The rest of the code can be restructured to remove unnecessary duplication. Instead of using the exact same html output in every if-else branch, use the branch only to define your query:

// this is the default query, so it can be set right at the start
$allBooks = "SELECT * FROM `$library` ORDER BY Author";
if(isset($_GET['search'])){
    $author = $_GET['author'] ?? '';
    $title = $_GET['booktitle'] ?? '';
    if ($author !== '' and $title !== '') {
        // here we just overwrite it if we have all the necessary parameters
        $allBooks = "SELECT * FROM `$library` WHERE Author LIKE '%$author%' ORDER BY Author";
    }
}

And then afterwards execute the query and use the html output once with the result of the query.

Concerning your script called by AJAX:

1) Here you are making three queries to pull three columns from the same table:

$bookTitleA = mysqli_query($conn, "SELECT Title FROM `$library` WHERE InternalBarcode = '$barcode'");
$bookTitle = mysqli_fetch_array($bookTitleA)[0];
$desc = mysqli_fetch_array(mysqli_query($conn, "SELECT Description FROM `$library` WHERE Title = '$bookTitle'"))[0];
$onLoanA = mysqli_query($conn, "SELECT OnLoan FROM `$library` WHERE InternalBarcode = '$barcode'");

It should all be done in a single query with SELECT Title, Description, OnLoan ....

2) There is no need to make $onLoan global. You're using it in the output of the script, so you can simply delete all those lines.

3) You don't need the exit either, because you've already reached the end of the script.

4) $thing = "BookModal($bookTitle, $barcode, $desc, '$onLoan'"; looks like a leftover since it isn't used anywhere in the script.

Concerning your javascript:

1) Prefer using const and let over var. I see you using let, so you must be at least partially familiarized with them. I'd advise you to turn var barcodeNum into const barcodeNum.

2) You don't need all those variables in the success function. All you really need is const allVar = JSON.parse(data); (note that I changed it to const since you never need to reassign it). Then you can just use its properties directly and avoid unnecessary initialization of several variables which you only use once:

document.getElementById('bookTitle').innerHTML = allVar.booktitle;
El_Vanja
  • 3,660
  • 4
  • 18
  • 21
0

I used

$('.btn').on('click', function()