A Really Big PHP Tutorial [...part 1]
by , 12-17-2012 at 02:04 AM (14018 Views)
.
Who Is This For?
I'm going to make some assumptions about you, as a programmer:
- You're probably not an expert with PHP, but you know at least "the basics."
If you're a copy+paste PHP coder, that's okay, but hopefully you won't be once we're done.- You have some patience. Yes, you want to see results; but you can trust that they're coming.
- You're "okay" with doing things you've never tried before.
There are some things I would like you to know before we get started.
While I assume that you know your way around a basic PHP script, I want to assure you that if you're a newbie, nothing in here will break you! This tutorial is more about "the plan," and how to write scripts, and less about understanding all those complicated, obscure, hyper-abstracted details that I usually blather on about.
It is a long endeavor - my guess is four to six posts. That "patience" thing I mentioned above will pay off. There are going to be lots of little things that we set up in one part of the tutorial, but don't get around to using until much later.
What Are We Doing?
We're going to build something. We're going to create a user log-in system.
I've mentioned before that, when you write a program, it's a good idea to write it PHP-first. So we're going to do that. A neat side-effect of PHP-first is that it forces you to plan out your application - since you're not just writing code "as you think of it," you need to know what you're going to write in advance.
So let's make some goals for hedgeclipper. First, the obvious:
- Requires the person trying to access the page/program to be logged in.
- Allows the person to log in/out.
- Is secure*
* What "secure" implies is deserving of its own discussion, but let's not interrupt our "flow" right now.
Some not-so-obvious goals:
- Flexible: Can be configured and used in different ways on a page-specific basis.
- Extensible: Code can be changed easily; adding, removing, or switching features is not difficult.
- Portable: Can be used on new or existing pages, on different sites or servers, or with different codebases.
And a "Feature List":
- verify username + password
- track logged-in status (so we don't have to login on every request)
- control access to restricted pages
- control access to restricted content on pages
- allow user to log out
Sounds simple, right?
Notice that, to start, we're not going to worry about some common features, like registration pages, email validation, password recovery, or permissions and groups. That doesn't mean we won't: we're just going to start with the bare minimum. But we're going to make the code flexible enough that we can add these features (and more!) later on, without making a huge mess in the process.
We are going to make control panels (how else could we set up user accounts/passwords?). Those will come later, on a separate page.
Next, describe the situations hedgeclipper might encounter, and what it should do in those situations.
...What if we need to configure options for the program (hint: we do)?
Do it!...What if we need to find out if the user is logged in or not (hint: we do)?
...What if the user already logged in?
Cool. I'll remember that....What if the user is logging in right now?
...What if the login attempt is valid?...What if the user is logging out?
Cool. I'll remember that....What if it's no good?
Reject the login attempt.
Cool. I'll remember that....What if the user is not logged in, and only logged-in users are allowed to continue?
Require user to log in.
Guess What?
We just wrote hedgeclipper's main controller script.
hedgeclipper_controller()Hard part's over. : )PHP Code:/**
* this function allows _hedgeclipper_ to decide what it should do.
*
* @param array|null $options configuration options. we'll talk a little about this next.
*/
function hedgeclipper_controller( $options=null ){
# What if we need to configure options for the program (hint: we do)?
# Do it!
hedgeclipperOptions( $options );
# What if we need to find out if the user is logged in or not (hint: we do)?
# What if the user already logged in?
if( hedgeclipper_checkLoggedIn() ){
# Cool. I'll remember that.
hedgeclipper_rememberLoggedIn();
# What if the user is logging in *right now*?
}elseif( hedgeclipper_isLoggingIn() ){
# What if the login attempt is valid?
if( hedgeclipper_validateLogin() ){
# Cool. I'll remember that.
hedgeclipper_rememberLoggedIn();
# What if it's no good?
}else{
# Reject the login attempt.
hedgeclipper_forgetLoggedIn();
hedgeclipper_loginFailed();
}
}
# What if the user is logging out?
if( hedgeclipper_isLoggingOut() ){
# Cool. I'll remember that.
hedgeclipper_forgetLoggedIn();
}
# What if the user is not logged in, and only logged-in users are allowed to continue?
if( hedgeclipperOptions( 'restrict' ) ){
# Require user to log in.
hedgeclipper_requireLogin();
}
}
Now, we just need to write out what all those functions do. The first thing we'll look at is how we handle setting and checking configuration options.
hedgeclipperOptions()
If you know about how PHP handles scope, you might be confused by the variablePHP Code:/**
* this function keeps track of hedgeclipper's configuration settings.
* it also handles setting custom options, and returns option values when requested.
*
* @param string|array $opt if $opt is a string, we're asking for the value of the matching config setting.
* if $opt is an array, we're setting config options with specific values.
* @return mixed returns the value of $opt if $opt is a config option; FALSE otherwise.
*/
function hedgeclipperOptions( $opt=null ){
# more about `static` in the paragraph below
static $options;
# assign default values to configuration options if none exist
if( empty( $options ) ){
$options = array(
'datatype' => 'mysqli'
,'datasource' => null
,'deny' => ''
,'expiry' => null
,'hooks' => array()
,'restrict' => true
);
}
# if $opt is an array, use it to update $options
if( is_array( $opt ) ){
$options = array_merge( $options,$opt );
return;
}
# if $opt is a string, and a matching setting exists in $options, return its value
if( is_string( $opt ) && isset( $options[$opt] ) ){
return $options[$opt];
}
# if we get to this point, nothing went right.
return false;
}
$optionsin this function. Normally, variables inside of functions are limited to that function: they "disappear" when the function completes, and are "restarted" every time the function is called. That would make defining our $options inside the function basically useless: they'd be *gone* when the function ended.
Thestaticoperator changes that - the variable is still accessible only from the function's scope, but its contents are preserved when the function completes. That's what allows us to use this function to "look up" values - the function remembers what is in $options between calls. Interestingly, this allows us to change options in the middle of our program, or even make up new config settings - but we can explore that later.
You might also wonder about ourdatasource. For this tutorial, we're going to use a MySQL database as our data source - many, many websites already use MySQL for something, so we'll take advantage of that by passing the database handle into our functions, rather than creating a new connection.
We mentionedrestrictearlier, and we'll mentiondenyandhookslater.
Next Time
In part two, we'll talk about how to check if a user is logged in or not, and we'll write the following functions:
- hedgeclipper_checkLoggedIn()
- hedgeclipper_rememberLoggedIn()
We'll also write some HTML, so we have an idea of what our users are looking at on the front-end.
I'll give you a week or so to stew, but in the meantime, Please Ask Questions!
'Till then,
-Adrian





![Submit "A Really Big PHP Tutorial [...part 1]" to del.icio.us](images/misc/bookmarksite_delicious.gif)
![Submit "A Really Big PHP Tutorial [...part 1]" to StumbleUpon](images/misc/bookmarksite_stumbleupon.gif)
![Submit "A Really Big PHP Tutorial [...part 1]" to Google](images/misc/bookmarksite_google.gif)
![Submit "A Really Big PHP Tutorial [...part 1]" to Digg](images/misc/bookmarksite_digg.gif)

