Let Your Users Log In

January 6th, 2012

Something everyone should do once ( or several times ) when learning PHP is create a simple user and log in system. It is the basis of many different types of web sites, forums, WordPress sites, ebay, even search engines (Google) let you log in to customize your experience and access advanced features.

Let’s stick to just the user system here, no fancy features or tricky security. Just the basics that you can expand on later. The steps will be Registration, Log In,  Log Out. To save space I won’t include the html that is involved, so you’ll need to take some initiative and handle that part.

CREATE TABLE `site_users` (
  `name` varchar(255) NOT NULL,
  `email` text NOT NULL,
  `password` text NOT NULL,
  `status` varchar(255) NOT NULL default ''
);

There’s your user table in sql query format. We will be using MySQL and it is probably easiest to just add that table in a PHPMyAdmin interface unless you have a better way already.

Next create a page that shows some input fields for registration. name email and password are fine.

<?php
//first connect to MySQL and select the database you want, use your own code here
$conn = mysql_connect($database_host, $database_user, $database_pass);
mysql_select_db($database_name);
//initializing variables
$completed_message = '';
$error_message = '';
//then check if there was a post, there are many ways to check, use whatever you prefer
if($_SERVER['REQUEST_METHOD'] == 'POST'){
    if(strlen($_POST['name']) < 3){
        $error_message = "the 'name' was not long enough";
    }elseif(strlen($_POST['email']) < 3){
        $error_message = "the 'email' was not long enough";
    }elseif(strlen($_POST['password']) < 3){
        $error_message = "the 'password' was not long enough";
    }else{
    //insert data:
        mysql_query("INSERT INTO site_users SET name='".$_POST['name']."', email='".$_POST['email']."', password='".$_POST['password']."'");
        $completed_message = "Your new account has been created, sign in now";
    }
}
//if $completed_message != '' then we did not submit the form, or it failed. if it was blank for example it would fail
if($completed_message != ''){
    echo $error_message;
//show an html form  for registration that includes a field for name, password, email, and a submit button
...
}else{
    echo $completed_message; //and that's it, the form was submitted and completed
}
?>

Did you have trouble reading through that example file? If so review MySQL queries and other basics and it should become clear. I used the format “INSERT INTO site_users SET x=y etc.” which isn’t as common as other insert statement formats, but I find it to be superior. Since we checked all the fields for length by using strlen(…) < 3 we are sure that there was at least something entered into the fields. It’s a terribly incomplete check but you can probably figure out how to add more tests depending on your needs. You should always make sure strings are escaped, don’t allow unescapped user input in MySQL queries.

If for example you want to make sure they don’t just fill fields with spaces you can use regular expressions to see what kind of characters were entered.

There is one test I specifically want to show you. Assume the same file as above, but instead of just the insert query:

...
}else{
    //insert data:
        $test_name = mysql_query("SELECT name FROM site_users WHERE name = '".$_POST['name']."'");
        if(mysql_num_rows($test_name) > 0){
            $error_message = "That name is already in use, please enter a new name.";
        }else{
            mysql_query("INSERT INTO site_users SET name='".$_POST['name']."', email='".$_POST['email']."', password='".$_POST['password']."'");
            $completed_message = "Your new account has been created, sign in now";
        }
    }
...

That is one of several ways to prevent a user from using a name that already exists. The name needs to be unique. You could also repeat that for email addresses if you want users to only have one account for 1 email address. Start a new file for the next example.

<?php
//first connect to MySQL and select the database you want, use your own code here
...
//start a session
session_start();
//initializing variables
$completed_message = '';
$error_message = '';
$session_message = '';
//then check if there was a post, there are many ways to check, use whatever you prefer
if($_SERVER['REQUEST_METHOD'] == 'POST'){
    if(strlen($_POST['name']) >= 3){
        $get_user = mysql_query("SELECT * FROM site_users WHERE name = '".$_POST['name']."'");
        $user_row = mysql_fetch_array($get_user);
        if(!$user_row){
            $error_message = "there is no user by that name";
        }elseif($user_row['password'] != $_POST['password']){
            $error_message = "the entered password was incorrect";
        }elseif($user_row['status'] == 'banned'){ //I'll explain this later
            $error_message = "you have been banned from this site, you cannot log in";
        }else{
            $completed_message = 'you are now logged in, welcome!'
            $_SESSION['site_user']['name'] = $user_row['name'];
            $_SESSION['site_user']['password'] = $user_row['password'];
        }
    }else{
        $error_message = "enter your name and password";
    }
}else{
    if( $_SESSION['site_user']['name'] ){
        $get_user = mysql_query("SELECT * FROM site_users WHERE name = '".$_POST['name']."'");
        $user_row = mysql_fetch_array($get_user);
        if(!$user_row){
            $error_message = "your session is invalid";
        }elseif($user_row['password'] != $_SESSION['site_user']['password']){
            $error_message = "your session is invalid";
        }elseif($user_row['status'] == 'banned'){
            $error_message = "you have been banned from this site, your session is invalid";
        }else{
            $session_message = "Logged in as ".$user_row['name'];
        }
        if($session_message == ''){
            unset($_SESSION['site_user']);
        }
    }
}
//if $completed_message != '' then we did not submit the form, or it failed. if it was blank for example it would fail
if($completed_message != ''){
    echo $error_message;
    echo $session_message;
//show an html login form that includes a field for name, password, and a submit button
...
}else{
    echo $completed_message;
}
?>

That probably seemed unnecessarily long but I wanted to show some details of what goes on in a login system. It checks carefully that you are properly logged in on every page load. Sessions are a way of handling a user or login behind he scenes using cookies and server based storage. session_start() is always called early to ensure that it is before any headers or html output. Make sure any html is below the main PHP blocks in these files for that reason.

Once you have logged in you stay logged in for a while, or until the browser closes. These settings can be adjusted with PHP’s session functions.

To logout, just make a link to a logout page.

<?php
//first connect to MySQL and select the database you want, use your own code here
...
//start a session
session_start();
unset($_SESSION['site_user']);
echo "you are now logged out";
?>

The field called ‘status’ is in the original table and is checked in the login portions. Status is blank normally, meaning the user is valid and ‘normal’. If a user did something wrong and you want to keep them off the site, well that is what the status ‘banned’ is for. It is checked in the login area and the user is never logged in if they are banned. They are also logged out the moment the system is able to once they are banned.

The code to ban someone would go something like this:

<?php
//first connect to MySQL and select the database you want, use your own code here
...
mysql_query("UPDATE site_users SET status='banned' WHERE name = '".$_POST['name']."'");
...
?>

Parsing XML in PHP

December 7th, 2011

I’m sure many php users have needed to read some xml data into a php program and looked around hoping to find a function that can parse an XML file with a few lines of code. The road to simple XML usage may not be that short, but we’ll explore some techniques to get the data you want from an xml source.
First define some xml:

$contents = ‘
<rss version=”2.0″>
<channel>
<item>
<title>Orange Cat</title>
<link>http://www.phpprogrammer.co.uk/</link>
<description>A nice tabby.</description>
</item>
<item>
<title>Black Cat</title>
<link>http://www.phpprogrammer.co.uk/</link>
<description>A shy cat.</description>
</item>
</channel>
</rss>
‘;

Then parse the XML with this PHP code:

$parser = xml_parser_create('UTF-8');
$did_parse = xml_parse_into_struct($parser, trim($contents), $xml_values);
if(!$did_parse) {
	echo xml_error_string(xml_get_error_code($parser)) . " error on line: " . xml_get_current_line_number($parser);
}

The above example takes an “XML document”, in the form of a string, and parses it into an array ($xml_values). The array style and structure is complicated, but we will go through some simple steps to rearrange it into a usable format. $parser is an object. Functions like xml_parse_into_struct($parser … ) take $parser as an argument.
Read the rest of this entry »

Cookies – PHP can help with cookies

December 6th, 2011

Cookies are a long standing method of storing information so it can be used again on a per user basis. Prior to database and server based sessions becoming popular cookies saw use in more complex ways. There are still a component of sessions and used on most web sites, from shopping carts to web mail. In PHP it isn’t hard to get started with cookies.

setcookie("UserInfo", "3644 Alder St", time() + 3600, "/~phppro/", "iodigitalsec.com");

That example shows an example of setting the cookie UserInfo to a street address.
Read the rest of this entry »

PHP Regular Expression Techniques – Part 2: Characters

October 8th, 2011

Now we turn to a component of regular expressions that cannot be left out. We will be dealing with characters, how to use them, and how to escape them when needed. Regular expressions are explained in the PHP manual, and in this article we are focusing on the type that are Perl compatible, like in the function preg_match. The pattern is the regular expression we are using in each case. Since it uses a slash at the beginning and end, here’s the first thing to understand about characters in patterns: each character has a meaning or function, and escaping the character gives it a different meaning.

preg_replace("/catalog/toys/", "catalog/fun", "http://shop.com/catalog/toys");
//this basically cannot work because of the 2nd slash

preg_replace("/catalog/toys/", "catalog/fun", "http://shop.com/catalog/toys");
//this is correct

Escaping a character, as shown, is usually butting the backslash character before it. It is also normal to put it in front of a double quote or another backslash in a PHP string like that anyway, but in patterns we use it for a various things.

preg_replace("/[rn]/", "", "http://shop.com/catalog/toysn"); //removes the newline

r and n are also standard php string characters representing newlines. (There may be different systems for newlines from different operating systems and programs, some use n only, some use rn.) The [] brackets in the pattern mean you want to match any character inside the brackets. The function basically means replace r or n with “”. If you wanted to actually match brackets instead of that you can escape them too: []
Read the rest of this entry »

Tips for OOP Programming with PHP- Part 2: Object Storage

October 8th, 2011

Before starting this article/tutorial you should already be familiar with PHP, and basic class and object syntax. This article is going to go through some useful operations you can do with objects. The first thing I want to demonstrate is how to store objects and their member variables.

class MyCart{

	var $items;

	function add_item ($artnr, $num){

		$this->items[$artnr] += $num;

	}

}

session_start();

$_SESSION['user_cart'] = new MyCart();

In this case we are storing the object in the session variable. It is a fairly painless process, and getting that stored object on the next page the user loads is just as easy, after session_start() it will be available just like a session variable. If you try to use the session stored object on a page that does not have the class’s declaration, class MyCart{}, you will get a generic object with no member functions, as explained on the PHP manual page ‘Object Serialization’.

$user_cart = new MyCart();

$user_cart_string_data = serialize($user_cart);

$fp = fopen('data.txt', 'w');

fwrite($fp, $user_cart_string_data);

fclose($fp);

This is another basic method of storing objects. We converted the object to a string representation, and made or overwrote a file with that data. If it is not already clear, you restore the object by reading the file into a string, then using unserialize on it, reversing the effects of serialize. Like the session type of storage, you need the class to be defined in any file that uses that type of object.
Read the rest of this entry »

UNIX Timestamp Explained – A PHP Tutorial

October 4th, 2011

Understanding PHP’s date and time functions doesn’t seem difficult, but if you don’t already have a grasp of the UNIX timestamp system you won’t get the most out of them. time() is a PHP function that returns the current UNIX timestamp, which is a number. Specifically, it is the number of “Seconds since the UNIX Epoch (January 1 1970 00:00:00 GMT)”. It is independent of locations/timezones so it makes sense to use it as absolute time for computer and IT purposes and it is a number that can be held in 4 bytes, so it’s easy to store.

echo date ("l dS of F Y h:i:s A", time()); //current date and time
echo date ("l dS of F Y h:i:s A", time() - (60 * 60)); //date and time an hour ago
echo date ("l dS of F Y h:i:s A", time() + (60 * 60 * 24 * 90)); //date and time in 90 days

As you can see time() can be useful for doing simple math to get future or previous values. When stored in a database, the UNIX timestamp can be easily searched and modified, and there are many practical uses for it in programming languages, software, and technology.

To sum it up the UNIX timestamp is just the number of seconds since the start of 1970. This means it cannot hold dates that occurred before that time. In theory there are also future dates that it may not hold, because the programming language isn’t expecting numbers that high. This introduction to PHP’s UNIX timestamp capabilities doesn’t cover every aspect but the common uses have been explained.

PHP Regular Expression Techniques – Part 1: Pattern Modifiers

October 4th, 2011

This article will focus on PHP’s regular expression functions with pattern modifiers. Specifically these functions are of the preg type, and have preg as the prefix. preg_match() is probably the most basic regular expression function of that type and some examples of it will be used in this article.

Regular expressions provide versatile ways of searching text or ‘matching’ it. A string called a pattern is used, similar to a search phrase, and in this case the patterns take a form that is basically the same a the expressions in the Perl language.
Read the rest of this entry »

Tips for OOP Programming with PHP- Part 1: Objects and References

October 3rd, 2011

Programming in PHP utilizing objects is not complex and the syntax and other basics are well covered in various articles and tutorials. It’s also covered in the PHP manual and I will include a brief example for those who need a refresher. Before that I am going to illustrate the basic principals of references without using objects at all. I will then build upon that example to show how use objects and references in your program in useful and efficient ways.
Read the rest of this entry »