Sanitizing w/ preg_replace (beginner)

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
diseman
Forum Contributor
Posts: 174
Joined: Mon Jul 26, 2010 1:30 pm
Location: Florida

Sanitizing w/ preg_replace (beginner)

Post by diseman »

Hello Expert(s),

Taking it slow learning PHP and not sure about something. I have a php contact form w/ phone number fields that I want to format to 123-456-7890. What I currently have works, but I've been trying to research if there's a better way to do it. As a noob, I'm thinking concatenate maybe, but my attempts didn't work. Then I saw someone else who did it like me and it makes me wonder if this is in fact the right way to do it. Here's the code:

Code: Select all


$b_phone_h = preg_replace('/[\()]/', '', $b_phone_h); // Remove ( & )
$b_phone_h = preg_replace('/[ ]/', '-', $b_phone_h);  // Remove any spaces and replace with -
$b_phone_h = preg_replace('/[.]/', '-', $b_phone_h);  // Remove any . and replace with -

I have six phone fields on the form, which means if above is right - I'd have to enter a total of 18 preg_replace's, which doesn't seem right. Is there a way to have one preg_replace that covers all three replacements and reduce the code to one preg_replace for each phone field?

Please keep it simple and examples are GREATLY appreciated to learn by.

Thank you...
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Sanitizing w/ preg_replace (beginner)

Post by Weirdan »

  1. [] defines a character class in regexp - meaning any character from the list would match. Thus you can simply concat your character classes where you replace with the same value and use single regexp instead of the last two:

    Code: Select all

    $b_phone_h = preg_replace('/[ .]/', '', $b_phone_h);
  2. when you have several data items (phone fields in your case) all needing similar processing you don't need to replicate the code for every item. Such situations are best handled with arrays and loops. For example, if you can change your phone field names (in html) to 'phones[business]', 'phones[home]', etc, you'd be able to iterate over them like this:

    Code: Select all

    $phoneTypes = array('mobile', 'home', 'business');
    $phones = array();
    foreach ($phoneTypes as $type) {
        if (!isset($_POST['phones'][$type])) {
               die(ucfirst($type) . ' phone is a required field');
        }
        $phone = $_POST['phones'][$type];
        $phone = preg_replace('/[\()]/', '', $phone);
        $phone = preg_replace('/[. ]/', '-', $phone);
        $phones[$type] = $phone;
    }
    //do something with $phones here
    and be able to add any number of phone fields just by adding them to the form and $phoneTypes array.
  3. Generally all you should care about is that there's enough digits in the number - after all this is all the phone companies care about when you enter a number. So you don't have to store dashes, dots, spaces, braces, etc - because they are only meaningful to humans, not computers or phones. However, if you intend to support foreign phone numbers this can get tricky because different countries use different number of digits. For example full number somewhere near Taipei would be 12 digits, while in Russia it would be 11 and in Greenland it would be only 9.
jraede
Forum Contributor
Posts: 254
Joined: Tue Feb 16, 2010 5:39 pm

Re: Sanitizing w/ preg_replace (beginner)

Post by jraede »

Just a correction to Weirdan's answer, the . is a special character in regex that matches any non-whitespace character. I'm pretty sure you'd have to escape it with a backslash to avoid matching all characters and replacing it with ''. And also you may as well replace all whitespace characters instead of just a space to be safe. I may have got the order wrong of the characters within that range, so you'd have to switch the \. with \s if you get an error in the regex.

So it should be [syntax]$b_phone_h = preg_replace('/[\s\.]/', '', $b_phone_h);[/syntax]
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Sanitizing w/ preg_replace (beginner)

Post by Weirdan »

jraede wrote:Just a correction to Weirdan's answer, the . is a special character in regex
But not in a character class:
php manual wrote: All non-alphanumeric characters other than \, -, ^ (at the start) and the terminating ] are non-special in character classes, but it does no harm if they are escaped. The pattern terminator is always special and must be escaped when used within an expression.
User avatar
diseman
Forum Contributor
Posts: 174
Joined: Mon Jul 26, 2010 1:30 pm
Location: Florida

Re: Sanitizing w/ preg_replace (beginner)

Post by diseman »

Thank you for the help. Its taken so long to reply because I've literally been studying the array & foreach commands for several hours today.

@weirdan - I tried running the code you supplied, but kept getting 'missing entry' error even though they were entered. That's OK, it got me learning about arrays and foreach today, which is interesting. Then I found some very simple examples, which I liked a lot and then wanted to make work in my program. However, I can't get it to work after hours of attempts and reading. Check this out:

My ultimate goal is to achieve this in my .php file:

Code: Select all

$b_phone_h = preg_replace('/[\()]/', '', $b_phone_h);        // @weirdan notice the $ signs in this line
When I have that in the page, it effectively removes the ( & ) from the phone field. Good....

So, I put in something like 18 lines of preg_replace to cover all values & requirements. Then weiderman brings up the 'array,' which I then attempt.

I put the following code in, which when 'echo'd' (for testing purposes) does put it on the screen exactly right, but when un-echo'd - doesn't work. Nothing happens.

Code: Select all

$phoneType = array('$b_phone_h', '$b_phone_m', '$b_phone_w', '$cb_phone_h', '$cb_phone_m', '$cb_phone_w');

foreach ($phoneType as $value) {
	$value = preg_replace('/[\()]/', '', $value) ;
	$value = preg_replace('/[ .]/', '-', $value) ;
}
I had to add the $ to the field names in the array or the 'foreach' command would output the field names as 'b_phone_h' which won't work because the preg_replace command in my script needs/wants a $ in front of the value (see the comment in the code at the top of this posting).

As I said, when I echo the 'foreach' command it displays everything properly on the screen, but that's not what I need. I need the preg_replace to be executed before my data is inserted to db; not displayed to the screen for me to see.

Your help is greatly appreciated....
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Re: Sanitizing w/ preg_replace (beginner)

Post by superdezign »

Firstly, if these are coming from a form, then the values should be in one of the superglobal arrays. An example of a superglobal array is $_POST. If the submission method of your form is a POST request, which you can tell from the method attribute of your <form> element, then the data will be there. I recommend using that since the variables you are using are generated from the $_REQUEST superglobal, which can also hold data from GET requests (which come from the URL). So, instead of $b_phone_h, you'd use $_POST['b_phone_h']. Not that you HAVE to do that now, but keep that in mind for future reference.

Secondly, what you are trying to accomplish can be done with dollar signs. You'd just use a variable variable (not a typo). PHP has this capability to allow you to access variables without knowing their name. So, you could change your code to this:

Code: Select all

$phoneType = array('b_phone_h', 'b_phone_h', 'b_phone_w', 'cb_phone_h', 'cb_phone_m', 'cb_phone_w');

foreach ($phoneType as $value) {
        echo $$value;
} 
Notice the double dollar signs? Instead of looking at $value, it looks at the variable with the same name as $value's value, i.e $b_phone_h, $b_phone_m, etc.

Thirdly, sanitization and verification are different processes. Since all that you are doing is removing characters for sanitization, it's faster and simpler to just use str_replace. The parameters it takes are the value(s) to look for, the value(s) to replace those with, and the value(s) to do it to. So, you can use:

Code: Select all

$replaceThese = array('(', ')', ' ', '.');
$withThese    = array( '',  '', '-', '-');
str_replace($replaceThese, $withThese, $b_phone_h); 

There's a lot more I want to say, but I don't want to go too deep.
User avatar
diseman
Forum Contributor
Posts: 174
Joined: Mon Jul 26, 2010 1:30 pm
Location: Florida

Re: Sanitizing w/ preg_replace (beginner)

Post by diseman »

Thank you superdezign for taking the time to write so much; I'm grateful. I going through your posting piece by piece and testing. I'm on the str_replace for the moment, which I think is wonderfully simple and makes perfect sense even for a beginner. Surprisingly though, it's not working! I copy/pasted directly with no changes. I looked it up and you appear to have it right from what I've read, so not sure why it wouldn't be working. I even moved the block of code to all different parts of the page just to make sure... nothing.

The STR_REPLACE seems the most simple and intuitive, so if we can get that to work that would be great.

I'm going to place my code below. Maybe I'm not revealing something that will make all the difference:

Code: Select all


<?php

// Connect to server then db and return error if not completed

include_once ("../_includes/dbconnect.php");

	$b_firstname = ""; 
	$b_lastname = "";
	$b_address = "";
	$b_address2 = "";
	$b_city = "";
	$b_state = "";
	$b_zipcode = "";
	$b_ssn = "";
	$b_birthday = "";
	$b_dl = "";
	$b_phone_h = "";
	$b_phone_m = "";
	$b_phone_w = "";
	
	$cb_firstname = ""; 
	$cb_lastname = "";
	$cb_address = "";
	$cb_address2 = "";
	$cb_city = "";
	$cb_state = "";
	$cb_zipcode = "";
	$cb_ssn = "";
	$cb_birthday = "";
	$cb_dl = "";
	$cb_phone_h = "";
	$cb_phone_m = "";
	$cb_phone_w = "";
	
	
	if (isset($_POST['submit']))
{
	
	$b_firstname = $_POST['b_firstname']; 
	$b_lastname = $_POST['b_lastname'];
	$b_address = $_POST['b_address'];
	$b_address2 = $_POST['b_address2'];
	$b_city = $_POST['b_city'];
	$b_state = $_POST['b_state'];
	$b_zipcode = $_POST['b_zipcode'];
	$b_ssn = $_POST['b_ssn'];
	$b_birthday = $_POST['b_birthday'];
	$b_dl = $_POST['b_dl'];
	$b_phone_h = $_POST['b_phone_h'];
	$b_phone_m = $_POST['b_phone_m'];
	$b_phone_w = $_POST['b_phone_w'];
	
	$cb_firstname = $_POST['cb_firstname']; 
	$cb_lastname = $_POST['cb_lastname'];
	$cb_address = $_POST['cb_address'];
	$cb_address2 = $_POST['cb_address2'];
	$cb_city = $_POST['cb_city'];
	$cb_state = $_POST['cb_state'];
	$cb_zipcode = $_POST['cb_zipcode'];
	$cb_ssn = $_POST['cb_ssn'];
	$cb_birthday = $_POST['cb_birthday'];
	$cb_dl = $_POST['cb_dl'];
	$cb_phone_h = $_POST['cb_phone_h'];
	$cb_phone_m = $_POST['cb_phone_m'];
	$cb_phone_w = $_POST['cb_phone_w'];
	
/*
// Sanitize all phone number entries to our preferred format 

$b_phone_h = preg_replace('/[\()]/', '', $b_phone_h); 		// Remove ( & )
$b_phone_h = preg_replace('/[ .]/', '-', $b_phone_h);  	       // Remove any 'spaces' & '.' and replace with -

$b_phone_m = preg_replace('/[\()]/', '', $b_phone_m); 		// Remove ( & )
$b_phone_m = preg_replace('/[ .]/', '-', $b_phone_m);  	// Remove any 'spaces' & '.' and replace with -

$b_phone_w = preg_replace('/[\()]/', '', $b_phone_w); 		// Remove ( & )
$b_phone_w = preg_replace('/[ .]/', '-', $b_phone_w);  	// Remove any 'spaces' & '.' and replace with -


$cb_phone_h = preg_replace('/[\()]/', '', $cb_phone_h);	// Remove ( & )
$cb_phone_h = preg_replace('/[ .]/', '-', $cb_phone_h);  	// Remove any 'spaces' & '.' and replace with -

$cb_phone_m = preg_replace('/[\()]/', '', $cb_phone_m); 	// Remove ( & )
$cb_phone_m = preg_replace('/[ .]/', '-', $cb_phone_m);  	// Remove any 'spaces' & '.' and replace with -

$cb_phone_w = preg_replace('/[\()]/', '', $cb_phone_w); 	// Remove ( & )
$cb_phone_w = preg_replace('/[ .]/', '-', $cb_phone_w);  	// Remove any 'spaces' & '.' and replace with -
*/

/* Previous attempt with preg_replace. Not working

$phoneType = array('$b_phone_h', '$b_phone_m', '$b_phone_w', '$cb_phone_h', '$cb_phone_m', '$cb_phone_w');

foreach ($phoneType as $value) {
	$value = preg_replace('/[\()]/', '', $value) ;
	$value = preg_replace('/[ .]/', '-', $value) ;
}

*/

$replaceThese = array('(', ')', ' ', '.');
$withThese    = array( '',  '', '-', '-');
str_replace($replaceThese, $withThese, $b_phone_h);


// Insert data from form into db fields

$sql = "INSERT contact_info (

	b_firstname, 
	b_lastname,
	b_address,
	b_address2,
	b_city,
	b_state,
	b_zipcode,
	b_ssn,
	b_birthday,
	b_dl,
	b_phone_h,
	b_phone_m,
	b_phone_w,
	
	cb_firstname, 
	cb_lastname,
	cb_address,
	cb_address2,
	cb_city,
	cb_state,
	cb_zipcode,
	cb_ssn,
	cb_birthday,
	cb_dl,
	cb_phone_h,
	cb_phone_m,
	cb_phone_w)

VALUES (

	'$b_firstname',
	'$b_lastname',
	'$b_address',
	'$b_address2',
	'$b_city',
	'$b_state',
	'$b_zipcode',
	'$b_ssn',
	'$b_birthday',
	'$b_dl',
	'$b_phone_h',
	'$b_phone_m',
	'$b_phone_w',
	
	'$cb_firstname',
	'$cb_lastname',
	'$cb_address',
	'$cb_address2',
	'$cb_city',
	'$cb_state',
	'$cb_zipcode',
	'$cb_ssn',
	'$cb_birthday',
	'$cb_dl',
	'$cb_phone_h',
	'$cb_phone_m',
	'$cb_phone_w')";

// Check connection and insert data. If problem, indicate an error

if (!mysql_query($sql,$con))
  {
  die('Error: ' . mysql_error());
  }

// ---------------------------------------------------------------

$id = mysql_insert_id();

$q =  "Select * from contact_info where id=".$id;

$re = mysql_query($q);

if (!$re)
   die(mysql_error());
else
{
        $ro = mysql_fetch_object($re);

	$b_firstname = $ro->b_firstname; 
	$b_lastname = $ro->b_lastname;
	$b_address = $ro->b_address;
	$b_address2 = $ro->b_address2;
	$b_city = $ro->b_city;
	$b_state = $ro->b_state;
	$b_zipcode = $ro->b_zipcode;
	$b_ssn = $ro->b_ssn;
	$b_birthday = $ro->b_birthday;
	$b_dl = $ro->b_dl;
	$b_phone_h = $ro->b_phone_h;
	$b_phone_m = $ro->b_phone_m;
	$b_phone_w = $ro->b_phone_w;
	
	$cb_firstname = $ro->cb_firstname; 
	$cb_lastname = $ro->cb_lastname;
	$cb_address = $ro->cb_address;
	$cb_address2 = $ro->cb_address2;
	$cb_city = $ro->cb_city;
	$cb_state = $ro->cb_state;
	$cb_zipcode = $ro->cb_zipcode;
	$cb_ssn = $ro->cb_ssn;
	$cb_birthday = $ro->cb_birthday;
	$cb_dl = $ro->cb_dl;
	$cb_phone_h = $ro->cb_phone_h;
	$cb_phone_m = $ro->cb_phone_m;
	$cb_phone_w = $ro->cb_phone_w;


}

mysql_close($con) ;

}

?>


Thanks again for any help...
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Re: Sanitizing w/ preg_replace (beginner)

Post by superdezign »

Oh, sorry, you can blame me for not making that clearer.

The str_replace() function returns a value. It doesn't actually change the value that is given to it. So, you need to assign the value of the function to the variable.

Code: Select all

$replaceThese = array('(', ')', ' ', '.');
$withThese    = array( '',  '', '-', '-');
$b_phone_h = str_replace($replaceThese, $withThese, $b_phone_h); 
User avatar
diseman
Forum Contributor
Posts: 174
Joined: Mon Jul 26, 2010 1:30 pm
Location: Florida

Re: Sanitizing w/ preg_replace (beginner)

Post by diseman »

Thank you superdezign. That works very good and I'm lovin' it. I've now come down from 18 lines of code to 12, and finally 8. The remaining question is why can't I add another array and make a 'foreach' loop work with this str_replace? Why can't I do something like this:

Code: Select all

$phoneType = array('b_phone_h', 'b_phone_m', 'b_phone_w', 'cb_phone_h', 'cb_phone_m', 'cb_phone_w');
$replaceThese = array('(', ')', ' ', '.');
$withThese    = array( '',  '', '-', '-');
foreach ($phoneTypes as $value) {
$value = str_replace($replaceThese, $withThese, $value);
}
When I put echo in front of the first $value in the last line of the code and run it, I see why I think it's not working, but have no idea how to fix it or if it's even do'able.

Looking forward to your answer : )
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Re: Sanitizing w/ preg_replace (beginner)

Post by superdezign »

Remember when I said that you COULD use a variable variable?

Code: Select all

$phoneTypes = array('b_phone_h', 'b_phone_m', 'b_phone_w', 'cb_phone_h', 'cb_phone_m', 'cb_phone_w');
$replaceThese = array('(', ')', ' ', '.');
$withThese = array('', '', '-', '-');

foreach ($phoneTypes as $value) {
    $$value = str_replace($replaceThese, $withThese, $$value);
} 
By the way, you may notice that I changed the first array to "$phoneTypes" instead of "$phoneType". You had a type where you were defining "$phoneType", but using "$phoneTypes" in your foreach loop.
User avatar
diseman
Forum Contributor
Posts: 174
Joined: Mon Jul 26, 2010 1:30 pm
Location: Florida

Re: Sanitizing w/ preg_replace (beginner)

Post by diseman »

Great stuff superdezign. That works perfectly. I've now reduced more code and learned about preg_replace, arrays, foreach, and str_replace. Thank you for your working examples. They make learning A LOT easier.

A little mad about the double $ sign thing because I don't usually ask questions until after I've spent a long time trying to find the answer myself. Even php.net doesn't say anything about this double $ sign thing, so how are we supposed to know. Even now I'm not seeing anything on it.

Anyway, this PHP programming is fun stuff although challenging. Thank you for the great help. I'm going to move on to the next piece and see where I get hung up. It won't be long I'm sure of that. : )

Thanks again Superdezign. See you around!
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Re: Sanitizing w/ preg_replace (beginner)

Post by superdezign »

No problem. When I first started coming here, I didn't know anything about PHP. It's one of the most flexible and forgiving programming languages around, and learning to handle it is a separate task than learning how to properly tame it. Keep at it and stick with DevNetwork. Answering questions helps the learning process just as much as asking them because you learn whether your thought process is correct or not.
Post Reply