Jump to content
Larry Ullman's Book Forums

Recommended Posts

Thank you Larry for suggesting to put the questions one by one.

 

So I will begin with with Registration chronologically:

 

The code for register is:

 

<?php
# Script 16.6 - register.php
// This is the registration page for the site.
ob_start();
require_once ('includes/config.inc.php');
$page_title = 'Register';
include('includes/head_part.html');

if (isset($_POST['submitted'])) { // Handle the form.

require_once (MYSQL);

// Trim all the incoming data:
$trimmed = array_map('trim', $_POST);

// Assume invalid values:
$fn = $ln = $e = $p = FALSE;

// Check for a first name:
if (preg_match ('/^[A-Z \'.-]{2,20}$/i', $trimmed['first_name'])) {
	$fn = mysqli_real_escape_string ($dbc, $trimmed['first_name']);
} else {
	echo '<p class="error">Please enter your first name!</p>';
}

// Check for a last name:
if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['last_name'])) {
	$ln = mysqli_real_escape_string ($dbc, $trimmed['last_name']);
} else {
	echo '<p class="error">Please enter your last name!</p>';
}

// Check for a username:
if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['username'])) {
	$un = mysqli_real_escape_string ($dbc, $trimmed['username']);
} else {
	echo '<p class="error">Please enter your username!</p>';
}

// Check for an email address:
if (preg_match ('/^[\w.-]+@[\w.-]+\.[A-Za-z]{2,6}$/', $trimmed['email'])) {
	$e = mysqli_real_escape_string ($dbc, $trimmed['email']);
} else {
	echo '<p class="error">Please enter a valid email address!</p>';
}	

// Check for a password and match against the confirmed password:
if (preg_match ('/^\w{4,20}$/', $trimmed['password1']) ) {
	if ($trimmed['password1'] == $trimmed['password2']) {
		$p = mysqli_real_escape_string ($dbc, $trimmed['password1']);
	} else {
		echo '<p class="error">Your password did not match the confirmed password!</p>';
	}
} else {
	echo '<p class="error">Please enter a valid password!</p>';
}

// Check for country:
if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['country'])) {
	$c = mysqli_real_escape_string ($dbc, $trimmed['country']);
} else {
	echo '<p class="error">Please enter your Country!</p>';		
}	

//Check for state:	
if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['state'])) {	
	$s = mysqli_real_escape_string ($dbc, $trimmed['state']);
	} else {
	echo '<p class="error">Please enter your State!</p>';	
}

if ($fn && $ln && $e && $p && $un && $c) { // If everything's OK...

//combine first and last names
$name = $fn. ' ' .$ln;

// Make sure the email address is available:
$q = "SELECT user_id FROM users WHERE email='$e'";
$r = mysqli_query ($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));

if (mysqli_num_rows($r) == 0) { // Available.

// Create the activation code:
$a = md5(uniqid(rand(), true));

// Add the user to the database:
$q = "INSERT INTO users (name, username, email, pass, country, state, active, registration_date) VALUES ('$name', '$un', '$e', SHA1('$p'), '$c', '$s', '$a', NOW() )";
$r = mysqli_query ($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));

if (mysqli_affected_rows($dbc) == 1) { // If it ran OK.

// Send the email:
$body = "Thank you for registering at the Venture Wilderness Website. Just one last step to activate your account, please click the following link:\n\n";
$body .= BASE_URL . 'registrar/activate.php?x=' . urlencode($e) . "&y=$a\n\n";
$body .= "This will activate your login ability and verify your email. If you have any questions or need some assistance, please feel free to contact our Staff (from 7 AM to 7 PM (EST = European Standard Time).\n\n";
$body .= "If you are interested to know how we evaluate user data, please see our Privacy Policy at https://venture-wilderness.com/services.php?tab=2#TabbedPanels2'.\n\n";
$body .= "Venture Wilderness";  
mail($trimmed['email'], 'Registration Confirmation', $body, 'From: services@venture-wilderness.com');

// Finish the page:
echo '<p>Thank you for registering! A confirmation email has been sent to your address. Please click the link in that email to verify your email and activate your account.</p>';
//include ('includes/footer.html'); // Include the HTML footer.
exit(); // Stop the page.

} else { // If it did not run OK.
echo '<p class="error">You could not be registered due to a system error. We apologize for any inconvenience.</p>';
}

} else { // The email address is not available.
echo '<p class="error">That email address is already registered. If you have forgotten your password, use the link, "Retrieve Password" to have your password sent to you.</p>';
}

} else { // If one of the data tests failed.
echo '<p class="error">Please re-enter your passwords and try again.</p>';
}

mysqli_close($dbc);

} // End of the main Submit conditional.

?>	

<link href="../_css/reg_log.css" rel="stylesheet" type="text/css" />

<div id="mainContent">


<table width="550" border="0">
 <tr>
<td width="150"><h2>Registration</h2></td>
<td width="150"><a href="../regist_tnc.php" title="Terms & Conditions">Terms & Conditions</a>
     	</td>
<td width="230"><label for="checkbox">I accept Terms & Conditions<class ="rustred" input name="acceptance" type="checkbox" value="checkox" checked /></td>
 </tr>
</table>

     	<form action="register.php" method="post">

<fieldset>

<p><label for="">First Name</label><input name="first_name" type="text" class="textField" value="<?php if (isset($trimmed['first_name'])) echo $trimmed['first_name']; ?>" size="20" maxlength="20" /></p>

<p><label for="">Last Name</label><input name="last_name" type="text" class="textField" value="<?php if (isset($trimmed['last_name'])) echo $trimmed['last_name']; ?>" size="20" maxlength="40" /></p>

 	<p><label for="">Username</label><input name="username" type="text" class="textField" value="<?php if (isset($trimmed['username'])) echo $trimmed['username']; ?>" size="20" maxlength="40" /></p>

<p><label for="">Email Address</label><input name="email" type="text" class="textField" value="<?php if (isset($trimmed['email'])) echo $trimmed['email']; ?>" size="20" maxlength="80" /></p>	

 	<p><label for="">Password</label><input name="password1" type="password" class="textField" size="20" maxlength="20" /></p> 

<p><label for="">Confirm Password</label><input name="password2" type="password" class="textField" size="20" maxlength="20" /></p>

<p><label for="country">Country</label><input name="country" type="text" class="textField" value="<?php if (isset($trimmed['country'])) echo $trimmed['country']; ?>" size="20" maxlength="30" /></p>

<p><label for="state">State</label><input name="state" type="text" class="textField" value="<?php if (isset($trimmed['state'])) echo $trimmed['state']; ?>" size="20" maxlength="30" /></p>

<div id="submit" align="left"><input name="submit" type="image"  value="Join The Elite Travellers!"  src="../_images/page_decos/register_btn.png"/></div>
<p><input type="hidden" name="submitted"  value="TRUE" /></p>	

</fieldset>
</form>  	
</div>
<?php
include ('includes/foot_part.html'); 
// Flush the buffered output.
ob_end_flush();
?>

 

On registering a user, it throws an error, but enters the user in the database. The error occurs because I have an entry "State" in the form which is to be filled up only if the users "Country" is "United States" (because of a. varying "Sales Tax or VAT " in each of the States and b. vast distances between the main airports - i.e. cost of air ticket: New York - Delhi is approx. EUR 1250.- whereas LA - Delhi is approx. EUR 1650. Other Countries have the same tax in all their states and provinces and most flights are also priced approximately same. This entry is undefined and is not an error, but a NOTICE or warning. Reporting Notices is turned "OFF" in your script as well as on my local and remote servers. So I don't know how to bypass it.

I tried to fix it with PHP so that the field "State" will only appear if the "Country" is set to "United States", but was unable to achieve it.

 

 An error occurred in script '/home/zabber1/public_html/venture-wilderness/registrar/register.php' on line 87: Undefined variable: s <br />Date/Time: 5-21-2011 13:12:07 <br /><pre>Array (

 	[GLOBALS] => Array

  *RECURSION*

 	[_ENV] => Array

     	(

             [CONTENT_LENGTH] => 191

 [size=2]            [CONTENT_TYPE] => application/x-www-form-urlencoded[/size]

 

I also tried putting the lists of "Countries" and "States" as Record Sets using Dreamweaver. It works perfectly on the testing server, but does not work on the remote server. The problem seems to be the "mysql_select_db" in the following script that Dreamweaver generates:

 

mysql_select_db($database_registrations, $registrations);
$query_rsCountries = "SELECT * FROM countries ORDER BY countryName ASC";
$rsCountries = mysql_query($query_rsCountries, $registrations_con) or die(mysql_error());
$row_rsCountries = mysql_fetch_assoc($rsCountries);
$totalRows_rsCountries = mysql_num_rows($rsCountries);

mysql_select_db($database_registrations, $registrations);
$query_rsStates = "SELECT * FROM states ORDER BY stateName ASC";
$rsStates = mysql_query($query_rsStates, $registrations_con) or die(mysql_error());
$row_rsStates = mysql_fetch_assoc($rsStates);
$totalRows_rsStates = mysql_num_rows($rsStates);

 

In addition when any users register the message they get looks looks this:

 

1306001907-U1.jpg

 

Is there a way to display this gracefully?

 

Knowing how to solve these errors will help me solve all other problems regarding the application.

 

Thank you :)

Link to comment
Share on other sites

I'm not familiar with record sets in Dreamweaver, but I think I can respond to your other questions.

 

First off, if you want to make a State field appear only when the US is selected for the Country field, then you're going to need to use some JavaScript. How familiar are you with JavaScript? If you want, I will gladly help you accomplish what you want to, but please first tell me how much JavaScript you know, and also exactly what you want to accomplish with this.

 

Likewise, if you want to make the error display more "gracefully", you should probably use sticky forms (discussed in the book), and place a little message in red or something next to the State field asking them to please enter a state.

 

Hopefully that somewhat answers your questions. Please let us know if you have any other questions.

  • Upvote 2
Link to comment
Share on other sites

You could address the state issue in your validation code:

 

//Check for state:      
       if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['state']) && $trimmed['country'] == 'US') {  // assuming country code is US and not USA
               $s = mysqli_real_escape_string ($dbc, $trimmed['state']);
               } else {
               echo '<p class="error">Please enter your State!</p>';   
       }

Then the error message would only be displayed if the country is 'US' and the State field is left blank. If the country isn't 'US' no error would be displayed whether or not the state field is completed. Easier to do it this way than using Javascript to create the state field when the country is US, although the Javascript way would be less confusing to non-US residents.

 

Agree with HartleySan's suggestion of sticky fields. Users expect 'stickiness' these days.

  • Upvote 2
Link to comment
Share on other sites

As usual, Paul comes in with a stunning answer. Thanks, Paul. And certainly, using a test like that would eliminate the need for JS. If you go that route though, I'd definitely put a note next to the State field telling the user that they only need to enter a state if the country is the US.

 

Better yet, you might want to make a drop-down list with all the states. That seems more intuitive for users. Also, you could set the default value for the drop-down list to something like --. I think that's pretty straightforward.

 

If you decide to go the JS route, you'll need to attach an event to the Country field to basically detect when info is entered for the Country field, and when it is, test whether it's some variation on the US (this can be tricky, and will probably require a regex), and if the country is the US, you'll need to use DHTML to dynamically insert a div with the State field below the Country field.

 

Not incredibly difficult, but not for beginners of JS either.

 

Anyway, I think Paul's suggestion would be easier with a little note next to the State field. Also, a drop-down list for the states (and countries) would be best, I think.

  • Upvote 2
Link to comment
Share on other sites

Thank you very much for the input!

 

@Hartley: JS would certainly solve that problem, but I am only a dabbler with it. I understand to some extent the written code, but can hardly concoct a string to any particular cause or effect. Doing it just with PHP would be okay and as for "not confusing the user" I would put a note in the state field itself "Fill only if your country is United States" with the help of some new HTML 5 (placeholder) attribute. The note would erase itself as soon as the user enters cursor in the field to put any content inside.

 

The entry for Country in the pull down is United States.

 

@Paul Swanson: This seems the easier and simpler way out, but on implementing it continues to give the same "undefined" error:

 

  
<p>An error occurred in script 'XYZ/venture-wilderness/registrar/register.php' on line 86: Undefined variable: s <br />Date/Time: 5-25-2011 06:52:24 <br /><pre>Array (  

 

Would be great if we can develop/manipulate the strings to comply to our needs.

 

I was testing in a similar way, but more so on the lines: (This also generated errors..)

 

//Check for State
if (isset(Country['United States'])) {

(preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['state'])) {  
           	$s = mysqli_real_escape_string ($dbc, $trimmed['state']);
}
}

 

Sorry for responding so late, but the board somehow did not inform with the usual email.

 

Regards to all :)

Link to comment
Share on other sites

The German language and the German people seem to have some fantastic expressions!

 

And here's one more - one of my favorites. When you want to wish someone good luck:

 

Hals- und Beinbruch! (= wish you broken neck and leg..) :lol:

 

 

Couple of small script issues and maybe the one below needs to be tweaked as it does not enter "state" to the database even when the country has been assigned as ['United States'] and the "states" field has been filled up.. In addition it shows the message "Please enter your State!" to every successful Registration:

//Check for state - courtesy Swanson:      
       if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['state']) && $trimmed['country'] == 'US') {  // assuming country code is US and not USA
               $s = mysqli_real_escape_string ($dbc, $trimmed['state']);
               } else {
               echo '<p class="error">Please enter your State!</p>';   
       }

 

If there is a way to allow symbols in the "username" and "passwords" and allow an integer as the first character in a username (at the moment it does not accept it)? It is becoming common practice now a days to use symbols especially in passwords and so on.

 

Thanks for any suggestions.

Link to comment
Share on other sites

If your users are selecting 'United States' instead of US for the country, the code needs to be altered to this:

if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['state']) && $trimmed['country'] == 'United States') {  
   	$s = mysqli_real_escape_string ($dbc, $trimmed['state']);
} else {
   	echo '<p class="error">Please enter your State!</p>';
}

To allow digits or symbols in your username and/or password fields, you'll need to alter the pattern you are using in your regular expression. The class [:alnum:] will pickup all letters and numbers. [:punct:] will add punctuation characters. A combination of those should suit your purposes.

  • Upvote 2
Link to comment
Share on other sites

Hi Paul,

 

Thanks for pointing that out. Now it definitely does not show the message and also adds the state when the users enter country as United States and their state.

 

However, when

 

1. a registrant whose country is not United States leaves the field blank as instructed, it still shows the message, "Please enter your State!"

 

2. a registrant whose country is a United States, but leaves it the state blank, it shows the the same message, though it continues and registers the user. This however, is quite in order and I will make the form sticky and return it to the user to complete.

 

Regards

Link to comment
Share on other sites

If you nest the state validation within the country validation, you should get the missing state message only when the country is 'United States':

// Check for country:
if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['country'])) {
$c = mysqli_real_escape_string ($dbc, $trimmed['country']);

// Check for State if country is 'United States':
if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['state']) && $trimmed['country'] == 'United States') {
   	$s = mysqli_real_escape_string ($dbc, $trimmed['state']);
} else {
   	$s = NULL;
   	echo '<p class="error">Please enter your State!</p>';
}

} else {
echo '<p class="error">Please enter your Country!</p>';
}

That should take care of your first issue. For the second, I usually create an array to hold error messages and add to that array when the validation indicates a required entry was missing or the wrong data format. If the array is empty, I do the database query, if not I print all the error messages and don't even attempt the database query. I don't have the same edition of the book as you, but an example might be in your edition (it's not in the 2nd edition, but it is in the "PHP 5 Advanced" book). Essentially, at the very beginning of form validation, after checking for form submission, create an array variable to store error messages instead of immediately printing them:

if (isset ($_POST['submitted']) {
$errors = array ();

// form field validations ...
// Check for country:
if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['country'])) {
   	$c = mysqli_real_escape_string ($dbc, $trimmed['country']);

   	// Check for State if country is 'United States':
   	if (preg_match ('/^[A-Z \'.-]{2,40}$/i', $trimmed['state']) && $trimmed['country'] == 'United States') {
       	$s = mysqli_real_escape_string ($dbc, $trimmed['state']);
       } else {
       	$s = NULL;
       	$errors[] = 'Please enter your State!';
       }

	} else {
   	$c = NULL;
   	$errors[] = 'Please enter your Country!';
	}

// more fields validated ...
// ...

// if errors, print them, otherwise update database
if (!empty ($errors)) { // we have errors
   	echo '<div class="error">';
   	foreach ($errors as $error) {
       	echo $error . '<br />';
   	}
   	echo '</div>';
} else { // no errors, do database query
   	// place your database query code here
} // end of $errors conditional
} // end of form validation

Using a method such as this one will ensure that you don't update the database until you have all of the information required.

  • Upvote 2
Link to comment
Share on other sites

  • 3 weeks later...

(admin/mod: if you feel this should be a separate question in a different place, please move it to the appropriate location)

Hi,

Did me a great favor by staying off php for a while and now recuperated I am back with another question concerning my script. That is good advice by Larry in the book!

In my log-in and registration php application, I have my links in the sidebar and these remain visible when clicked to show different elements in the main content.

However, these do not show as activated or inert when their corresponding element is showing in the main content. For example I hover over the link it changes its color and I click on it, it shows the login form, but the link to the login form does not show as an activated link..that cannot be used again.

The last behavior property (below) in the css file seems to make no difference at all.

 

 
<?php
// Display links based upon the login status - (if user is logged in):
if (isset($_SESSION['user_id'])) {
echo '<a href="log_out.php" title="Logout">Logout</a><br />
   	<a href="change_password.php" title="Change Your Password">Change Password</a><br />
   	<a href="../reg_log.php" title="Login">Login</a>';
}
?>

 

Here's the CSS:

 #sidebar a:hover {
background-color: #E0DDD8;
}
 /* When the link is pressed down and showing the element; this property is not showing */

#sidebar a:active {
background-color: #E0DDD8;
cursor:default;
}

 

Any ideas how to achieve this?

Thank you

Link to comment
Share on other sites

Is CSS the active pseudo class is only used to style the link for when it is pressed - so that declaration will take place when you click... it won't have any impact once the page reloads etc... Can be confusing if you've used :visited before.

 

I don't think what you want to do is apply the test individually - if I was doing it in PHP I'd probably create a function that takes the link href and link text and outputs the link HTML dynamically... something like:

 

function print_link($href, $title, $page){

 $class = (strpos($_SERVER['REQUEST_URI'], $page)) ? ' class="active" ' : '';

 echo '<a href="' . $href . '"' . $class . '>' . $title . '</a>';

}

 

A little crude and would require fleshing out but you get the idea - then create an md-array containing all the links in your sidebar including:

 

$href = The URL you want to link to

$title = Text anchor for the link

$page = Unique portion of the URL that will be present when on that page

 

Then a quick foreach loop calling that function could print all your links with an 'active' class applied to the one representing the current page.

 

Or if thats overkill use jQuery to do the same thing:

 

$('#sidebar > a').each(function(){

// Check if anchor matches URL

   // If so apply the class
   $(this).addClass('active');

});

  • Upvote 2
Link to comment
Share on other sites

I'm not sure I understood exactly what you want to do, but if you want for instance to give a different background color to the link corresponding to the current page, here is one way of doing it. It's less advanced and less dynamic than what Jonathon and Stuart propose, but it works too.

 

— The opening <body> tag of the html pages is in my header.html file. I added an "id" attribute to the <body> tag, represented by a variable.

<body id="<?php echo $body_id ?>">

 

— On each separate page, I give a different value to the $body_id variable. For instance:

$body_id = "index_page";
$body_id = "login_page";

 

— In the navigation menu, each link also has a unique "id" attribute:

<a href="/index.php" id="index_link">Home</a>
<a href="/login.php" id="login_link">Log In</a>

 

— Then, in my css file, I give different background colors to the links according to their status.

Ordinary links:

#navigation li a, #navigation li a:visited
{ background: #dcdcdc; color: #10190e;}
#navigation li a:hover, #navigation li a:focus, #navigation li a:active
{ background: #a7ccf7; color: #10190e; }

 

Link for the current page:

body#index_page a#index_link,
body#login_page a#login_link
{ background: #627dc6; color: #ffffff; }

 

Which means:

the <a> tag with an "index_link" id attribute on the page where <body> has an "index_page" id attribute

and

the <a> tag with a "login_link" id attribute on the page where <body> has a "login_page" id attribute

have a blue background (instead of grey for ordinary links).

 

I hope this helps,

  • Upvote 2
Link to comment
Share on other sites

@ Stuart

 

Thanks for the input, but it sounds a little hazy and complex. But in retrospect:

 

@Josee

 

This is more understandable and manageable, at least, to a nit wit like me! It was the, as in your words below, what was baffling me:

 

 

— The opening <body> tag of the html pages is in my header.html file (in my case head_part.html). I added an "id" attribute to the <body> tag, represented by a variable.

<body id="<?php echo $body_id ?>">

 

Now, with this under the belt I should be able to fix the problem. I will get back as soon as I am done.

 

Thanks a ton..

Link to comment
Share on other sites

 Share

×
×
  • Create New...