I have a simple update query for when someone subscribes to my web app, updating the details of their license.
Recently I made some minor changes to this and it has stopped working (I presume these are linked, but haven't actually managed to prove this) - I've tried reversing whatever I did but seems to be to no avail.
For some reason, the update runs successfully and all fields update, except the expiry field.
I write my sql query into a log file and I've copied this into phpmyadmin command line and it works exactly as expected.
[Result is:
UPDATE License
SET type='Full'
, payer_id = 'XXXXXXX'
, gross = 'XXXX'
, payer_email = 'XXXXXXX'
, license_start = '2019-08-21 14:46:17'
, expiry = '2019-09-21'
, product = 'MON'
, stripe_id = 'XXXXXX'
WHERE user_id = XXX
which seems fine to me
I've adapted the format, apostrophes, I've even just put a date in like '2019-12-10' and it still won't update via the mysqli query. I've also tried expiry = $start, which requires truncation, but should work... still just doesn't update that field.
$expiry = date("Y-m-d", strtotime("+$couponmonths months", strtotime(date("Y-m-d H:i:s",$expiryts))));
$start = date ("Y-m-d H:i:s");
$sql = "UPDATE `$license_table` SET `type`='Full', `payer_id`='$subid', `gross`='$price', `payer_email`='$email', `license_start`='$start', `expiry` = '$expiry', `product`='$product_name', `stripe_id`='$stripeid' WHERE `user_id`=$userid";
}
...
if (mysqli_query($connection,$sql) === TRUE) {...}
Thanks those of you that tried to help. I've fixed this now by literally creating a new column called expiry_date instead of expiry, copying the data across to the new column, and updating all references.
Feel like I haven't solved what went wrong, but I have at least got it working again. It felt like the column had decided to to accept updates via PHP - not sure this is even possible???
I decided to try this course of action when I sent a query saying only to update this column and it still didn't work... madness!
Would love to hear an explanation if there is one, but just happy to have it working for now.
I think you should be setting $expiry, which presumably gets inserted into a datetime or timestamp type column in your DB, with the default SQL datetime format Y-m-d H:i:s as you did below.
Also, make sure that
strtotime("+$couponmonths months", strtotime(date("Y-m-d H:i:s", $expiryts)))
actually works the way you intend and returns the desired time.
Also, you should use {} to insert variables into strings.
Like so:
"UPDATE `{$license_table}` SET `type`='Full', `payer_id`='{$subid}', `gross`='{$price}', `payer_email`='{$email}', `license_start`='{$start}', `expiry` = '{$expiry}', [...]"
and so on.
This makes sure php is interpreting the variables correctly.
If all still fails, try to dump the query string and run it manually with the DB-manager or cli of your choice, for you to debug.
Related
I am providing 24 hours trial membership in my android application. I do not know more about PHP. I want check user registration time and want disable trial membership if 24 hours got passed. I have made little PHP file for that.
$sql = "SELECT id, email, registration_time FROM user WHERE trial = 1";
$result = $conn->query($sql);
if($result) {
while($row = $result->fetch_row()) {
$id = $row[0];
$email = $row[1];
$registrationTime = strtotime($row[2]);
$currentTime = strtotime("-1 day");
if($currentTime > $registrationTime) {
$update = "UPDATE user SET trial = 0 WHERE email = '$email'";
$conn->query($update);
$update = "UPDATE number_list SET disable = 1 WHERE user_id = $id";
$conn->query($update);
}
}
}
Its not providing any result even I have one user which time passed more than 48 hours.
How can I solve this issue?
try this and check
$currentTime=date('m-d-Y',strtotime($registrationTime . "-1 days"))
You should use a prepared statement to update the database for all the users with the same email (your first update query). Also see the documentation.
If someone registers with an e-mail address like test'; DROP ALL TABLES; --#gmail.com1 this code will dutifully remove your database. Never put user data into code directly like that.
Now let's look at the example code;
$sql = "SELECT id, email, registration_time FROM user WHERE trial = 1";
$result = $conn->query($sql);
if($result) {
while($row = $result->fetch_row()) {
You're saying there is no result at all. I assume that you've tested the output with a debug statement. E.g. putting echo 'users exist'; in between here. The first thing to do would be to check your user table if there are any rows. Does this SQL query produce results?
Assuming that it does, there doesn't appear to be anything wrong with the SQL statement. Assuming you have a table called user with four columns id, email, registration_time, and trial it should produce results.
Next, what you want to do is read the query function documentation. As you can see there, when a query fails, for whatever reason, it returns FALSE. Try writing an 'else' code block and logging the error that occurs. You can fetch it using the error function mysqli::error. Try appending this code;
} else {
echo "MySQL Error: " . $conn->error;
}
Where you can replace the echo with your error handling of choice.
It's probably a good idea to write a wrapper for mysqli if you're going to execute more than a few queries in your application. That way, you can write error handlers in your wrapper class for what your application should do if a query or database connection fails.
What could also be the case is that, while your initial query succeeds and fetches some rows, the time check fails. You may want to do some stricter date/time parsing than using strtotime and hoping for the best. Assuming you're using a TIMESTAMP column to store the data, you can use this:
function readDatabaseTimestampValue($value) {
$dateTime = date_create_from_format("Y-m-d H:i:s", $value);
$timestamp = $dateTime->getTimestamp();
return $timestamp;
}
Check the exact time data returned from your database. Dates and times are complicated, and if things are reinterpreted, say the day number in SQL may become the year in the PHP app, which can cause strange bugs. E.g. you can do this by doing say:
echo "24 hours ago: " . strtotime("-1 day") . ", user data: " . $row[2];
Next, you probably have some bugs in the logic. '24 hours ago' is better done by doing this, as using '-1 day' will cause weird issues when people mess with the calendar:
$timestamp = time() - 86400;
There's 86,400 seconds in a day (well, excluding DST and leap seconds, but you want 24 hours of subscription time, not 23 hours around the 21st of March).
Finally, there's problems if the same E-mail address is present more than once in the table. You will set 'trial' to 0 for one user, but may set the 'disable' flag for another if two users register within the same 24-hour period with the same e-mail. If the latter is guaranteed to be unique then this is no issue. Otherwise, you may want to update by id in both tables.
Next, we can look at some optimization. Right now, you fetch everything from the database. But you can do much better/faster by having an index on registrationTime, and using the database's sorting features. E.g. let's say we know the exact date/time of 24 hours ago as $yesterday in PHP we can write a query like:
SELECT id, email, registration_time FROM user WHERE trial = 1 AND registration_time > ?
Bind the $yesterday variable to the parameter. Now you no longer need the if() statement; the database does it for you. Also, as your database grows, you're not checking the old records one-by-one every time the code runs.
1Note, that may not be a legal e-mail address, but there's probably ways to do evil things even with a legal mail address.
I have a input field which takes input in the time format 'H:i A' and should store in the mysql database of time type data.
I have converted the input by the dateTime function which looks like-
$sat_opened = DateTime::createFromFormat( 'H:i A',$_POST['sat_opened']);
$sat_opened_new = $sat_opened->format('H:i:s');
And query used to insert is -
mysqli_query($connect, "INSERT INTO biz_hours VALUES(DEFAULT, '$bid', 'Sat', '$sat_status', '$sat_opened_new', '$sat_closed','')")
Others Data are being inserted but for opened column it always inserts 12:00:00 . If i print the converted time (echo $sat_opened_new) then it prints time fine that should be in the MySQL time format like - 08:50:00 or 17:30:00
What problem actually is there? Please help me to find out. Thanks
It appears that you're successfully able to insert a date directly through phpMyAdmin: INSERT INTO biz_hours (opened) VALUES ('12:34:56') . So you need to work back through your PHP query and debug it. Start with the minimal working mysqli_query and begin adding back other fields (biz_id, day, status, etc.) until you encounter the problem again. Perhaps one of your variables is not properly set.
Trying to make a little Search feature for a user, so he can type in a date on a webpage made with HTML/PHP, and see which people in the db have registered as member on or after (a date). My user inputs the date in format 2015-10-01. This gets sent to a PHP page with a jqxGrid on it, populated with member details of members conforming to my query on the MySQL database (using PDO).
The query uses the operator >= on a string passed as (for example) "2015-10-01" in the WHERE clause, so I am using STR_TO_DATE to make the comparison work:
WHERE `lastUpdated` >= STR_TO_DATE( ? , '%Y-%m-%d');
With PDO, the ? later gets bound to the date (which was passed in as a string).
The db column for registration date is in DATETIME format, and in the db values look like: "2015-10-12 17:12:52".
My query returns an empty array every time, - and this after many hours of trying every conceivable permutation of date format, both in the MySQL statement and on the page that prepares the data for populating the grid.
Can someone show me what's wrong here?
Thanks!!
SP
Make it
WHERE `lastUpdated` > ?
and check your data and stuff.
Basically, you should never touch PDO until you get raw SQL to work.
okay, so here is the PDO version that works - passing in ? instead of the date:
function getJSONAllMembersByDate($PDOdbObject, $regDate)
{
try
{
$membersByDateSQL = "SELECT `id`, `name_first`, `name_last`, `organization`,`email`, `phone`,`source`,`comments`,`language_id`, `lastUpdated` FROM `member` WHERE lastUpdated>=?";//'$regDate'
$get=$PDOdbObject->prepare($membersByDateSQL);
$get->execute(array($regDate));
$rows = $get->fetchAll(PDO::FETCH_ASSOC);
$json=json_encode($rows);
return $json;
}
The fact that it works proves there were other errors in the file containing the jqxwidget (the version before I posted here). I certainly tried about a million different things to get this working.
I don't know if this counts as an answer, but at least it WORKS! There are so many variables in this problem - json, jqxgrid, pdo ... not forgetting that there are several ways to use PDO. I probably had several errors in different places.
(#apokryfos, the STR_TO_DATE was indeed unnecessary.)
In the end, this is what works:
In the PHP page containing the jqxGrid, the url sent to the server is:
url: 'my-json-responses.php?fct=getJSONAllMembersByDate®Date=<?php echo $fromDate ?>'
This $fromDate comes from the $_POST when the user typed in a date (in the format 2015-10-01) on the input page. When the PHP page containing the jqxGrid loads, it does
$fromDate = $_POST['regDate'];
The url "transits" through the file my-json-reponses.php, which contains many functions. It finds the right one:
if ($_GET['fct'] == 'getJSONAllMembersByDate')
{
$result = getJSONAllMembersByDate($connectionObject, $_GET['regDate']);
echo $result;
}
The $result is called on the file that contains all my PDO database requests, including:
function getJSONAllMembersByDate($PDOdbObject, $regDate) { try
{
$membersByDateSQL = "SELECT `id`, `name_first`, `name_last`, `organization`,`email`, `phone`,`source`,`comments`,`language_id`, `lastUpdated` FROM `member` WHERE lastUpdated>='$regDate'";
$get=$PDOdbObject->query($membersByDateSQL);
$rows = $get->fetchAll(PDO::FETCH_ASSOC);
$json=json_encode($rows);
return $json;
}
catch (PDOException $e)
{
echo "There was a problem getting all members with this search query.";
echo $e->getMessage();
}}
Note that I couldn't make the version using "?" in the query work at all, hence passing in the variable $regDate directly, with single quotes around the variable just to make life interesting.
This returns a nice list of all my users as of 2015-10-01 - but is presumably still open to MySQL injection attacks ...
But after this marathon of debugging I am happy enough for now. (All improvements welcomed, naturally!)
SP
I have a very simple query which updates a 'status', a 'has_note', (both are tinyints in the database) and a time. The time updates correctly every time this is run, however, the other two are not affected and never changed.
Here is the code:
$status_sql = "
UPDATE voe_employment
SET status = 5, email_date = NOW()
WHERE emp_id = " . $_POST['emp_id'] . "
LIMIT 1";
$status_result = mysql_query($status_sql);
I have copied and pasted the resulting $status_sql into pmadmin, and everything updates correctly.
Also, $status_result = 1 after executing this code, which signifies success.
This block of code is wrapped around a "try, catch" statement, and the catch is never run/activated. And I have tried wrapping the table name in ``, wrapping the 5 in '', etc.
Check to make sure no other code is doing another UPDATE right after. We have found this in the past. Another unexpected update was running that we didn't know was that overwrote the data.
I'm calling strtotime() on a formatted datetime string and for some reason it always returns NOW()...
If my formatted datetime string (stored in the last_seen attribute) is: 2013-06-13 07:13:04
and I write the following code:
echo $user->last_seen;
echo date('F j, Y', strtotime($user->last_seen));
The output I get is:
NOW() January 1, 1970
What on earth is going wrong here??? This is definitely not the expected result. The string is stored in a MySQL database, if that makes any difference.
Edit: by request, the code used to create the attribute in the database is:
$user->last_seen = date('Y-m-d H:i:s');
$user->save;
Edit 2: by request, the code used to pull the users table, with the user we want, is:
$user = User::find($user_id);
(not very helpful, lol).
Edit 3: if I var_dump($user->last_seen) the result is:
object(Laravel\Database\Expression)#40 (1) { ["value":protected]=> string(5) "NOW()" }
Edit 4: If I echo var_dump(strtotime($user->last_seen)) the result is:
bool(false)
Edit 5: this problem was a result of me being an idiot, but some fine debugging was done by everyone who posted. Read the answers if you are interested.
First of all You check the return value of strtotime($user->last_seen)
If strtotime($user->last_seen) returns false then $user->last_seen may be empty or not a valid Date and Time Formats
var_dump(strtotime($user->last_seen))
Your problem is most likely not in the select clause, but lays there where you store your data.
When you are inserting the time in the database, you are probably doing
insert into myTable (fieldname) values ('now()');
instead of
insert into myTable (fieldname) values (now());
So you need to lose the quotes there...
You are NOT storing the time in the database, but the string now() ...
The best thing you could actually do is change the database column type from varchar to DateTime, so even the database knows it's a DateTime. Then you avoid having to cast it back to DateTime in PHP.
Oh dear god.... I'm going to kick myself for this one. I did a project wide Ctrl+F for last_seen and I discovered that in my routing scheme I had this:
Route::filter('before', function() {
if (Auth::check()) {
$user = Auth::user();
$user->last_seen = DB::raw('NOW()');
$user->save();
}
});
Walks away with tail between legs...