This follows on from a previous question (html/php/sql form with insert/update) so use that for reference on the HTML form. When a client moves in, their client's active is changed to 1, the room's room_vacant is changed to 0, and an occupancy record is made.
As well as this, the first rental payment needs to be generated using all this information. The rent_occupancy_id is worked out through the user of lastInsertId(), as the last inserted id would've been the occupancy ID.
The rent_cost is generated whether the client moving in is on benefits on not. If a client is not on benefits, then the rent_cost = £126.57 but if they are then rent_cost = £20.03. The date_lastpaid is the same as the start_date of the client's occupancy record and the date_due is equal to a week ahead of the date_lastpaid.
The problem is that a rent record is not being created yet all the other changes for the other records etc. are being made. Any help would be much appreciated.
<?php
require("dbconnect.php");
//CLIENT
$id = $_POST['id'];
//UPDATES client's to 1/Yes to say that they're now an active client in JRH,
//where the selected client's ID is equal to :id
$stmt = $dbh->prepare("UPDATE client SET active = 1 WHERE client_id=:id");
$stmt->bindParam(':id', $id);
$stmt->execute();
//ROOM
$room_id = $_POST['room_id'];
$stmt = $dbh->prepare("UPDATE room SET room_vacant = 0 WHERE room_id = :room_id");
$stmt->bindParam(':room_id', $room_id);
$stmt->execute();
//OCCUPANCY
$id = $_POST['id'];
$room_id = $_POST['room_id'];
$start_date = $_POST['start_date'];
$stmt = $dbh->prepare("INSERT INTO occupancy (occupancy_client_id, occupancy_room_id, start_date) VALUES(:id, :room_id, :start_date)");
$stmt->bindParam(':id', $id);
$stmt->bindParam(':room_id', $room_id);
$stmt->bindParam(':start_date', $start_date);
$stmt->execute();
//Working out Rent Cost
$id = $_POST['id'];
$stmt=$dbh->prepare("SELECT * FROM client WHERE client_id=:id");
$stmt->bindParam(':id', $id);
$stmt->execute();
$row = $stmt->fetch();
//Works out whether a client has benefits or not,
//and then uses this information to generate a cost of the rent
if ($row['benefits'] == '0') {
$rent_cost = "126.57";
} else{
$rent_cost = "20.03";
}
//RENT INSERT
//
//As the occupancy record is being created above
//and the rent table needs a rent_occupancy_id to join,
//then we use lastInsertId() in order to get that occupancy id
$rent_occupancy_id = $dbh->lastInsertId();
$date_lastpaid = $_POST['start_date']; //As the client hasn't made a payment yet,
//we say that their last payment was the date they joined
$date_due = strtotime($date_lastpaid);
$date_due = strtotime('+1 week', $date_due);
$date_due = date('Y/m/d', $date_due);
$stmt = $dbh->prepare("INSERT INTO rent (rent_occupancy_id, rent_cost, date_lastpaid, date_due) VALUES (:rent_occupancy_id, :rent_cost, :date_lastpaid, :date_due)");
$stmt->BindParam(':rent_occupancy_id', $rent_occupancy_id);
$stmt->BindParam(':rent_cost', $rent_cost);
$stmt->BindParam(':date_lastpaid', $date_lastpaid);
$stmt->BindParam(':date_due', $date_due);
$stmt->execute();
?>
just change to lowercase first letter in bindParam();
$stmt->bindParam(':rent_occupancy_id', $rent_occupancy_id);
$stmt->bindParam(':rent_cost', $rent_cost);
$stmt->bindParam(':date_lastpaid', $date_lastpaid);
$stmt->bindParam(':date_due', $date_due);
$stmt->execute();
Related
I need to generate a code which consists of some arbitrary prefix, a year, and an incrementing number. The incrementing number must start at 1 at the first time when the number is generated that year.
This code needs to be added to the sqlite database and be available elsewhere in the PHP script.
What i have done now uses 4 accesses to the database:
$codePrefix = 'TEST';
$stmt = $db->prepare(
'INSERT INTO test (year)
VALUES(strftime("%Y", "now"))'
);
$stmt->execute();
$id = $db->lastInsertId();
$stmt = $db->prepare('SELECT `year` FROM `test` WHERE `id`=:id');
$stmt->bindValue(':id', $id);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$year = $result['year'];
$stmt = $db->prepare('SELECT Ifnull(Max(id), 0) `max_id` FROM `test`
WHERE `year`<:year');
$stmt->bindValue(':year', $year);
$result = $stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$previousMax = $result['max_id'];
$codeSuffix = $id-$previousMax;
$code = "{$codePrefix}-{$year}-{$codeSuffix}";
$stmt = $db->prepare('UPDATE `test` SET `code`=:code WHERE `id`=:id');
$stmt->bindParam(':code', $code);
$stmt->bindParam(':id', $id);
$stmt->execute();
Here i am abusing the fact that the id is an integer primary key, and autoincrements.
This works. But i feel that it is doing something very easy in a very complicated manner.
Is there a better solution? I need to assume that the midnight of the first of January can happen at any moment of the code, so i cannot do things like get the year information from PHP without hitting the database.
Before somebody asks, the reason i am using prepared statements even when no values are bound is because late on obviously more data will be inserted into the table.
Consider a pure SQL solution using the ROW_NUMBER window function. Below assigns to new field, new_id:
UPDATE test
SET new_id = 'TEST_' || test.[Year] || '_' || sub.rn
FROM (
SELECT id,
[Year],
ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY id) AS rn
FROM test
) AS sub
WHERE test.id = sub.id;
I have a like button, which allows users to like posts on my site. If the user likes a post they have not liked before it will +1, if they press the same like button again it will -1. This is working on my virtual server on my laptop. However, the same code is not working on my live site. On my live site the user is able to like the same post multiple times, which is not what I want. I'm using a JQuery Ajax call to a PHP file that fires a some MySQL code.
Can anyone see anything obviously wrong with the PHP below?
include ("../con/config.php");
$postid = $_POST['postid'];
$userid = $_POST['userid'];
$query = $con->prepare("SELECT COUNT(*) AS CntPost FROM Likes WHERE UserID = ? AND PostID = ?");
$query->bind_param('ss',$userid,$postid);
$query->execute();
$result = $query->get_result();
$fetchdata = $result->fetch_assoc();
$count = $fetchdata['CntPost'];
if($count == 0){
$stmt = $con->prepare("INSERT INTO Likes(UserID,PostID) VALUES(?,?)");
$stmt->bind_param("ss", $userid, $postid);
$stmt->execute();
} else {
$stmt = $con->prepare("DELETE FROM Likes WHERE UserID = ? AND PostID = ?");
$stmt->bind_param("ss", $userid, $postid);
$stmt->execute();
}
// count numbers of likes in post
$query = $con->prepare("SELECT COUNT(*) AS CntLike FROM Likes WHERE PostID = ?");
$query->bind_param('s', $postid);
$query->execute();
$result = $query->get_result();
$fetchlikes = $result->fetch_assoc();
$totalLikes = $fetchlikes['CntLike'];
$return_arr = array("likes"=>$totalLikes,"type"=>$count);
echo json_encode($return_arr);
Managed to solve it. The issue was in the MySQL database column itself for the UserID. The number of chars for the column was not long enough and was truncating the UserID, which I populate using the sessionID. I amended this field in the database to allow for the length of a sessionID.
perhaps this statement
"SELECT COUNT(*) AS CntLike FROM Likes WHERE PostID = ?" need UserID in WHERE statement so you would know that specific UserID in that specific PostID
I'm sorry if this has been asked before or if I'm not able to explain in a great way. I've spent hours trying to wrap my head around the issue and I just can't seem to fix this issue. The code is working fine locally, but when I upload it to my server there seems to be some sort of issue with how the server handles/checks differences in time between server and client. Not sure exactly how or what to think. I'm also aware that I'm inserting data into pdo statements incorrectly, I don't care about that at the moment. I will tidy all this up at a later point.
The part of the application that I'm experiencing issues with is when it checks an active shipment (it's a sort of game). I want to compare the timestamp from the database with the current time to see if the time has passed. In the case that the arrival time is past, then I want to set the status of the shipment to 'delivered' as well as add the data to another table called 'storage'.
function check_active_shipment(){
$pdo = pdo();
$username = $_SESSION['username'];
$statement = $pdo->prepare("SELECT * FROM shipments WHERE username LIKE '$username' AND status LIKE 'active' LIMIT 1");
$statement->execute();
$rows = $statement->fetch();
$id = $rows['id'];
if($rows['type'] == "purchase"){
if(time() >= strtotime($rows['arrival'])){
$statement = $pdo->prepare("UPDATE shipments SET status='delivered' WHERE id LIKE '$id'");
$statement->execute();
$statement = $pdo->prepare("INSERT INTO storage (username, crate_type_id, quantity) VALUES (?, ?, ?)");
$statement->bindParam(1, $username);
$statement->bindParam(2, $rows['crate_type_id']);
$statement->bindParam(3, $rows['quantity']);
$statement->execute();
//header("location:index.php");
}
}
else if($rows['type'] == "sale"){
if(time() >= strtotime($rows['arrival'])){
$statement = $pdo->prepare("UPDATE shipments SET status='delivered' WHERE id LIKE ?");
$statement->bindParam(1, $id);
$statement->execute();
$statement = $pdo->prepare("SELECT cash FROM users WHERE username LIKE ?");
$statement->bindParam(1, $username);
$statement->execute();
$user = $statement->fetch();
$cash = $user['cash'] + $rows['value'];
$statement = $pdo->prepare("UPDATE users SET cash=?");
$statement->bindParam(1, $cash);
$statement->execute();
//header("location:index.php");
}
}
}
Let me know if there is any information I'm missing to share.
Would getting the time from the server, rather than using the time() function solve you problem.
Either do a separate query
SELECT NOW()
or add it to your existing query
SELECT *, NOW() as curtime FROM shipments WHERE .....
Have you tried using the DateTime Class? Perhaps it behaves much like you had expected... Here's a snippet on how to use it in your case:
<?php
// ...SOME CODE...
if($rows['type'] == "purchase"){
// TRY USING DateTime CLASS
$arrival = new DateTime($rows['arrival']);
$arrivalTS = $arrival->getTimestamp();
if(time() >= $arrivalTS){
// REST OF THE CODE...
}
}else if($rows['type'] == "sale") {
// TRY USING DateTime CLASS AGAIN
$arrival = new DateTime($rows['arrival']);
$arrivalTS = $arrival->getTimestamp();
if (time() >= $arrivalTS) {
// REST OF THE CODE...
}
}
So i think i'm close to figuring this out but my query won't add the item from the "pending" table to the "items" table. can you guys help me out with this please. Also if i want it to delete after it gets added should i add the code below the INSERT INTO SELECT query? thanks
action.php:
$sql = "INSERT INTO items (photo,title,description, name) SELECT (photo,title,description, name) FROM pending";
$stmt = $conn->prepare($sql);
$stmt->execute();
Example for delete query after it takes the item from the "pending" into items:
$idToDelete = filter_var($_POST["recordToDelete"],FILTER_SANITIZE_NUMBER_INT);
//try deleting record using the record ID we received from POST
$sql = "DELETE FROM pending WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $idToDelete, PDO::PARAM_INT);
$stmt->execute();
I think you are leaving yourself open to mistakes doing it this way.
Consider what would happen if a new row is added to the pending queue after you have issued the INSERT SELECT but before you have started your delete.
I think you need to do this in a more controlled way inside a single loop to make sure you are only deleting what you have copied from pending into items.
$sql = "SELECT photo,title,description, name FROM pending";
$select_pending = $conn->prepare($sql);
$select_pending->execute();
$sql = "INSERT INTO items (photo,title,description, name)
VALUES (:photo,:title,:description, :name)";
$insert_items = $conn->prepare($sql);
$sql = "DELETE FROM pending WHERE id = :id";
$delete_pending = $conn->prepare($sql);
// only if you are using INNODB databases.
//$conn->beginTransaction();
while( $row = $select_pending->fetch_object() ) {
$insert_items->bindParam(':photo', $row->photo, PDO::PARAM_STR);
$insert_items->bindParam(':title', $row->title, PDO::PARAM_STR);
$insert_items->bindParam(':description', $row->description, PDO::PARAM_STR);
$insert_items->bindParam(':name', $row->name, PDO::PARAM_STR);
$insert_items->execute();
$delete_pending->bind_param(':id', $row->id, PDO::PARAM_INT);
$delete_pending->execute();
}
// only if you are using INNODB databases.
//$conn->commit();
$sql = "INSERT INTO items (photo,title,description, name)
SELECT photo,title,description, name FROM pending";
remove the () in the SELECT statement.
I am working on code that updates points for someone when they contribute content. I have a table "points" and a column "contributions." When I create a variable called contributions and assign it a value of 3 and then do SET contributions = $contributions such as this below code it WORKS:
$contributions = 3
$yesupdate = "UPDATE points SET contributions = $contributions WHERE ID =
$user_ID";
$stmt2 = $dbh->prepare($yesupdate);
$stmt2->bindParam(':WID', $yes_WID, PDO::PARAM_INT);
$stmt2->bindParam(':approved', $e = Y, PDO::PARAM_STR);
$stmt2->bindParam(':position', $row2[0]['position'], PDO::PARAM_INT);
$stmt2->execute();
HOWEVER, I do not want the points to be set to 3. I want it to add 3 each time. So I tried the below approach, but nothing happens:
$yesupdate = "UPDATE points SET contributions = $contributions + 3 WHERE ID
= $user_ID";
$stmt2 = $dbh->prepare($yesupdate);
$stmt2->bindParam(':WID', $yes_WID, PDO::PARAM_INT);
$stmt2->bindParam(':approved', $e = Y, PDO::PARAM_STR);
$stmt2->bindParam(':position', $row2[0]['position'], PDO::PARAM_INT);
$stmt2->execute();
Can anyone see what I am missing? Do I need to set the $contributions variable in example 2 like I did in example 1? If so, what would I assign to that variable when I just want the code to update the existing value of "contributions" in the database by 3?
You want your query to reference the current value in the column (not the variable) and add three:
UPDATE points SET contributions = contributions + 3 WHERE ID = $user_ID
You should use the prepare properly though too, have a look at: PHP Manual: PDO::prepare
$yesupdate = "UPDATE points SET contributions = contributions + 3 WHERE ID = $user_ID";
$stmt2 = $dbh->prepare($yesupdate);
$stmt2->bindParam(':WID', $yes_WID, PDO::PARAM_INT);
$stmt2->bindParam(':approved', $e = Y, PDO::PARAM_STR);
$stmt2->bindParam(':position', $row2[0]['position'], PDO::PARAM_INT);
$stmt2->execute();