Jump to content

[SOLVED] EREG() Pattern help please, I'm stuck


Recommended Posts

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?

 

.

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)) {

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.

@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
)

@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.

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

)

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..

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.

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

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.

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.

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 ;)

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

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).

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'];

 

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.