i was always curious about how many websites have a delete button on their user panels.
For example, if a user can submit a post and this must be available on his user control panel to delete it if he wants how would you code this button without any frameworks in php?
What i've dont now its creatre a form with a hiden value, you can see a piece of the code below:
<?php foreach ($results as $result): ?>
<tr>
<td> <?php echo $result['id'] ?> </td>
<td> <?php echo $result['message'] ?> </td>
<td> <?php echo $result['name'] ?> </td>
<td>
<form method="POST" action="">
<input type="checkbox"
name="delete_action"
value="<?= $result['id'] ?>"
style="display:none; visibility:hidden;"
checked>
<input class="" type="submit" value="Delete">
</form>
</td>
</tr>
Time for the php action:
if (isset($_POST['delete_action'])) {
$get_id_to_delete = $_POST['delete_action'];
$delete_action = $pdo_testimonials->prepare("DELETE FROM testimonials WHERE id = :id");
$delete_action->bindParam(':id', $get_id_to_delete);
$delete_action->execute();
}
So, as you can see the methond is so insecure and easy to mess up. However i've used it only for a control panel which only i have access. I know that i should never use a similar way of adding a delete button on a production website.
Is there any better, more secure and reliable way to do it?
Simple link (GET) showing only when it's content that current user can remove is ok, as long as you check that in PHP again. So:
Check if current user can remove element.
If so, display (image) link to for example /delete.php?id=2.
On page delete.php check if current user can remove element with id = 2.
If so, remove element and get back to page. Otherwise display warning.
It can be done with AJAX too, with same steps.
Related
I have a dynamic table which is set inside a foreach, so for each item of the array fetched create a new row. I have in the last column a button for each row. When clicking that submit button I am suppose to receive the id of that in PHP. Submission is being done correctly, but I am receiving the wrong id in PHP. Its basically taking the last id of the array when submitting. Any idea why?
Here is the table:
<form method="post" id="frm-example" action="<?php echo $_SERVER["PHP_SELF"] . '?' . e(http_build_query($_GET)); ?>">
<table id="example" class="display compact">
<thead>
<th>Device</th>
<th>Sales date</th>
<th>Client comments</th>
<th>Breakage count</th>
</thead>
<tbody>
<?php foreach ($arr_cases_devices as $cases) { ?>
<tr>
<td>
<?php echo $cases['name']; ?>
</td>
<td>
<?php echo $cases["sales_date"]; ?>
</td>
<td>
<?php echo $cases["dev_comment"]; ?>
</td>
<td>
<input type="hidden" name="device_id_breakage" value="<?php echo $cases["Dev_Id"]; ?>" />
<button type="submit" name="see_rma">See RMA</button>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</form>
When clicking on see_rma this is what I receive in PHP:
if (isset($_POST['see_rma'])) {
$selected_dev = e($_POST['device_id_breakage']);
print_r($selected_dev); // prints the "Dev_Id" of the last row, not of the row clicked
}
If I try printing $cases["Dev_Id"]; inside loop in the table, it prints perfectly fine, so it prints the Dev_Id of each row correctly. So, that means there is nothing wrong with the array or data. I don't why is this happening but it's for sure the first time I am having this issue.
I do this in many other tables but for some reasons in this one its not working properly.
You have multiple <input> elements with the same name within your form, and all of them are going to be submitted when you submit the form, but PHP can only get one of them. That's why you end up with only the last one in $_POST.
It looks like you should be able to fix this by just moving some attributes from the hidden input into the button (replacing the hidden input).
<button type="submit" name="device_id_breakage" value="<?php echo $cases["Dev_Id"]; ?>">
See RMA
</button>
Only the button that was clicked will be submitted. Note that after changing the name of the button, you won't have see_rma in $_POST any more, so if you have any code that depends on that you'll need to change it to look for the other name instead.
I'd like to know if there is a way to pass a record id to another page without showing in the URL (using $_GET).
This is my code:
<table class="table table-bordered">
<thead>
<tr>
<td>#</td>
<td>Sigla</td>
<td>Nome</td>
<td>Bilancio</td>
<td>Responsabile</td>
<td>Azione</td>
</tr>
</thead>
<tbody>
<?php foreach ($rows as $row): ?>
<tr>
<td><?=$row['id']?></td>
<td><?=$row['sigla']?></td>
<td><?=$row['nome']?></td>
<td><?=$row['bilancio']?></td>
<td><?=$row['responsabile']?></td>
<td class="actions">
<a href="update.php?id=<?php echo $row['id']; ?>" class="edit">
<i class="fas fa-pen fa-xs"></i>
</a>
<a href="delete.php?id=<?php echo $row['id']; ?>" class="trash">
<i class="fas fa-trash fa-xs"></i>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
As you can see for each record i create an <href> with the redirect to the "delete" or "update", so i will pass the id via $_GET.
Is there a way to not show the id in the URL?
You need AJAX or a form
Using a link to delete is VERY dangerous since once viist from a crawler and your database is corrupt
I suggest something like this
delegate the click to the container table
use data-attributes for the ID
Ajax using POST - I use fetch to do that here
let fetchData = {
method: 'POST'
}
const url = "delete.php";
document.querySelector("form").addEventListener("click", function(e) {
const tgt = e.target;
if (tgt.classList.contains("trash") && confirm("Delete "+this.id+"?")) {
e.preventDefault();
fetchData["body"] = {
"id": this.getAttribute("data-id")
};
fetch(url, fetchData)
.then(function() {
console.log("deleted");
});
}
})
<a href="#" data-id="<?php echo $row['id']; ?>" class="trash">
<i class="fas fa-trash fa-xs"></i>
</a>
The id being shown in the URL is an absolute non-issue. That doesn't make the delete operation any more secure or insecure. What you have are one, perhaps two, other issues:
Any destructive operation must use POST requests. Normal links are free to be crawled by search engines, or preloaded by browsers. Which means, as soon as Google has crawled all your links, your database will be empty. That's why using POST is important, because every properly behaved HTTP client understands that POST is destructive.
If you're asking this question because you're afraid users can simply manipulate the id shown in the URL and delete other records they're not supposed to delete, then your real issue isn't in where you pass the id, but that you have no permission checking on your server.
For starters, use a form to create POST requests:
<form action="delete.php?id=<?php echo htmlspecialchars(urlencode($row['id'])); ?>"
method="post">
<input type="submit" value="Delete">
</form>
(Also note the proper way to URL-encode and HTML-encode the value, since you're embedding it in a URL in the context of HTML.)
On the PHP side, you'd process this something like this:
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$id = $_GET['id'];
// permission checking here
// delete record here
}
Instead of transporting the ID as a query parameter, you could also make it a form field:
<form action="delete.php" method="post">
<input type="hidden" name="id" value="<?php echo htmlspecialchars($row['id']); ?>">
<input type="submit" value="Delete">
</form>
On the server you'd then take the value from $_POST['id'] instead of $_GET['id'].
Note that this does not fundamentally change anything and is mostly a matter of taste.
You can customise that drab submit button in various ways, or perhaps switch to more interactive Javascript; but those are all just ways to pretty up this basic operation.
You can do it by something like this https://laravel.com/docs/5.8/encryption
At back-end you have to encrypt all your parameters like the following code:
$encryptedParameters = encrypt([
'id' => 132,
'something' => 'value',
'another_key' => 'another_value',
]);
and then send this value to your html template.
At front-end if you want to do it by GET do something like this and your users can't see what are you sending to your back-end because it is encrypted:
and if you want to do it by POST you can do it by Ajax or by generating a form and putting this value as a hidden input inside it. and then when user clicked on this link at back-end you have to decrypt it and use it's values like the following code:
$decryptedParameters = decrypt($_GET['s']);
$id = $decryptedParameters['id'];
$something = $decryptedParameters['something'];
$another_key = $decryptedParameters['another_key'];
Convert the GET request to a Post using a hidden form submission, a preferred method is to encrypt the record id when submitting the data.
I have an PHP page, which contains a form with some different input fields, e. g. day, month, year etc.. The form method is POST, only one non-editable field (The user ID) is sent via GET.
Of course, there is a "Submit"-Button, which triggers the form Action (PHP Script on Server).
The form tags contain a table with empty cells too. Now comes my question:
If the user clicks into one of the table cells, the form should be submitted, but additional to the regular form data the ID of the table cell should be transmitted too (If via POST or GET doesn't matter to me). How can I do that?
//Edit 2:
...
<form method="post" action="<?= DOMAIN?>/.../addUserTimetable.php?uid=<?= $user->getUserID() ?>">
<select id="day" name="day">
...
</select>
...
<input name="yearend" id="yearend" ...>
<button type="submit">...</button>
<table class="bordered">
<tr>
<th>Std.</th>
<th>Montag</th>
<th>Dienstag</th>
<th>Mittwoch</th>
<th>Donnerstag</th>
<th>Freitag</th>
</tr>
<?php
for($i=1; $i<13;$i++) {
echo "<tr>";
echo "<th>".$i. "</th>";
for($j=1;$j<6;$j++) {
echo "<td id='h".$i. "d".$j. "' onclick='???'></td>";
}
echo "</tr>";
}
?>
</table>
</form>
...
The server sided procession is fine, but I haven't got any ideas - even after two hours google - how I could transmit the cell id additionally.
That shouldn't be to hard. Have a look at the following example:
<form>
<input type="text" name="something">
<table>
<tr>
<td><input type="submit" name="cel1">
</tr>
<tr>
<td><input type="submit" name="cel2">
</tr>
<tr>
<td><input type="submit" name="cel13">
</tr>
</table>
<input type="submit" value="save">
</form>
By giving the submit buttons in the table cells a name attribute, that name will also be present as a key on the $_REQUEST. Go ahead and var_dump the $_REQUEST and you'll see you can find out in the backend which button got pushed by checking which key exists.
Note that POST / GET is completely irrelevant here, both will work just the same. And obviously you could apply some css to those buttons to make them transparent and lay them on top of the table cells, so they don't look like buttons, but just "capture" the user's click.
One last side note, are you sure you want to send the userID as a GET parameter? That would be very easy for someone with bad intentions to manipulate. Consider not sending the ID at all, but keeping it in the session on the server.
I have this chunk of code, which is displayed on a user's journal page. They can add an entry and they have the option to delete an entry once it's on the page.
Ill show the code with some comments and then explain the problem.
// Figures out how many recent posts to display
$posts = $config_journalposts + 1;
if($noposts!=1) {
// Gets the data from the query
while(($row = mysql_fetch_array($journalquery)) && ($posts > 1)) {
// For each of the posts that were gathered, display the following:
echo '<table border="0" width="100%">
<tr>
<td colspan="2" style="vertical-align:bottom;">
// Display the title as a link to be used as a permalink
<p class="fontheader">'.$row['title'].'</p>
</td>
</tr>
<tr>
// Show the o-so-important content
<td width="100%" style="vertical-align:top;padding-left:10px;">
'.$row['content'].'
</td>
</tr>
<tr>
// Show the date
<td style="font-size:8pt;padding-top:10px;">'.$row['date_day'].'/'.$row['date_month'].'/'.$row['date_year'].'</td>';
// Checks if the current user is the owner of the journal or an admin
if($_SESSION['user']==$pageowner || $_SESSION['user_rank']=='Admin') {
echo '<td align="right">
// FOCUS POINT
<form method="POST" id="deljournal">
<input type=\'hidden\' name=\'delete_id\' value=\''.$row['id'].'\' />
// A delete button that executes a bit of Javascript
<button type="button" class="button" name="delete" value="Delete" onClick="delete_journal()" />Delete</button>
</form>
// END FOCUS POINT
</td>';
}
echo '</tr>
</table>
<hr>
';
$posts --;
}
Here is the Javascript that gets triggered on the button press
function delete_journal() {
var answer = confirm("Are you sure you want to delete this journal entry?")
if (answer){
// Submits the form
$("#deljournal").submit()
}
}
This javascript triggers the forum in the PHP code above which reloads the page and triggers this at the very top of the page, before the tag
if(($_POST['delete_id'])) {
// Gets the post ID from the hidden forum tag
$deleteid = addslashes(strip_tags($_POST['delete_id']));
// Deletes the row that has the ID of the hidden form
mysql_query("DELETE FROM `gamezoid_accounts`.`journal_$pageowner` WHERE `id`='$deleteid'");
}
Now, for the problem. In the while loop, this form gets repeated over and over. What happens is that upon pressing the delete button, it triggers the form that has the ID "deljournal". Since all of them have the ID "deljournal" it does the one at the top of the page. Trying to embed the post ID into the form ID breaks the code because the mysql_query doesn't know that the delete function has been triggered in the first place.
Any way around this?
Reason why I'm using Javascript as a trigger is for the confirmation popup in case anyone askes.
Anyways, thanks heaps for reading this far!
<input type=\'hidden\' name=\'delete_id[]\' value=\''.$row['id'].'\' />
then only u will get all the values as array when posted.
<input type=\'hidden\' name=\'delete_id[]\' value=\''.$row['id'].'\' />
then only u will get all the values as array when posted.
and on server side u should use
$delete_values= implode (',',$_POST['delete_id']);
Found a solution.
I have changed the form to be
<form method="POST" id="deljournal_'.$row['id'].'">
<input type=\'hidden\' name=\'delete_id\' value=\''.$row['id'].'\' />
</form>
<button type="button" class="button" name="delete" value="Delete" onClick="delete_journal_'.$row['id'].'()" />Delete</button>
by adding the journal entry ID into the ID of the form and the onClick function. The javascript is just below it outside the table cell and looks like:
<script type="text/javascript">
function delete_journal_'.$row['id'].'() {
var answer = confirm("Are you sure you want to delete this journal entry?")
if (answer){
$("#deljournal_'.$row['id'].'").submit()
}
}
</script>
where the entry ID has been added to the function name and form ID tag. By putting the Javascript into a while loop and not into an external file, it can be manipulated with the loop to have the same values.
It is a bit messy and will slightly increase load times + execution times but it was the quickest way that I could find.
Hope this helps anyone else who has been having a similar problem.
I am building an iframe based - facebook application. My problem is, whenever I redirect user to any page, I can see pages are loaded twice. (first, it shows the page without css and then again page is loaded with css). Same is happening when I post any form.
So, every form is posted twice. Data is added twice for each and every action. Moreover, I can see all my POST data in url... facebook is passing all session data in URL. Is it normal?
Am I missing something? Please help me. Below is my code.
foreach($records as $product_list)
{
?>
<tr>
<td width="250">
<form name="frm_product_<?php echo $product_list->product_id; ?>" id="frm_product_<?php echo $product_list-> product_id; ?>" action="cart.php">
<?php echo $product_list->product_name; ?><br />
Price : <?php echo $product_list->price; ?> SGD<br />
<input type="hidden" name="product_id" value="<?php echo $product_list->product_id; ?>" />
<input type="submit" name="btn_submit_<?php echo $product_list->product_id; ?>" id="btn_submit_<?php echo $product_list->product_id; ?>" value="Add to Cart" />
<input type="hidden" name="action" value="add" />
</form>
</td>
</tr>
<tr>
<td> </td>
</tr>
<?php
}
?>
if(isset($_REQUEST['action']) && $_REQUEST['action']=='add')
{
$cart = new Cart($db);
$cart->user_id = 1;
$cart->product_id = $_REQUEST['product_id'];
$cart->qty = 1;
$cart->add_to_cart1(); //this is adding items two times
}
Thanks in advance.
For double post problems always check you do not have somewhere an image href set to '' (empty string).
It colud be an or an url() in a css.
This is not an issue but a design decision in HTTP, empty GET url (like an empty image src) means redio the request that get you on the page (that could be a POST).
It's maybe not your case, but last time I was it by that it took me 3 days to find :-)