You're trying to call a PHP function (with several issues) from a Javascript event handler. That won't work. You need to use AJAX to send your Javascript action along to a PHP script, and read the response from that.
Let's first think about what you need to do in Javascript:
- When the button for a row is clicked, collect all (potentially modified) values for that row, and send it to a PHP script;
- After sending the values to PHP, you'll want to prevent the user from making further changes until that PHP script is finished.
- When the PHP script is done, allow the user to make further changes again. If the update wasn't successful, tell the user.
Disclaimer: The code examples below are untested. They should help you get on the right track though. If the PHP code does not give you any output, make sure error reporting is enabled so you can see what's going wrong.
Step 1: Preparing your HTML
To be able to collect the values for the row, we need an identifier to select them by. Your <input>
s currently don't have one, which will make things more difficult. So let's change that by adding unique id
attributes we can find easily:
<td class="cellL"><input id="' . $r['code'] . '_category" type="text" style="width: 80px" name="category" value="' . $r['category'] . '"></td>
<td class="cellL"><input id="' . $r['code'] . '_type" type="text" style="width: 140px" name="type" value="' . $r['type'] . '"></td>
<td class="cellL"><input id="' . $r['code'] . '_size" type="text" style="width: 300px" name="size" value="' . $r['size'] . '"></td>
You're already calling an editId
function when a cell is clicked, but looking at your data, $r['code']
is a string and your current code will not send it as a string. That will give an error, so we need to add quotation marks around it (since you're already using single quotes for your echo, we need to escape our new ones). Also, setting the onclick
handler on a <td>
is bad practice, it would be better to create a button for it:
<td class="buttonR"><button id="' . $r['code'] . '_button" type="button" onclick="editId(\'' . $r['code'] . '\');">' . $r['code'] . '</button></td>
Note: <button>
elements have a default type
of submit
, which we don't want in this case. I added an id
which we'll need later.
Step 2: Preparing your Javascript
Now that we have our HTML prepared, it's time to move on to the Javascript. I'm assuming you have jQuery available on your page.
Our JS function will need to accept one argument (the $r['code']
value for that row) and collect the values for that row into an object. It will then need to block the <input>
s and the <button>
so the user can't make any changes while PHP is busy, before sending the object to the server.
When the server responds, it will need to re-enable the <input>
s and <button>
. Now, if PHP successfully updated the data, no further action is needed. But if there was a problem, we'll want to alert the user that something went wrong.
<script type="text/javascript">
function editId(code) {
// get the button
var button = $('#' + code + '_button'),
category = $('#' + code + '_category'),
type = $('#' + code + '_type'),
size = $('#' + code + '_size');
// disable them all so the user can't interact anymore
button.prop('disabled', true);
category.prop('disabled', true);
type.prop('disabled', true);
size.prop('disabled', true);
// build the object we're going to send to PHP
var data = {
"code": code,
"category": category.val(),
"type": type.val(),
"size": size.val()
};
// send the object to PHP
$.post(
'/update.php',
data
).fail(function() {
alert('Failed to update row ' + code);
}).always(function() {
// whether successful or failed, always re-enable the button and inputs
button.prop('disabled', false);
category.prop('disabled', false);
type.prop('disabled', false);
size.prop('disabled', false);
});
}
</script>
Step 3: Preparing your PHP
Note that in the Javascript function we're calling "/update.php". You can place name this PHP file wherever you want, just make sure the path in the Javascript function matches.
Our Javascript function is expecting an error if the update fails. That means sending a response header from PHP with a status code that's not in the 200-range. We'll be doing that with the header()
function. The benefit of this method is that if we mess up our PHP code, the server will send a 500 internal server error, which our JS function will catch as well.
Our script is only going to try to update if all values are posted, so we need to check for that. Our JS is not going to do anything with the result, so we don't need to send any output. We're going to anyway, in case we need to do some debugging later. You can use your browser's network inspector to check the result you get from the AJAX call.
<?php
// I'm assuming your dbh_*** functions are somewhere in another PHP
// file you need to include here at the top. I'm also assuming
// dbh_get() returns a PDO database. If it returns a mysqli database,
// you'll need to change the binding of the parameters and the check
// for the number of affected rows accordingly.
// first make sure we're handling a POST request
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('HTTP/1.1 405 Method Not Allowed');
echo 'Request method must be POST, this is a ' . $_SERVER['REQUEST_METHOD'] . ' request.';
die();
}
// make sure all the properties we're expecting are submitted
$expected = array('code', 'category', 'type', 'size');
foreach ($expected as $property) {
if (!isset($_POST[$property])) {
header('HTTP/1.1 406 Not Acceptable');
echo 'Missing a value for ' . $property;
die();
}
}
// now we can update our row in the database
$dbh = dbh_get();
$sql = "
UPDATE `table`
SET `category` = :category,
`type` = :type,
`size` = :size
WHERE `code` = :code
";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
':category' => $_POST['category'],
':type' => $_POST['type'],
':size' => $_POST['size'],
':code' => $_POST['code']
));
if ($stmt->rowCount() == 0) {
dbh_free($dbh);
header('HTTP/1.1 204 No Content');
echo "No changes were made, either there is no row with code '" . $_POST['code'] . "' or the values were the same as already stored.";
die();
}
// no need to send a 'HTTP/1.1 200 OK' header, because that's the
// default response header sent by PHP. We also don't need to die()
// here, because this should be the last line in this file and
// it will stop automatically.
echo "Changes saved successfully";