Jump to content

date() not reliable?


Torrie

Recommended Posts

10-year intermittent problem:

Invoices displayed on my website are assigned a unique 7-digit order number generated by PHP's date function

 

$invoice_number = date("njis"); // creates, for example, invoice number "7223060"

 

Roughly 10% of the time, no order number is displayed!

 

That means, for whatever reason, from time to time, php's date function decides NOT to create a date.

 

Over the past 10 years, I have been on different servers, at different hosts, with, obviously, different PHP versions.

 

Is this one of those things, like, a "well-known-issue" about PHP's date function? Or what?

 

I have even had to code built-in "backup-plan fail-safes" like:
$invoice_number = date("njis");

if (strlen($invoice_number) < 4) {

$invoice_number = date("njis").rand(11111,99999);

// mail(webmaster notice);

}

 

What are your thoughts?

 

Thank you!!

Link to comment
Share on other sites

your's is the first post i have ever seen that has indicated a problem with not getting a data() and given you have had this on different servers and php versions and that most problems are due to code and not underlying bugs, it's more likely that the problem is something like register_globals (in php versions where it exists) overwriting the $invoice_number variable or some handling of the value (in code or the database) is truncating it/clearing it.

 

the 'njis' format string will generate a 6, 7, or 8 character string. perhaps you have some code or data storage that when it is either 6 or 8 characters, that the value is getting cleared?

 

in those cases where you don't get a value, what does your date("njis").rand(11111,99999) value end up being?

 

assuming you are storing these values in a database column, do you have a unique key/index set up on the column, because multiple invoices could be generated during the same second, resulting in duplicate values that could end up resulting in data not being inserted into the database table. also, what is the data type of the column (you could be generating values that are out of range or invalid for the type, resulting in a zero or an empty string being inserted instead.)

 

it's also possible that your code is being requested twice on occasion, once with and once without expected external data and the execution path the code takes results in a value being generated and inserted into your database that's not what you expect.

 

another common occurrence for unexplained operation of code that are redirects that don't have exit; statements after them and the code that continues to run after the redirect does unexpected things to data, since that code isn't receiving the inputs that it expects.

 

you could also have code that is updating a properly stored value to an empty value, either due to pages being requested twice/redirects without exit; statements...

 

short-answer: in about 99.7% of all cases of common things php code is used for, incorrect operation of code/data is due to something the code/data is or is not doing, not due to underlying bugs in the language.

Edited by mac_gyver
Link to comment
Share on other sites

Thank you, your answer gives me a lot to think about. In answer to the rand() question, $invoice_number.rand(1111,9999) just gives me the random number.

 

Like you said, date("njis") gives a 6 - 8 character number, and the errors are easy to spot in my mySQL column:

7223564

7223669

7234452

11121

7234498

7238566

 

Here's my exact code:

 

if (strlen($invoice_number) < 4) {
$invoice_number = date("njis");
}
 
### INCREMENT invoice_number BY "1" IF the invoice_number ALREADY has been used before.
 
$p1 = "select exists(select invoice_number from sales_orders where invoice_number regexp '".$invoice_number."' and name is NOT NULL  and name NOT regexp '".$name."' )";
 
if (@mysql_result(@mysql_query($p1),0,0) == 1) {
$orderarray = array();
$savedSQL = 'select invoice_number from sales_orders';
$savedQuery = mysql_query($savedSQL);
while($savedResult=mysql_fetch_array($savedQuery)) {
if(preg_match("/\d{4}/",$savedResult[0])) {
$orderarray[] = preg_replace('/\D/','',$savedResult[0]);
}
}
$invoice_number = (max($orderarray) + 1);
}

 

 

I cannot for the life of me think of what I can do to improve this code. Yes, it's newbie-stupid, and still uses deprecated mySQL, but I can't think of what else to do.

 

The code (above) is in red, because my face is red/embarassed for the dumb question :-)

Edited by Torrie
Link to comment
Share on other sites

the code you posted above is a race-condition waiting to happen. unless you lock the table, you CANNOT select data and increment the highest value and be sure that you don't have concurrent visitors doing the same thing at the same time, producing the same end value. in fact, since it's going to take a relatively long time (in terms of computing) to retrieve all the rows, there's an even bigger window of time where multiple visitors can be trying to run that same code.

 

why aren't you using an auto-increment column as the invoice number?

Edited by mac_gyver
Link to comment
Share on other sites

...Sigh...

MacGyver, I wish I was smart enough to read your post and go "Oh I wish I thought of that," and then open up my code and type in a few lines and do what you just suggested.

 

Unfortunately, I look at what you just said, and I'm thinking that is an Excellent idea.... but I don't know how to do what you just said.

 

Would you be so kind as to post a couple lines of code?

 

I know that I want my sales Invoice Number to start with the month and the date (e.g. I know that an Invoice Number that looks like "7108473" would go to an order created on July 10th, etc.).

 

And my table is already autoincremented. Since I built the current code, I have 34 sales, so a "select max(id) as id from sales_orders" would give me "34" and not a number like "710****."

 

If you could bang out 2 or 3 lines of code to push me in the right direction, I will absolutely PROMISE to hold a door open for an elderly lady this coming weekend.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.