5kyy8lu3 Posted January 21, 2009 Share Posted January 21, 2009 Hi. I'm writing some form validation stuff and I need to verify that a variable has only numbers in it. It can be 0 through 999. No spaces, no letters, no symbols. Here's my code: if (ereg('[^0-9]', $cadence)) { //yay it matches } else { $_SESSION['error_count']++; $_SESSION['cadence_err'] = 'Error: Cadence must be a numeral.'; } I've searched all over and tried lots of variations of the pattern but I can't seem to get this to do anything but NOT match even when I manually set the variable to a number like '123'. Any ideas? . Quote Link to comment Share on other sites More sharing options...
MadTechie Posted January 21, 2009 Share Posted January 21, 2009 try this if (preg_match('/^\d{1,3}$/', $cadence)) { //yay it matches } else { $_SESSION['error_count']++; $_SESSION['cadence_err'] = 'Error: Cadence must be a numeral.'; } EDIT: oh for EREG it would be if (ereg('^[[:digit:]]{1,3}$', $cadence)) { Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted January 21, 2009 Share Posted January 21, 2009 I would probably make use of ctype_digit() in conjunction with strlen() On a side note, it is best to use preg instead of erge, as POSIX (which ereg is part of) will no longer be inlcuded with the core of PHP as of 6 (it will be available as an extension, which may [or may not] be used by your hosting provider). Future proof your code now so that you will not run the risk of having it break on you later on when PHP 6 comes out. Quote Link to comment Share on other sites More sharing options...
.josh Posted January 21, 2009 Share Posted January 21, 2009 @MadTechie: \d allows for exponents. Better to use [0-9]{1,3} if you strictly want a 3 digit number. @nrg_alpha: Since you have to cast the subject as a string to make sure that ctype_digit works, and since you have to make conditions based on two diff functions (ctype_digit and strlen), I automatically assumed the regex would be way faster. But for shits and grins I decided to benchmark it anyways, and was surprised to see that the ctype/strlen method was actually faster... Here is my benchmark script and sample of results: <?php function pregMethod ($subject) { if (preg_match('~^[0-9]{1,3}$~', $subject)) return true; else return false; } // end pregMethod function ctypeMethod ($subject) { $subject = (string) $subject; if ((strlen($subject) > 0) && (strlen($subject) < 4)) { if (ctype_digit($subject)) return true; } else { return false; } // end strlen range } // end ctypeMethod $subject = 123; /*** test regex method ***/ for ($x = 1; $x < 11; $x++) { $time_start = microtime(true)*1000; pregMethod($subject); $time_end = microtime(true)*1000; $pregTime[$x] = $time_end - $time_start; } // end test regex method /*** test ctype method ***/ for ($x = 1; $x < 11; $x++) { $time_start = microtime(true)*1000; ctypeMethod($subject); $time_end = microtime(true)*1000; $ctypeTime[$x] = $time_end - $time_start; } // end test regex method /*** generate some stats ***/ $pregSum = array_sum($pregTime); $ctypeSum = array_sum($ctypeTime); $higher = max($pregSum, $ctypeSum); $lower = min($pregSum, $ctypeSum); $diff = $higher - $lower; $ratio = round($higher / $lower,1); /*** end generate stats ***/ /*** echo out stats ***/ echo "Benchmark test<br/>"; echo "regex vs. ctype/strlen methods<br/>"; echo "time measured in microtime*1000<br/>"; echo "<br/>"; echo "regex method: $pregSum total<br/>"; echo "ctype method: $ctypeSum total<br/>"; echo "difference of: $diff or $ratio times faster"; echo "<pre>"; print_r($pregTime); echo "</pre>"; echo "<pre>"; print_r($ctypeTime); echo "</pre>"; /*** end echo out stats ***/ ?> Benchmark test regex vs. ctype/strlen methods time measured in microtime*1000 regex method: 0.152 total ctype method: 0.0630000000001 total difference of: 0.0889999999998 or 2.4 times faster Array ( [1] => 0.087 [2] => 0.0179999999999 [3] => 0.00599999999997 [4] => 0.00600000000009 [5] => 0.00599999999997 [6] => 0.00599999999997 [7] => 0.00600000000009 [8] => 0.00499999999988 [9] => 0.00600000000009 [10] => 0.00599999999997 ) Array ( [1] => 0.013 [2] => 0.00599999999986 [3] => 0.00600000000009 [4] => 0.00599999999997 [5] => 0.00600000000009 [6] => 0.00500000000011 [7] => 0.005 [8] => 0.005 [9] => 0.005 [10] => 0.00599999999997 ) Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted January 21, 2009 Share Posted January 21, 2009 @nrg_alpha: Since you have to cast the subject as a string to make sure that ctype_digit works, and since you have to make conditions based on two diff functions (ctype_digit and strlen), I automatically assumed the regex would be way faster. But for shits and grins I decided to benchmark it anyways, and was surprised to see that the ctype/strlen method was actually faster... CV, while preg is fast, functions like str_replace, cytpe_[whatever], strlen, strpos, and the like is typcially faster then preg..(you don't have as much internal overhead that preg carries) You do get additional robustness out of preg granted (and that is the trade off.. speed for flexibility). Sometimes, while I love preg (my sig says it all), if simple tasks can be achieved outside preg (or perhaps using minimal preg in conjunction with php built-in non-regex functionality, the results usually are faster, so I'm not surprised. Quote Link to comment Share on other sites More sharing options...
MadTechie Posted January 21, 2009 Share Posted January 21, 2009 Kinda weird, mine is the other way around Benchmark test regex vs. ctype/strlen methods time measured in microtime*1000 regex method: 0.0986328125 total ctype method: 0.1025390625 total difference of: 0.00390625 or 1 times faster Array ( [1] => 0.02099609375 [2] => 0.009033203125 [3] => 0.0087890625 [4] => 0.0078125 [5] => 0.008056640625 [6] => 0.009033203125 [7] => 0.00830078125 [8] => 0.0087890625 [9] => 0.009033203125 [10] => 0.0087890625 ) Array ( [1] => 0.029052734375 [2] => 0.0087890625 [3] => 0.0087890625 [4] => 0.008056640625 [5] => 0.008056640625 [6] => 0.0078125 [7] => 0.008056640625 [8] => 0.00830078125 [9] => 0.0078125 [10] => 0.0078125 ) Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted January 21, 2009 Share Posted January 21, 2009 Kinda weird, mine is the other way around There is always a margin of calculating error... typcially, constanly reshfreshing and making note of each results will bring more more less the faster method's results ahead.. but some cycles may give slightly different results.. Quote Link to comment Share on other sites More sharing options...
MadTechie Posted January 21, 2009 Share Posted January 21, 2009 Yeah i know, but all results were 1 to 1.1, but on each test preg was slightly faster Quote Link to comment Share on other sites More sharing options...
.josh Posted January 21, 2009 Share Posted January 21, 2009 CV, while preg is fast, functions like str_replace, cytpe_[whatever], strlen, strpos, and the like is typcially faster then preg..(you don't have as much internal overhead that preg carries) You do get additional robustness out of preg granted (and that is the trade off.. speed for flexibility). Sometimes, while I love preg (my sig says it all), if simple tasks can be achieved outside preg (or perhaps using minimal preg in conjunction with php built-in non-regex functionality, the results usually are faster, so I'm not surprised. Yeah I know that if you're wanting to for instance to just check if a string is inside another string, to use the built-in functions instead; I figured ctype_digit and strlen by itself would be faster, but I just figured that since you were having to do multiple things: type casting, both function calls, more complex conditions, etc.. that it would all add up. Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted January 21, 2009 Share Posted January 21, 2009 Yeah i know, but all results were 1 to 1.1, but on each test preg was slightly faster Here's what I came up with for a simple one string test.. $str = '123'; $loop = 1000; $time_start = microtime(true); for($i = 0; $i < $loop; $i++){ $total = strlen($str); // use strlen only once.. if($total > 0 && $total < 4){ $status = (ctype_digit($str))? 'true': 'false'; } else { $status = 'false'; } } $time_end = microtime(true); $elapsed_time = round($time_end-$time_start, 4); echo '<pre>'.print_r($str, true). " = $status (cytpe)"; echo '<br />Time: ' . $elapsed_time . '<br />'; $time_start = microtime(true); for($i = 0; $i < $loop; $i++){ $status = (preg_match('#^[0-9]{1,3}$#', $str))? 'true': 'false'; } $time_end = microtime(true); $elapsed_time = round($time_end-$time_start, 4); echo '<pre>'.print_r($str, true). " = $status (preg)"; echo '<br />Time: ' . $elapsed_time . '<br />'; Output: 123 = true (cytpe) Time: 0.0024 123 = true (preg) Time: 0.0054 Quote Link to comment Share on other sites More sharing options...
.josh Posted January 21, 2009 Share Posted January 21, 2009 oh and in case people didn't catch it..., my benchmark was multiplying microtime by 1000, so the difference is beyond negligible. Even looking at nrg_alpha's benchmark results, we're talking about .003s diff from doing 1000 calculations. Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted January 21, 2009 Share Posted January 21, 2009 Yeah I know that if you're wanting to for instance to just check if a string is inside another string, to use the built-in functions instead; I figured ctype_digit and strlen by itself would be faster, but I just figured that since you were having to do multiple things: type casting, both function calls, more complex conditions, etc.. that it would all add up. Yeah, I hear that.. I have seen samples where someoene would take something done in preg and instead, use 3-4 separate functions (a-la strpos, strlen, etc..) and it still outstripped preg's speed.. this is why I find it humourous when I see people demanding en entire solution in preg (read: 1 line of code), thinking that less "code-bloat" means faster solutions.. but what they don't realize is the preg is heavy in cost performance... flexible and powerful as hell.. but as all things in life, there's a price to pay for it. Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted January 21, 2009 Share Posted January 21, 2009 oh and in case people didn't catch it..., my benchmark was multiplying microtime by 1000, so the difference is beyond negligible. Even looking at nrg_alpha's benchmark results, we're talking about .003s diff from doing 1000 calculations. Hehe.. yes.. on a single pass, people would not see the difference at all... it's just to get us "performance-freaks" rocks off Quote Link to comment Share on other sites More sharing options...
.josh Posted January 21, 2009 Share Posted January 21, 2009 Well unless you are doing some kind of huge batch job, I would still opt for the preg_match method, as it is the 1-line solution. I guess it just depends on what the OP needs it. Quote Link to comment Share on other sites More sharing options...
5kyy8lu3 Posted January 21, 2009 Author Share Posted January 21, 2009 Well unless you are doing some kind of huge batch job, I would still opt for the preg_match method, as it is the 1-line solution. I guess it just depends on what the OP needs it. I'll have a ton of others forms i need to validate but right now I'm taking one step at a time, I still can't get this to work, it's driving me crazy. Did I code this incorrectly? code for the form itself: <input type="text" name="cadence" maxlength="3" size="7"> code to validate it: $cadence = $_POST['cadence']; if ( ctype_digit($cadence) ) { if ( ( strlen($cadence) > 0 ) && ( strlen($cadence) < 4 ) ) { echo 'It works! <br><br>'; } else { $_SESSION['error_count']++; $_SESSION['cadence_err'] = 'Error: Cadence must be a numeral.'; echo $_SESSION['cadence_err'], '<br><br>'; } } no matter what I type into that box, i get 'Yay it works!' I even have an echo $cadence; below the validation code and it echo's whatever I type in, and even with something like 'abc' it still ok's the code, I don't get it Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted January 21, 2009 Share Posted January 21, 2009 5kyy8lu3, I would start by trouble shooting your variables.. ensure that indeed $_POST['cadence'] is what you think it is.. (try echoing it out just to be sure)... Given the snippet you just provided, what happens if your variable fails ctype_digit? (hint: Currently nothing... as there is no else structure...) Not sure if you want to include some error in the event it doesn't pass this or not... Off topic, I'm curious as to why do you assign $_SESSION['cadence_err'] to a message, then output it separately? $_SESSION['error_count']++; echo $_SESSION['cadence_err'] = 'Error: Cadence must be a numeral.'; On a side note.. you can create a variable (say $stringLength) and assign strlen($cadence) to that, then check if($stringLength > 0 && $stringLength < 4){ This way, you don't make strlen calculate twice... just do it once, and store that into a variable that can in turn be checked multiple times without extra calculations... That's about all I can really think of off the top of my head..Perhaps CV can think of more and perhaps expand on it.. EDIT - Come to think of it, with maxlength="3" in your input, is ctype_digit even necessary? (haven't tried it to find out). Quote Link to comment Share on other sites More sharing options...
5kyy8lu3 Posted January 21, 2009 Author Share Posted January 21, 2009 fixed! i just wrote it wrong. instead of doing it nested i should've done all three checks in one if block. Quote Link to comment Share on other sites More sharing options...
.josh Posted January 21, 2009 Share Posted January 21, 2009 need to validate the length in your script. setting maxlength to 3 isn't enough, as someone can easily edit the form to remove that restriction and submit. try casting the value as a string: $cadence = (string) $_POST['cadence']; 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.