Torrie Posted July 23, 2015 Share Posted July 23, 2015 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!! Quote Link to comment Share on other sites More sharing options...
mac_gyver Posted July 23, 2015 Share Posted July 23, 2015 (edited) 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 July 23, 2015 by mac_gyver Quote Link to comment Share on other sites More sharing options...
Torrie Posted July 24, 2015 Author Share Posted July 24, 2015 (edited) 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 July 24, 2015 by Torrie Quote Link to comment Share on other sites More sharing options...
mac_gyver Posted July 24, 2015 Share Posted July 24, 2015 (edited) 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 July 24, 2015 by mac_gyver Quote Link to comment Share on other sites More sharing options...
Torrie Posted July 24, 2015 Author Share Posted July 24, 2015 ...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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.