PDO点击删除按钮删除表格行,避免页面刷新问题求助
Hey there! Let's work through fixing this delete button issue step by step—right now, you're getting full page reloads because of how the form is structured, and you're also not passing which specific book to delete. Here's how to fix both problems:
1. Fix the form structure & pass the book identifier
First, your current setup wraps the entire table in one form, so every delete button submits the same generic request. Plus, your SQL query doesn't fetch the book ID, which is essential to tell the server which entry to remove.
- Update your SQL query to include the book ID:
$query = "SELECT Library.id, Library.nameOfBook FROM loginUser JOIN userBook JOIN Library ON userBook.user_id = loginUser.id AND userBook.book_id = Library.id WHERE loginUser.username=:username LIMIT $sql_start, $sql_limit"; - Add per-row forms with hidden book IDs so each delete button targets the right book:
foreach($result as $row){ echo "<tr>"; echo "<td>" . $row['nameOfBook'] . "</td>"; echo "<td>"; // Each delete button gets its own mini-form with the book's ID echo "<form method='POST' style='margin: 0;'>"; echo "<input type='hidden' name='book_id' value='" . $row['id'] . "'>"; echo "<input type='submit' name='delete' value='Delete'>"; echo "</form>"; echo "</td>"; echo "</tr>"; } - Also, fix your broken form closing tag: change
echo "</form";toecho "</form>";
2. Prevent page reload with AJAX (for a smoother experience)
If you want to avoid page refreshes entirely, use AJAX to submit the delete request in the background. Here's how:
- Replace the per-row forms with buttons that carry the book ID as a data attribute:
foreach($result as $row){ echo "<tr>"; echo "<td>" . $row['nameOfBook'] . "</td>"; echo "<td><button class='delete-btn' data-book-id='" . $row['id'] . "'>Delete</button></td>"; echo "</tr>"; } - Add JavaScript to handle the click and AJAX call (put this at the bottom of your page or in a
<script>tag):document.querySelectorAll('.delete-btn').forEach(btn => { btn.addEventListener('click', async function(e) { e.preventDefault(); const bookId = this.dataset.bookId; // Send delete request to your server const response = await fetch(window.location.href, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `delete=true&book_id=${bookId}` }); if (response.ok) { // Remove the row from the table immediately this.closest('tr').remove(); } else { alert('Oops, failed to delete that book.'); } }); });
3. Update your PHP delete logic
Move the delete handling to the top of your getBooks function (before any HTML output) to avoid header issues, and add the actual delete query:
public function getBooks($start = 0, $limit = 2) { // Handle delete request FIRST, before any output if(isset($_POST['delete']) && isset($_POST['book_id'])){ // Delete the book from userBook (link table between user and library) $deleteQuery = "DELETE FROM userBook WHERE book_id = :book_id AND user_id = (SELECT id FROM loginUser WHERE username=:username)"; $deleteStmt = $this->db->prepare($deleteQuery); $deleteStmt->execute([ ':book_id' => $_POST['book_id'], ':username' => $this->username ]); // For AJAX requests, return success status if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'){ http_response_code(200); exit; } // For regular form submissions, redirect to avoid resubmission on refresh else { header("Location: " . $_SERVER['PHP_SELF']); exit; } } // Rest of your existing code for fetching and displaying books... $sql_start = $start * $limit; $sql_limit = $limit; $query = "SELECT Library.id, Library.nameOfBook FROM loginUser JOIN userBook JOIN Library ON userBook.user_id = loginUser.id AND userBook.book_id = Library.id WHERE loginUser.username=:username LIMIT $sql_start, $sql_limit"; $statment = $this->db->prepare($query); $statment->execute([ ':username' => $this->username ]); $result = $statment->fetchAll(); // Output table... }
内容的提问来源于stack exchange,提问作者Second View

