Вы находитесь на странице: 1из 30

tutorials (/tutorials) / Creating A PHP Application

Creating A PHP Application

08 May

Creating A PHP Application (blog-post.html)


By Kevin Waterson 1144607 12 Comments

CONTENTS
1. Abstract

2. The Database
3. User CRUD
4. Create A User
5. Verify User
6. Login
7. Log Out
8. Blog CRUD
9. Create A Category
10. Delete A Category
11. Create A Blog Entry
12. Retrieve Blog Entries
13. Update A Blog Entry
14. Delete A Blog Entry
15. Sod This, Just Give Me The Blog
16. Credits

ABSTRACT
In this introductory tutorial the process of building a complete php application is explored. The application is a simple blog and uses a MySQL database to store
all the data. The blog application contains a user system for the adminstrator to post new blog entries. The nal approval for each blog entry is handle by the
administor. Assumed knowledge is basic use of HTML and CSS to render the display.
This tutorial will suit those looking to begin with PHP and have never written an entire application. No external resources will be used in the building of the
application and all code will be generated here. This tutorial does not make use of Object Oriented code which may be more ecient.
Each section of the tutorial introduces new concepts from the PHP language that are used frequently in many PHP applications and websites. Many functions
are used and explanations given for each as they are introduced.

THE DATABASE
As mentioned above, the blog data will be stored and retrieved from a MySQL database. PHP provides many simple to use MySQL functions for this purpose, but
rst, the database needs to be created. The command line below shows how to create the database from the command line.
mysqladmin create blog -u root -p
Following this the system will prompt the user for the root password and when given the new database, named blog, will be created. From there a username
and password will need to be set for the blog application, after all, using root to interface to the database would be poor form.
mysql blog -u root -p
Once again, a password is required, and when given, the mysql prompt is ready to take commands. Here is the command to create a user for the database
named blog.
GRANT ALL ON blog.* TO blog_master@localhost IDENTIFIED BY 'blog_password';
With the database successfully created, and a username and password in place exit the database and login again using the new username and password.

mysql blog -u blog_master -p


When prompted, type in the password for the blog_master.
The database tables are themselves quite basic. A table of blog categories, and a table of blog_content. The blog_category table need only contain the blog
category id, and the blog category name.
The blog content table has a little extra. This table will contain the blog id, the blog category id, the blog headline, the blog text, and the blog date. The blog id will
be an auto incremented value to avoid duplication and provide a primary key to ensure fast indexed lockup's. The blog category id will be a foreign key which
references the blog category id in the blog category table. To this end, the tables must make use of the InnoDB table type.
The tables will look like this:

CREATETABLEblog_users(
blog_user_idint(11)NOTNULLauto_increment,
blog_user_namevarchar(20)NOTNULL,
blog_user_passwordchar(40)NOTNULL,
blog_user_emailvarchar(254)NOTNULL,
blog_user_access_levelint(1)NOTNULLdefault0,
PRIMARYKEY(blog_user_id),
UNIQUEKEYblog_username(blog_user_name)
)ENGINE=InnoDBDEFAULTCHARSET=latin1;

CREATETABLEblog_categories(
blog_category_idint(11)NOTNULLAUTO_INCREMENT,
blog_category_namevarchar(50)NOTNULL,
PRIMARYKEY(blog_category_id)
)ENGINE=InnoDBDEFAULTCHARSET=latin1;

CREATETABLEblog_content(
blog_content_idint(11)NOTNULLAUTO_INCREMENT,
blog_category_idint(11)NOTNULL,
blog_user_idint(11)NOTNULL,
blog_content_headlinevarchar(50)NOTNULL,
blog_content_texttextNOTNULL,
blog_content_datetimestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,
blog_publishint(1)NOTNULLdefault0,
PRIMARYKEY(blog_content_id),
FOREIGNKEY(blog_user_id)REFERENCESblog_users(blog_user_id)ONDELETECASCADE,
FOREIGNKEY(blog_category_id)REFERENCESblog_categories(blog_category_id)ONDELETECASCADE
)ENGINE=InnoDBDEFAULTCHARSET=latin1;

Note in the blog_content table that the blog_category_id, and the blog_user_id elds are set as a foreign key and that they are set to ON DELETE CASCADE. This
means if a blog category is deleted, all blog content that is related to it will also be deleted from the blog_content table, also, if a blog user is deleted, all blog
entries by that user will be deleted. Be careful.
Copy and paste the database schema above into the command line to create the tables. Be careful if using a third party application such as phpmyadmin to talk
to MySQL as many of these applications have poor support for foreign keys.
With the database set up complete, the rst steps can be made to start blogging.

USER CRUD
Before any blog entries can be added by users, the users must rst be added to the system. An admin user will also be required to oversee, or moderate, the
blog entries. The method of creating, retrieving, updating and deleting database entries is commonly referred to as CRUD
Create
Retrieve
Update
Delete
These a are the basic tasks needed to build the blog most PHP applications. Indeed, they are possibly the most commonly used tasks of all database driven
applications and web sites, and hence, get their own acronym. But before any data can go into the database, a database connection needs to be made. This will
be the rst le and will be included in all les where a database connection is required.
Create a directory called includes in which to keep all the php scripts that are created for the blog. This will keep things tidy and easy for maintenance purposes.
In the includes directory create a le called conn.php which will look like this:

<?php
/***mysqlhostname***/
$hostname='localhost';

/***mysqlusername***/
$username='blog_master';
/***mysqlpassword***/
$password='blog_password';
/***connecttothedatabase***/
$link=@mysql_connect($hostname,$username,$password);
/***selectthedatabase***/
$db=mysql_select_db('blog',$link);
?>

In the beginning of the above script, several variables are set which can then be used with the mysql_connect() function to connect to the datbase. Once the
database connection is established, the database can be selected with the mysql_select_db() function. The resource returned by the mysql_select_db() function is
checked later in the script to see if a valid connection has been made and that the database is available.
If this le were to be accessed on its own, no data would be shown, not even if there was an error. The use of the @ symbol before mysql_connect() is used to
suppress errors. This is rarely required and should be used only where appropriate. It is used in this instance to suppress the error as a check will soon be made
on the validity of the $db link that follows.

CREATE A USER
Now that a database connection can be made, users can be added to the system. Each user will have a user name, and password, and an access level. The
access level will detirmine what les they have access to. Having regular users access the administration les would be disasterous, so care must be taken to
ensure that users recieve only the amount of access they require.
Initially, the users will be confronted with a form which prompts for user name and password. When complete an email will be sent to the specied email
address and the user will have 24 hours in which to verify the sign up or the entry will be deleted.
The process of verifying a user is quite simple. In the email that is sent to the user, the user id is sent in a link along with a randomly generated verication code.
The user must access the link provided, and enter the verication code. Upon success, the user is logged in and can submit blog entries.
To avoid repitition of commonly used HTML components, a simple template can be made of the components and included with the PHP include language
construct. As a language construct, include is not really a function, but is often thought of as a function to avoid confustion. Here, a header.php and footer.php
le will be created with elements common to all HTML les in the system, such as the DOCTYPE, title, body etc.
Create a directory called includes and in the includes directory, create a template called header.php and in it put the following HTML.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>PHPRO.ORG BLOG</title>
</head>
<body>
The footer le contains even less and has only the closing body and html tags. Create a le in the includes directory named footer.php an it put the following
HTML.
</body>
</html>
With these two les in place, the form to add users can be created. As the form is part of a CRUD system, it will server two purposes. To add users and then to
edit users. This means saves duplication and saves coding time. It is a simple HTML form and will accept a user name and password.
The form itself is included in the adduser.php le which will be created next. The form introduces the PHP isset() function and the PHP ternary operator. The
isset() function, as the name suggests, is used to check if a variable is set. The ternary operator is like a PHP if/else. So the following two snippets are the same.

<?php
/***usingif/else***/
if(isset($variable))
{
echo$variable;
}
else
{
echo'';

}
/***usingternary***/
echoisset($variable)?$variable:'';

The use of isset() and the ternary operator can make the form quite compact when checks need to be made if variables are set or not. The user_form.php will
look like this.

<h2><?phpechoisset($heading)?$heading:'';?></h2>
<formaction="<?phpechoisset($form_action)?$form_action:'';?>"method="post">
<dt><labelfor="blog_user_name">Username</label></dt>
<dd>
<inputtype="text"id="blog_user_name"name="blog_user_name"value="<?phpechoisset($blog_user_name)?$blog_username:'';?>"maxlength="20"/>
</dd>
<dt><labelfor="blog_password">Password</label></dt>
<dd>
<inputtype="password"id="blog_user_password"name="blog_user_password"value=""maxlength="20"/>
</dd>
<dt><labelfor="blog_password2">ConfirmPassword</label></dt>
<dd>
<inputtype="password"id="blog_user_password2"name="blog_user_password2"value=""maxlength="20"/>
</dd>
<dt><labelfor="blog_user_email">EmailAddress</label></dt>
<dd>
<inputtype="text"id="blog_user_email"name="blog_user_email"value="<?phpechoisset($blog_user_email)?$blog_user_email:'';?>"maxlength="254"/>
</dd>
<inputtype="hidden"name="form_token"value="<?phpechoisset($form_token)?$form_token:'';?>"/>
<dd>
<inputtype="submit"value="<?phpechoisset($submit_value)?$submit_value:'Submit';?>"/>
</dd>
</dl>

When including the above form, several issues need to be resolved. The form variables need to be set, including the form token. The form token is set to ensure
that the form that is being posted to the script, is in fact from the same server and not some malicious users form. The form token variable is destroyed when
the form is successfully submited to avoid re-posting the form with the browser refresh button.
The form token is stored in a session. PHP sessions are a method of storing variables and making the available from page to page. A variable set on one page,
can be accessed from other pages, quite a neat feature. When using sessions, the rst line of a script must be session_start(). More information on sessions can
be found in the Introduction To PHP Sessions (http://www.phpro.org/tutorials/Introduction-To-PHP-Sessions.html) tutorial.

<?php
/***beginoursession***/
session_start();
/***setaformtoken***/
$form_token=md5(rand(time(),true));
/***setthesessionformtoken***/
$_SESSION['form_token']=$form_token;
/***settheformaction***/
$form_action='adduser_submit.php';
/***settheformsubmitbuttonvalue***/
$submit_value='AddUser';
/***includetheheader.phpfile***/
include'includes/header.php';
/***includetheuserform***/
include'user_form.php';
/***includethefooter.phpfile***/

include'includes/footer.php';
?>

When accessed with the browser the form is displayed with the relevant variables values lled in, such as the form action, the submit button value, and the form
token. The form will post to a PHP script named adduser_submit.php. This script will check the values posted from the form, and if they are valid, put them into
a database and then email the user with a verication code which will be used later to activate the account. Sounds easy right?
The adduser_submit.php script will look like this.

<?php
error_reporting(E_ALL);
/***beginsession***/
session_start();
/***includetheheaderfile***/
include'includes/header.php';
/***anarraytoholderrors***/
$errors=array();
/***checktheformhasbeenpostedandthesessionvariableisset***/
if(!isset($_SESSION['form_token']))
{
$errors[]='InvalidFormToken';
}
/***checkallfieldshavebeenposted***/
elseif(!isset($_POST['form_token'],$_POST['blog_user_name'],$_POST['blog_user_password'],$_POST['blog_user_password2'],$_POST['blog_user_email']))
{
$errors[]='Allfieldsmustbecompleted';
}
/***checktheformtokenisvalid***/
elseif($_SESSION['form_token']!=$_POST['form_token'])
{
$errors[]='Youmayonlypostonce';
}
/***checkthelengthoftheusername***/
elseif(strlen($_POST['blog_user_name'])<2||strlen($_POST['blog_user_name'])>25)
{
$errors[]='InvalidUserName';
}
/***checkthelengthofthepassword***/
elseif(strlen($_POST['blog_user_password'])<=8||strlen($_POST['blog_user_password'])>25)
{
$errors[]='InvalidPassword';
}
/***checkthelengthoftheusersemail***/
elseif(strlen($_POST['blog_user_email'])<4||strlen($_POST['blog_user_email'])>254)
{
$errors[]='InvalidEmail';
}
/***checkforemailvalidemailaddress***/
elseif(!preg_match("/^\S+@[\w\d.]{2,}\.[\w]{2,6}$/iU",$_POST['blog_user_email']))
{
$errors[]='EmailInvalid';
}
else
{
/***escapeallvarsfordatabaseuse***/
$blog_user_name=mysql_real_escape_string($_POST['blog_user_name']);
/***encryptthepassword***/
$blog_user_password=sha1($_POST['blog_user_password']);
$blog_user_password=mysql_real_escape_string($blog_user_password);
/***stripinjectioncharsfromemail***/
$blog_user_email=preg_replace('((?:\n|\r|\t|%0A|%0D|%08|%09)+)i','',$_POST['blog_user_email']);
$blog_user_email=mysql_real_escape_string($blog_user_email);
/***ifwearehere,includethedbconnection***/

include'includes/conn.php';
/***testfordbconnection***/
if($db)
{
/***checkforexistingusernameandemail***/
$sql="SELECT
blog_user_name,
blog_user_email
FROM
blog_users
WHERE
blog_user_name='{$blog_user_name}'
OR
blog_user_email='{$blog_user_email}'";
$result=mysql_query($sql);
$row=mysql_fetch_row($result);
if($row[0]==$blog_user_name)
{
$errors[]='Usernameisalreadyinuse';
}
elseif($row[1]==$blog_user_email)
{
$errors[]='Emailaddressalreadysubscribed';
}
else
{
/***createaverificationcode***/
$verification_code=uniqid();
/***thesqlquery***/
$sql="INSERT
INTO
blog_users(
blog_user_name,
blog_user_password,
blog_user_email,
blog_user_access_level,
blog_user_status)
VALUES(
'{$blog_user_name}',
'{$blog_user_password}',
'{$blog_user_email}',
1,
'{$verification_code}')";
/***runthequery***/
if(mysql_query($sql))
{
/***unsetthesessiontoken***/
unset($_SESSION[\form_token']);
/***emailsubject***/
$subject='Verificationcode';
/***emailfrom***/
$from='test@phpro.org';
/***themessage***/
$path=dirname($_SERVER['REQUEST_URI']);
$message="Clickthelinkbelowtoverifyyoursubscription\n\n";
$message.='http://'.$_SERVER['HTTP_HOST'].$path.'/verify.php?vc='.$verification_code;
/***setsomeheaders***/
$headers='From:webmaster@example.com'."\r\n".
'ReplyTo:webmaster@example.com'."\r\n".
'XMailer:PHPROMAIL';

/***sendtheemail***/
if(!mail($blog_user_email,$subject,$message,$headers))
{
$errors='Unabletosendverification';
}
/***unsettheformtoken***/
unset($_SESSION['form_token']);
}
else
{
$errors[]='UserNotAdded';
}
}
}
else
{
$errors[]='Unabletoprocessform';
}
}
/***checkifthereareanyerrorsintheerrorsarray***/
if(sizeof($errors)>0)
{
foreach($errorsas$err)
{
echo$err,'<br/>';
}
}
else
{
echo'Signupcomplete<br/>';
echo'Averificationemailhasbeensentto'.$blog_user_email;
}
/***includethefooterfile***/
include'includes/footer.php';
?>

The structure of the above script takes the form of an if/elseif/else ladder. This allows the code execution to step through a variety of checks before the
operational part of the script is executed. The checks are many and provide the minimum security checking needed to secure a PHP application.
Stepping down the ladder, the rst uses isset() to check that the form token has been sent, this ensures the form that POSTed the data is not a hackup on a third
party machine. The second check also uses the isset() function, but this time checks four variables in one swoop. This feature of the isset() function makes the
if/elseif/else ladder much shorter and saves time on coding mulitple isset()'s for each POST variable.
A check is then performed on the form token to be sure that the token POSTed matches the token stored in the SESSION. If the tokens do not match and error is
generated. From there variables are checked for length. This is important as a malicious user may try to inject variables with lengths shorter or longer than the
length expected, or the length permitted by the database. This would cause an error that may give away internal information about your system.
A check is made on the validity of the email as well as on the length. There is no regular expression known to man that will successfully match all valid emails per
the RFC. This one will catch all sane email address.
If success, the script then prepares for use with the datbase. It is imperative that any variables that are to be used in an SQL statement are proplerly escaped to
prevent SQL injection (http://www.phpro.org/tutorials/Introduction-to-PHP-and-MySQL.html#16). It is at this time, the users email address is sanitized also, not
only for SQL injection, but for email header injection also. All variables that are to be used in emails should be proplerly sanitized to prevent header injection,
which is a leading cause of SPAM. A further check is made to ensure the username, or the email address is not already is not already in use. If it is already in use,
an error is generated. If all is well, the new user data is added to the database and and email is sent to the user with a verication code.

VERIFY USER
When a new user is created as above, an email is sent to the users email address with a verication code. The URL in the link contains a section like this:
verify.php?vc=48ba88c9efeef
This means the le verify.php will have access to the verication code via PHP super global named $_GET['vc'].

<?php
/***checkifverificationcodeispresent***/
if(!isset($_GET['vc']))
{
$error='InvalidVerificationCode';
}
/***checkverificationcodeisastringof13chars***/
elseif(strlen($_GET['vc'])!=13)
{
$error='VerificationCodeInvalid';
}
else
{
/***escapethecode***/
$blog_verification_code=mysql_real_escape_string($_GET['vc']);
/***includethedatabaseconnection***/
include'includes/conn.php';
/***checkforavalidconnection***/
if($db)
{
/***theupdateSQL***/
$sql="UPDATE
blog_users
SET
blog_user_status=1
WHERE
blog_user_status='{$blog_verification_code}'";
/***runthequery***/
$result=mysql_query($sql);
/***checkforaffectedrows***/
if(mysql_affected_rows($link)!=1)
{
$message='Unabletoverify';
}
else
{
$message='VerificationComplete,pleaselogintosubmitblog';
}
}
}
?>
<h1>Verification</h1>
<p><?phpecho$message;?></p>

The verify.php le itself is quite simple in comparison to the previous le. Once again the isset() function is used, this time to check that the verication code is
present in $_GET['vc']. Then the length of the string is check and if all is well, the verication code is prepared for use in the database using
mysql_real_escape_string().
The SQL query is run and updates the user status of the user with the matching verication code. By using the mysql_aected_rows() function it is possible to
check if the SQL query was successful.

LOGIN
Now that a user can be created and register with the system, it is possible for the user to log into the system. But rst, a method of navigation is required. The
navigation menu will be common to all pages, so can be part of the header. This means only a single copy is every needed and saves code duplication.
The new includes/header.php le will look like this.

<?php
/***ifauserisloggedin***/
if(isset($_SESSION['access_level']))
{

$log_link='logout.php';
$log_link_name='LogOut';
}
else
{
$log_link='login.php';
$log_link_name='LogIn';
}
?>
<!DOCTYPEhtmlPUBLIC"//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
<title>PHPRO.ORGBLOG</title>
<styletype="text/css">
.menuul{
color:green;
liststyle:none;
}
.menuulli{
padding:
display:inline;
float:left;
padding:2px8px;
}
hr{
clear:both;
}
</style>
</head>
<body>
<divclass="menu">
<ul>
<li><ahref="index.php">Home</a></li>
<li><ahref="<?phpecho$log_link;?>"><?phpecho$log_link_name;?></a></li>
</ul>
<hr/>

The rst change that is noticable in the header.php le is that the rst block of code at the top contains a check if the SESSION variable named access_level is
set. If a user is logged in, the value of the link is set to logout. If the user is not logged in, the values are set to provide a link to log in. The menu is very basic and
provides a small CSS unordered link list.
The login form is basic also, and will POST to a login_submit.php le, which will do some checking and attempt to log th e user into the sytem.
The login form will look like this.

<?php
/***startthesession***/
session_start();
/***includetheheaderfile***/
include'includes/header.php';
/***setaformtoken***/
$_SESSION['form_token']=md5(rand(time(),true));
?>
<h1>BlogLogin</h1>
<p>
Pleasesupplyyourusernameandpassword.
</p>
<formaction="login_submit.php"method="post">
<inputtype="hidden"name="form_token"value="<?phpecho$form_token;?>"/>
<dl>
<dt>Username</dt>
<dd><inputtype="text"name="blog_user_name"/></dd>

<dt>Password</dt>
<dd><inputtype="password"name="blog_user_password"/></dd>
<dd><inputtype="submit"value="Login"/></dd>
</dl>
</form>
<?phpinclude'includes/footer.php';?>

No surprises in the login form. It contains the obligatory session_start() function that must be used any time an interaction with session variables is required.
The form token is set and the header le is included. The form is simple and contains the form token and inputs for username and password, followed by the
inclusion of the footer.php le.
When the form is submitted, something dierent happens. The form token is checked, the username and passwords are validated and sanitized, but instead of
displaying a message, the script will redirect the user to the index.php page, which will be created now.
The index.php le will look like this.

<?phpinclude'includes/header.php';?>
<h1>PHPRO.ORGBlog</h1>
<p>
WelcometothePHPRO.ORGBlog...
</p>
<?phpinclude'includes/footer.php';?>

The index le will grow quite substantially further on as blog entries need to be retrieved, but for now, this is all that is required.
The login_submit.php le will look like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***beginsession***/
session_start();
/***checktheformhasbeenpostedandthesessionvariableisset***/
if(!isset($_SESSION['form_token']))
{
$location='login.php';
}
/***checkallfieldshavebeenposted***/
elseif(!isset($_POST['form_token'],$_POST['blog_user_name'],$_POST['blog_user_password']))
{
$location='login.php';
}
/***checktheformtokenisvalid***/
elseif($_SESSION['form_token']!=$_POST['form_token'])
{
$location='login.php';
}
/***checkthelengthoftheusername***/
elseif(strlen($_POST['blog_user_name'])<2||strlen($_POST['blog_user_name'])>25)
{
$location='login.php';
}
/***checkthelengthofthepassword***/
elseif(strlen($_POST['blog_user_password'])<8||strlen($_POST['blog_user_password'])>25)
{
$location='login.php';
}
else
{
/***escapeallvarsfordatabaseuse***/
$blog_user_name=mysql_real_escape_string($_POST['blog_user_name']);

/***encryptthepassword***/
$blog_user_password=sha1($_POST['blog_user_password']);
$blog_user_password=mysql_real_escape_string($blog_user_password);
/***ifwearehere,includethedbconnection***/
include'includes/conn.php';
/***testfordbconnection***/
if($db)
{
/***checkforexistingusernameandpassword***/
$sql="SELECT
blog_user_name,
blog_user_password,
blog_user_access_level
FROM
blog_users
WHERE
blog_user_name='{$blog_user_name}'
AND
blog_user_password='{$blog_user_password}'
AND
blog_user_status=1";
$result=mysql_query($sql);
if(mysql_num_rows($result)!=1)
{
$location='login.php';
}
else
{
/***fetchresultrow***/
$row=mysql_fetch_row($result);
/***settheaccesslevel***/
$_SESSION['access_level']=$row[2];
/***unsettheformtoken***/
unset($_SESSION['form_token']);
/***sendusertoindexpage***/
$location='index.php';
}
}
}
/***redirect***/
header("Location:$location");
/***flushthebuffer***/
ob_end_flush();
?>

This time, when the form is submitted, the user is redirected the index.php page if the login is successful. If the login fails, the user is redirected back to the login
page to try again. The rst line of code begins the output buering which allows PHP to no send any headers to the browser, which would cause an error as
headers are sent when using session_start and again when using the header() function.
The structure maintains the if/elseif/else ladder and traverses through some of the checks used earlier to validate and sanitize the user inputs. At the end of the
script, the header() function redirects and nally, the ob_end_ush() function sends the whole thing to the browser.
Note that the Login link in the menu changes to Log Out when a user logs in.

LOG OUT
Now that a user can log in to the system, a method is required to log out. As the link for the log out is already in the menu, it is simply a matter of creating the
logout.php le. This le only needs to check that the access_level SESSION variable is set, and if it is, unset() it, and then redirect the user back to the index.php
page.

The logout.php le will look like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***beginsession***/
session_start();
/***checktheformhasbeenpostedandthesessionvariableisset***/
if(isset($_SESSION['access_level']))
{
unset($_SESSION['access_level']);
}
/***redirect***/
header("Location:index.php");
/***flushthebuffer***/
ob_end_flush();
?>

BLOG CRUD
The blog CRUD, as the name suggest comprises four components.
Create
Retrieve
Update
Delete
To Create or add a blog entry, there must rst be some categories to add them to.

CREATE A CATEGORY
Before data can be retrieved from the database, it must rst be put in. The most common way of user input into a database with PHP is with a HTML form.
Because a form is a client side interface, the door is left open to abuse as the content the end user puts into the form, may not be the type of content expected
or, if a malicious users wants to get nasty, may to to compromise the system. It is the job of the PHP developer to close these security doors and the basic lesson
is this:

NEVER TRUST USER INPUT


NEVER TRUST USER INPUT
NEVER TRUST USER INPUT
As this blog is a multi-user system, precautions must be taken to avoid mistakes and mis-use. The form itself is quite simple and is simply HTML.
Creating categories is a function of the administrator, and so the script to add a category must only be availble to the admin user. The user access level for the
adminstrator is 5. This can be checked as the access level is stored in a session, so when the admin lands on the add_category.php page, access can be checked,
and if the access level is not correct, the user will be redirected to the index.php page.
Create a le named add_category.php in the main directory, as we are going to add a category to the blog. The add_category.php le in will look like this:

<?php
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/

include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'])||$_SESSION['access_level']!=5)
{
header("Location:index.php");
exit;
}
else
{
/***setatoken***/
$form_token=uniqid();
$_SESSION['form_token']=$form_token;
}
?>
<h3>AddCategory</h3>
<p>
Categorynamesmustcontainonlyalphanumericcharactersandunderscore,spaceorcomma.
</p>
<formaction="add_category_submit.php"method="post">
<inputtype="hidden"name="form_token"value="<?phpecho$form_token;?>"/>
<inputtype="text"name="blog_category_name"/>
<inputtype="submit"value="AddCategory"/>
</form>
<?php
include'includes/footer.php';
ob_end_flush();
?>

This le makes use of output buering to manage the headers. Headers are send from the included header.php le with session_start() and this would produce
a warning. The script checks that the user who is accessing the page is an administrator by checking rst that the access_level variable is set and that its value is
5. If this is not true, the user is forward o to the index page gracefully. I the access is from the administrator, then the form is shown in the page.
The le is a simple HTML form that contains the required input text eld to add a category. Note that the name of the input matches the name in the database.
This is not strictly required but gives clarity when dealing with variables.
The form action is the add_category_submit.php le. This is the le that will process the form data, and if all is well, will add the category to the database. To
achieve this several things need to happen.
The form eld must contain a valid name
The connection must be made to the database
The category must be added
A response is required
As the category name must be a string containing less than 50 characters, because the database eld is dened as VARCHAR(50), it is simple to validate that this
is what has been supplied by the form. The database connection is made by simply includeing the conn.php le. When a le is included with PHP, it is the same
as if the code were written where the include occurs. Following this, the category is added to the database and a thank you message created. The
add_category_submit.php le will look like this.

<?php
error_reporting(E_ALL);
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'])||$_SESSION['access_level']!=5)
{
header("Location:index.php");
exit;
}
else
{

/***checktheformhasbeenpostedandthesessionvariableisset***/

if(isset($_SESSION['form_token'],$_POST['form_token'],$_POST['blog_category_name'])&&preg_match('/^[az][az\d_,]{2,49}$/i',$_POST['blog_category_na
{
/***ifwearehere,includethedbconnection***/
include'includes/conn.php';
/***testfordbconnection***/
if($db)
{
/***excapethestring***/
$blog_category_name=mysql_real_escape_string($_POST['blog_category_name']);
/***thesqlquery***/
$sql="INSERTINTOblog_categories(blog_category_name)VALUES('{$blog_category_name}')";
/***runthequery***/
if(mysql_query($sql))
{
/***unsetthesessiontoken***/
unset($_SESSION['form_token']);
echo'CategoryAdded';
}
else
{
echo'CategoryNotAdded';
}
}
else
{
echo'Unabletoprocessform';
}
}
else
{
echo'InvalidSubmission';
}
}
/***flushthebuffer***/
ob_end_flush();
?>

It is quite clear from the above code, that ninety percent of the code is dedicated to error checking. This is perhaps the most important part of dealing with input
from users. Note that once again, the blog_category_name variable matches the name in the database, and that the naming convention is maintained
throughout the script.
The use of the preg_match() function contains several validation tasks rolled into a single function. Regular expressions are an excellent tool for validating user
input to ensure what is posted from a form, is what expected when processing the data. This regular expression allows the use of alpha numeric characters and
underscore, space and comma. This permits a good variety of characters to use for any sane category name.
The form and form submit now work as expected and categories can be added easily, A form token has been used to ensure teh validity of the form and to
prevent page refresh. The form token can be stored in a session with the add_category.php form, and then checked in the add_category_submit.php script, and
if the POST is successful, the token is deleted, thus preventing further POSTings of the form.

DELETE A CATEGORY
The process of deleting a category is very similar to that of adding a category, with a few small changes the code is mostly the same. The form maintains the
session token and the only dierence is that the category names and id's are extracted from the database to be used in the form with a drop-down select.
The process of gathering the information for the form is kept at the top of the script. This means all the application logic is separated from the display logic. This
will be important as scripts, and indeed, applications, become larger. The form script itself looks like this.

<?php
error_reporting(E_ALL);
/***beginoutputbuffering***/

ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'])||$_SESSION['access_level']!=5)
{
header("Location:index.php");
exit;
}
else
{
/***setatoken***/
$form_token=uniqid();
$_SESSION['form_token']=$form_token;
/***includethedatabaseconnection***/
include'includes/conn.php';
/***checkforavaliddbconnection***/
if($db)
{
/***sqltogetalltheblogcategories***/
$sql="SELECT
blog_category_id,
blog_category_name
FROM
blog_categories";
$result=mysql_query($sql);
if(!is_resource($result))
{
echo'Unabletogetcategorylisting';
}
else
{
/***createanemptyarray***/
$categories=array();
/***loopovertheresultsandaddthemtothearray***/
while($row=mysql_fetch_array($result))
{
$categories[$row['blog_category_id']]=$row['blog_category_name'];
}
}
}
else
{
echo'Databaseconnectionfailed';
}
}

?>
<h3>DeleteCategory</h3>
<p>
<?php
if(sizeof($categories==0))
{
echo'NoCategoriesAvailable';
}
else
{
echo'Selectacategorynamefordeletion';
}
?>
</p>

<formaction="del_category_submit.php"method="post">
<selectname="blog_category_id">
<?php
foreach($categoriesas$id=>$cat)
{
echo"<optionvalue=\"$id\">$cat</option>\n";
}
?>
</select>
<inputtype="submit"value="DeleteCategory"onclick="returnconfirm('Areyousure?')"/>
</form>
<?phpinclude'includes/footer.php';?>

Note the delete button has a small javascript onclick added which pops up a conrm window asking the users to conrm the delete when the button is pressed.
Moving to the includes/del_category_submit.php le, once again there is many similarities with the add_category_submit.php le. The same process is involved
with small changes to the error checking to validate that the blog_category_id is indeed a number. The inclusion of the database connection class and
connection resource is same and only the SQL query changes. A small addition when the deletion is completed is the mysql_aected_rows() line which returns
the number of aected rows from the previous mysql operation. This can be used to display the number of rows deleted which should be one.
The del_category_submit.php le looks like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'])||$_SESSION['access_level']!=5)
{
header("Location:index.php");
exit;
}
else
{
/***checktheformhasbeenpostedandthesessionvariableisset***/
if(isset($_SESSION['form_token'],$_POST['blog_category_id'])&&is_numeric($_POST['blog_category_id']))
{
/***ifwearehere,includethedbconnection***/
include'includes/conn.php';
/***testfordbconnection***/
if($db)
{
/***excapethestring***/
$blog_category_id=mysql_real_escape_string($_POST['blog_category_id']);
/***thesqlquery***/
$sql="DELETEFROMblog_categoriesWHEREblog_category_id=$blog_category_id";
/***runthequery***/
if(mysql_query($sql))
{
/***unsetthesessiontoken***/
unset($_SESSION['form_token']);
/***affectedrows***/
$affected=mysql_affected_rows($link);
echo"$affectedCategoryDeleted";
}
else
{

echo'CategoryNotDeleted';
}
}
else
{
echo'Unabletoprocessform';
}
}
else
{
echo'InvalidSubmission';
}
}
?>

Once again the code shows mostly error checking, this is the life of the PHP programmer. The task is not one of how make things right, but of how to stop things
going wrong. There are many aspects of simple scripts which need to be dealt with that are often overlooked. By attending to the smaller details, PHP scripts
and applications are robust and easy to maintain.
Add several categories such as Computers, Programming and Cars. These will be the categories used as the tutorial progresses.

CREATE A BLOG ENTRY


With the categories now available, the real work of CRUD can begin. Of course, the beginning is the creation of a blog entry. Once again a form will be used to
enter the data but this form will not be as simple as the previous. A little forward thinking is needed as a blog entry may need to be edited to correct some
aspect of the entry. The form elds will be identical, and it would be poor practice to duplicate the form and use separate forms for both add and editing a blog
entry.
Like any other piece of reusable code, the form can be included in a php script. The main dierence with a reusable piece of HTML code is that any PHP
variables within the code must be available to it. Also, the form action will be directed to two dierent scripts, so this too must be a variable set in the parent
script, that is, the script that includes the form.
The includes/blog_form.php le, which contains the form, will look like this

<h3><?phpecho$blog_heading;?></h3>
<formaction="<?phpecho$blog_form_action;?>"method="post">
<inputtype="hidden"name="blog_content_id"value="<?phpechoisset($blog_content_id)?$blog_content_id:'';?>"/>
<dl>
<dt>Headline</dt>
<dd><inputtype="text"name="blog_content_headline"value="<?phpechoisset($blog_content_headline)?$blog_content_headline:'';?>"/></dd>
<dt>Category</dt>
<dd>
<selectname="blog_category_id">
<?php
foreach($categoriesas$id=>$cat)
{
echo"<optionvalue=\"$id\"";
/***markasselected***/
echo(isset($selected)&&$id==$selected)?'selected':'';
echo">$cat</option>\n";
}
?>
</select>
<dd>
<dt>Blog</dt>
<dd>
<textareaname="blog_content_text"rows="5"cols="45"><?phpechoisset($blog_content_text)?$blog_content_text:'';?></textarea>
</dd>
<dd><inputtype="submit"value="<?phpecho$blog_form_submit_value;?>"/></dd>
</dl>
</form>

The form is much the same as the add_category form from used earlier, with the exception that this form has more elds. The category drop-down menu is
identical to that of the add category form and a text input eld is supplied for the heading along with a textarea for the blog_content_text. Once again the eld
names are identical to those in the database table that the form is designed for.
The form also contains several pieces of PHP code in the inputs to echo the value of form eld if they are set. The form action is set with a variable along with
the value of the submit button. These variables make the form re-usable later when updating blog data.
The add_blog.php le that will include the form performs several functions. Like the add category form a session is started at the top of the script and then the
session token is set. The header.php le is included as is the conn.php le to connect to the database. Once again, a check is made that a valid connection has
been made to the database, and if this is ok, a further check is made to be sure a category is available. If all is well, the categories are put into an array named
$categories with the category_id as the index. I is this array that is passed to the form to produce the category drop-down menu.
Following from there, the variables that are in the form are set. If one of them is omitted, an error will be produced, so it is important to make sure all variables
have a value, even if the value is an empty string.
The add_blog.php le will look like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'])||$_SESSION['access_level']<1)
{
/***ifnotloggedin,forwardtologinpage***/
header("Location:login.php");
exit;
}
else
{
/***setthetokentopreventmultipleposts***/
$form_token=uniqid();
$_SESSION['form_token']=$form_token;
/***getthecategoriesfromthedatabase***/
include'includes/conn.php';
/***checkfordatabaseconnection***/
if($db)
{
$sql="SELECT
blog_category_id,
blog_category_name
FROM
blog_categories";
$result=mysql_query($sql);
if(!is_resource($result))
{
echo'Unabletofindanycategories';
}
else
{
/***checkforaresult***/
if(mysql_num_rows($result)!=0)
{
/***putthecategoriesinanarray***/
$categories=array();
while($row=mysql_fetch_array($result))
{
$categories[$row['blog_category_id']]=$row['blog_category_name'];
}

/***settheformvalues***/
$blog_form_action='add_blog_submit.php';
$blog_heading="AddABlogEntry";
$blog_content_headline='';
$blog_content_text='';
$blog_form_submit_value='AddBlog';
/***includetheblogform***/
include'includes/blog_form.php';
}
else
{
echo'Nocategoriesfound';
}
}
}
else
{
/***ifweareherethedatabaseconnectionhasfailed***/
echo'Unabletocompleterequest';
}
/***includethefooter***/
include'includes/footer.php';
}
?>

The nal part of adding a blog entry is to create the add_blog_submit.php le. Like the add_category_submit.php le, the task of INSERTing the data into the
database is quite simple. The same process is repeated with a new SQL query for the blog table. The session token is destroyed in the same way to prevent
multiple posting by hitting the refresh button.
The add_blog_submit.php le will look like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'])||$_SESSION['access_level']<1)
{
/***ifnotloggedin,forwardtologinpage***/
header("Location:login.php");
exit;
}
else
{
/***checktheformhasbeenpostedandthesessionvariableisset***/
if(isset($_SESSION['form_token'],$_POST['blog_category_id'],$_POST['blog_content_headline'],$_POST['blog_content_text']))
{
/***firstcheckallPOSTvariablesfortypeandlength***/
if(!is_numeric($_POST['blog_category_id'])||$_POST['blog_category_id']==0)
{
echo'BlogCategoryNameisInvalid';
}
elseif(!is_string($_POST['blog_content_headline'])||strlen($_POST['blog_content_headline'])<3||strlen($_POST['blog_content_headline'])>50)
{
echo'BlogHeadlineisinvalid';
}
elseif(!is_string($_POST['blog_content_text'])||strlen($_POST['blog_content_text'])<3||strlen($_POST['blog_content_text'])>4096)
{
echo'BlogTextisInvalid';
}
else
{

/***ifwearehere,includethedbconnection***/
include'includes/conn.php';
/***testfordbconnection***/
if($db)
{
/***escapethestrings***/
$blog_user_id=$_SESSION['blog_user_id'];
$blog_category_id=mysql_real_escape_string($_POST['blog_category_id']);
$blog_content_headline=mysql_real_escape_string($_POST['blog_content_headline']);
$blog_content_text=mysql_real_escape_string($_POST['blog_content_text']);
/***thesqlquery***/
$sql="INSERT
INTO
blog_content(
blog_user_id,
blog_category_id,
blog_content_headline,
blog_content_text)
VALUES(
'{$blog_user_id}',
'{$blog_category_id}',
'{$blog_content_headline}',
'{$blog_content_text}')";
/***runthequery***/
if(mysql_query($sql))
{
/***unsetthesessiontoken***/
unset($_SESSION['form_token']);
echo'BlogEntryAdded';
}
else
{
echo'BlogEntryNotAdded'.mysql_error();
}
}
else
{
echo'Unabletoprocessform';
}
}
}
else
{
echo'InvalidSubmission';
}
}
?>

RETRIEVE BLOG ENTRIES


Now that blog entries can be created, they need to be retrieved in order to be displayed. This is achieved with the use of a single SELECT statement. The page to
view the last 5 blog entries will be the main index.php page.
This le is far less complex than the previous examples as it requires only a single query to extract the data and then display it. The conn.php le is included and
a check is made for a valid database connection. Further checks are then made to ensure a valid database resource is available and if all is well, the blog data is
SELECTed from the database.
The data is put into an array of blog data for use further down the script in the display where a simple foreach loop echoes each record in a little box that can
later be styled with CSS.
The index.php le will look like this.

<?php

/***includetheheader***/
include'includes/header.php';
/***includethedatabaseconnection***/
include'includes/conn.php';
/***checkforvaliddatabaseconnection***/
if($db)
{
/***theSQLquerytoselectlast5blogs***/
$sql="SELECT
blog_content_headline,
blog_content_text,
DATE_FORMAT(blog_content_date,'%b%d%Y')ASblog_content_date,
blog_category_name,
blog_user_name
FROM
blog_content
JOIN
blog_users
USING(blog_user_id)
JOIN
blog_categories
USING(blog_category_id)
ORDERBYblog_content_idDESC
LIMIT5";
/***runthequery***/
$result=mysql_query($sql)ordie(mysql_error());
/***createtheblogarray***/
$blog_array=array();
/***checkforavalidresource***/
if(is_resource($result))
{
/***checkthereareresults***/
if(mysql_num_rows($result)!=0)
{
/***stufftheblogentriesintotheblogarray***/
while($row=mysql_fetch_array($result,MYSQL_ASSOC))
{
$blog_array[]=$row;
}
}
}
else
{
echo'BlogUnavailable';
}
}
else
{
echo'NoBlogEntriesAvailable';
}
?>
<h1>PHPRO.ORGBlog</h1>
<p>
WelcometothePHPRO.ORGBlog...
</p>

<?php
if(sizeof($blog_array)>0)
{

/***loopovertheblogarrayanddisplayblogs***/
foreach($blog_arrayas$blog)
{
echo'<divclass="blog_entry">';
echo'<p><spanclass="category">'.$blog['blog_category_name'].':</span>
<spanclass="blog_date">Addedby'.$blog['blog_user_name'].'on'.$blog['blog_content_date'].'</p>';
echo'<h2>'.$blog['blog_content_headline'].'</h2>';
echo'<p>'.$blog['blog_content_text'].'</p>';
echo'</div>';
}
}
else
{
echo'NoBlogsHere';
}
/***includethefooterfile***/
include'includes/footer.php';
?>

UPDATE A BLOG ENTRY


Once a blog entry has been added, it will become the rst item displayed on the index page. It is about this time that a spelling error is noticed, so a method to
update or edit the entry is required. The form to do this has already been created, and is the same for that was used to add a blog entry, that is, the
blog_form.php le in the includes directory.
Like the add_blog.php le, the edit_blog.php will set a number of variables for the blog form, and pre-populate the input elds with the data from the database.
This will allow the content to be edited directly. Before this can happen, a method of choosing the blog entry to edit or update is required.
By creating a page with a table to select and list all the blog entries, a simple hypertext link can be used to forward to the edit blog page. The ID of the blog entry
is sent along with the URL and is retrieved using GET.
Each blog entry should only be able to be editted by the user who posted it, or the admin user, so it is important to check both the user id of the user, and the
access level. Remember, and access level of 5 is the administrator.
The list_blogs.php le will look like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level']))
{
header("Location:login.php");
exit;
}
else
{
/***includethedatabaseconnection***/
include'includes/conn.php';
/***checkforvaliddatabaseconnection***/
if($db)
{
/***theSQLquerytoselectlast5blogs***/
$sql="SELECT
blog_content_id,
blog_content_headline
FROM
blog_content
";
/***ifuserisnotadmin***/

if($_SESSION['access_level']==1)
{
$blog_user_id=mysql_real_escape_string($_SESSION['blog_user_id']);
$sql.="WHEREblog_user_id=$blog_user_id";
}
/***runthequery***/
$result=mysql_query($sql)ordie(mysql_error());
/***checkforavalidresource***/
if(is_resource($result))
{
/***checkthereareresults***/
if(mysql_num_rows($result)!=0)
{
/***stufftheblogentriesintoablogarray***/
$blog_array=array();
while($row=mysql_fetch_array($result,MYSQL_ASSOC))
{
$blog_array[]=$row;
}
}
else
{
echo'NoBlogEntriesFound';
}
}
else
{
echo'BlogUnavailable';
}
}
else
{
echo'NoBlogEntriesAvailable';
}
}
?>
<h3>MyBlog</h3>
<h4>Clickaheadlinetoeditblogentry</h4>
<table>
<thead><tr><td>ID</td><td>Headline</td><td>Edit</td><td>Delete</td></tr></thead>
<tfoot></tfoot>
<tbody>
<?php
/***loopovertheblogarrayanddisplayblogs***/
foreach($blog_arrayas$blog)
{
echo'<tr>
<td>'.$blog['blog_content_id'].'</td>
<td>'.$blog['blog_content_headline'].'</td>
<td><ahref="edit_blog.php?bid='.$blog['blog_content_id'].'">Edit</a></td>
<td><ahref="delete_blog.php?bid='.$blog['blog_content_id'].'"onclick="returnconfirm(\'Areyousure?\')">Delete</a></td>
</tr>';
}
?>
</tbody>
</table>
<?php
/***includethefooter***/
include'includes/footer.php';
?>

By now, the format of the list_blog.php le should be quite apparent. The header le is included along with the database connection le, conn.php. A simple SQL
SELECT pulls the blog id and headline from the and an array is created which is used in the creation of a HTML table to display each headline. The hypertext link
contains the blog_content_id which will be used by the edit_blog.php le to SELECT the data for that ID.

Note that if the user access level is equal to 1, the WHERE clause is added to the SQL query to ensure only the results for that users are displayed.
Like all data supplied from userland, the blog id, called "bid" for short, must be checked and escaped with the mysql_real_escape_string() function to protect
against SQL injection. An abbreviated version of the variable named in this case as it will be used in the URL and URL's should be kept as short as possible.
The edit_blog.php le will look like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'],$_SESSION['blog_user_id']))
{
header("Location:login.php");
exit;
}
else
{
/***setthetokentopreventmultipleposts***/
$form_token=uniqid();
$_SESSION['form_token']=$form_token;
/***checktheblogcategoryidissetandisanumber***/
if(isset($_GET['bid'])&&is_numeric($_GET['bid']))
{
/***getthecategoriesfromthedatabase***/
include'includes/conn.php';
/***checkfordatabaseconnection***/
if($db)
{
/***getthecategoriesforthedropdownmenu***/
$categories=array();
$sql="SELECTblog_category_id,blog_category_nameFROMblog_categories";
$result=mysql_query($sql);
while($row=mysql_fetch_array($result))
{
$categories[$row['blog_category_id']]=$row['blog_category_name'];
}
/***escapetheblogcategoryidandassigntoavariable***/
$blog_content_id=mysql_real_escape_string($_GET['bid']);
$sql="SELECT
blog_content_id,
blog_content_headline,
blog_content_text,
blog_category_id,
blog_category_name
FROM
blog_content
JOIN
blog_categories
USING(blog_category_id)
WHERE
blog_content_id=$blog_content_id";
/***checkifuserisadmin***/
if($_SESSION['access_level']==1)
{
/***allowonlyblogsforthisuser***/
$blog_user_id=mysql_real_escape_string($_SESSION['blog_user_id']);
$sql.="ANDblog_user_id=$blog_user_id";
}

/***runthequery***/
$result=mysql_query($sql)ordie(mysql_error());
/***checkforavalidresource***/
if(!is_resource($result))
{
echo'Unabletofetchblogrecord';
}
else
{
/***checkthereisablogentry***/
if(mysql_num_rows($result)!=0)
{
while($row=mysql_fetch_array($result))
{
$heading='EditBlog';
$blog_form_action='edit_blog_submit.php';
$selected=$row['blog_category_id'];
$blog_content_id=$row['blog_content_id'];
$blog_content_headline=$row['blog_content_headline'];
$blog_content_text=$row['blog_content_text'];
$blog_form_submit_value='EditBlog';
}
/***includetheblogform***/
include'includes/blog_form.php';
}
else
{
echo'Noblogfound';
}
}
}
}
else
{
/***ifweareherethedatabaseconnectionhasfailed***/
echo'Unabletocompleterequest';
}

/***includethefooter***/
include'includes/footer.php';
}
?>

With the edit_blog.php le in place, and all the variables set, it is now simply a matter of creating the le to submit to that will perform the updates made in the
form. Note that the correct category for the blog entry is selected in the drop down menu and and can be changed.
Create a le in the includes directory called edit_blog_submit.php. This le will, as with previous scripts, collect all the information coming in, validate it to be
sure it is what is expected, escape it to prevent SQL injection, and nally UPDATE the database record, saving the changes. If the process of continually checking
and re-checking data seems laborious, think of the task of having the site and/or database compromised and having to rebuild it.
The edit_blog_submit.php le will look like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'],$_SESSION['blog_user_id']))
{
header("Location:login.php");
exit;
}

else
{
/***checktheformhasbeenpostedandthesessionvariableisset***/
if(isset($_SESSION['form_token'],$_POST['blog_category_id'],$_POST['blog_content_id'],$_POST['blog_content_headline'],$_POST['blog_content_text'
{
/***firstcheckallPOSTvariablesfortypeandlength***/
if(!is_numeric($_POST['blog_category_id'])||$_POST['blog_category_id']==0)
{
echo'BlogCategoryNameisInvalid';
}
if(!is_numeric($_POST['blog_content_id'])||$_POST['blog_content_id']==0)
{
echo'InvalidID';
}
elseif(!is_string($_POST['blog_content_headline'])||strlen($_POST['blog_content_headline'])<3||strlen($_POST['blog_content_headline'])>50)
{
echo'BlogHeadlineisinvalid';
}
elseif(!is_string($_POST['blog_content_text'])||strlen($_POST['blog_content_text'])<3||strlen($_POST['blog_content_text'])>4096)
{
echo'BlogTextisInvalid';
}
else
{
/***ifwearehere,includethedbconnection***/
include'includes/conn.php';
/***testfordbconnection***/
if($db)
{
/***escapethestrings***/
$blog_content_id=mysql_real_escape_string($_POST['blog_content_id']);
$blog_category_id=mysql_real_escape_string($_POST['blog_category_id']);
$blog_content_headline=mysql_real_escape_string($_POST['blog_content_headline']);
$blog_content_text=mysql_real_escape_string($_POST['blog_content_text']);

/***thesqlquery***/
$sql="UPDATE
blog_content
SET
blog_category_id={$blog_category_id},
blog_content_headline='{$blog_content_headline}',
blog_content_text='{$blog_content_text}'
WHERE
blog_content_id=$blog_content_id";
/***runthequery***/
if(mysql_query($sql))
{
/***unsetthesessiontoken***/
unset($_SESSION['form_token']);
echo'BlogUpdatedSuccessfully';
}
else
{
echo'UnableToUpdateBlog';
}
}
else
{
echo'Unabletoprocessform';
}
}
}
else
{
echo'InvalidSubmission';

}
}
?>

DELETE A BLOG ENTRY


The nal part of the CRUD is the Delete. This process is much the same as seen previously in this tutorial when deleting a category. Like the edit blog process, a
method is needed to list all the blog entries so a selection can be made. Creating a new list identical to the one just created would be further, and unnecessary
duplication. With a small change to the list_blogs.php le, a delete option can be provided next to the edit option.
The delete link in the list_blogs.php le is already in place, saving the extra time of creating a second list.
Note also in the Delete link a small javascript onclick conrm has been provided so when the delete link is clicked, the user will be prompted with a conrmation
box with a message. If javascript is disabled, the script will simply delete the relevant blog entry without warning.
The del_blog_submit.php le is very much like the delete category page and performs the same function, it checks that a valid number has been submitted to
the page, and if all is will, the link is deleted, and a message appears to say the task is done.
The delete_blog.php le will look like this.

<?php
/***beginoutputbuffering***/
ob_start();
/***includetheheaderfile***/
include'includes/header.php';
/***checkaccesslevel***/
if(!isset($_SESSION['access_level'],$_SESSION['blog_user_id']))
{
header("Location:login.php");
exit;
}
else
{
/***checktheformhasbeenpostedandthesessionvariableisset***/
if(isset($_GET['bid'])&&is_numeric($_GET['bid']))
{
/***ifwearehere,includethedbconnection***/
include'includes/conn.php';
/***testfordbconnection***/
if($db)
{
/***excapethestring***/
$blog_content_id=mysql_real_escape_string($_GET['bid']);
/***thesqlquery***/
$sql="DELETE
FROM
blog_content
WHERE
blog_content_id=$blog_content_id";
/***checkaccesslevel***/
if($_SESSION['access_level']==1)
{
$blog_user_id=mysql_real_escape_string($_SESSION['blog_user_id']);
$sql.="ANDblog_user_id=$blog_user_id";
}
/***runthequery***/
if(mysql_query($sql))
{
/***affectedrows***/
$affected=mysql_affected_rows($link);

header("Location:list_blogs.php");
}
else
{
echo'BlogEntryNotDeleted';
}
}
else
{
echo'Unabletoprocessform';
}
}
else
{
echo'InvalidSubmission';
}
}
?>

With this le in place, the blog is complete and ready for action.

SOD THIS, JUST GIVE ME THE BLOG


The entire source code for this blog application is available for download and users are free to use it, or build on it however they wish.
Download blog.tar.gz (/downloads/blog.tar.gz)

CREDITS
Thanks to Captain Cook for discovering Australia, and to the British, for sending us here.

Search...

PHPcode
generator
GeneratePHP
codeforanylocal
orremote
database.

Categories
Testing (/quiz)
Services (/services)
Tutorials (/tutorials)

Articles (/articles)

(/)

(+61) 434 868 173

Examples (/examples)

Classes (/classes)

Contact (/contact)

Popular

Recent

(blog-single.html)

(blog-single.html)

(blog-single.html)

(blog-single.html)

(blog-single.html)

SPL Autoload (/tutorials/SPL-Autoload.html)


09 May, 2016

Easter Egg (/tutorials/Easter-Egg.html)


09 May, 2016

Simple Mysql PHP Menu (/tutorials/Simple-Mysql-PHP-Menu.html)


09 May, 2016

Simple Mysql PHP Menu (/tutorials/Simple-Mysql-PHP-Menu.html)


09 May, 2016

Xajax-In An Object Oriented Environment (/tutorials/Xajax-In-An-Object-Oriented-Environment.html)


09 Sep, 2014

About Us
Providing the best and most up to date tutorials and examples on the web. Our candidate testing service provides the best method of screen candidates to be
assured of securing the right resource for your business.

Get in Touch

Newsletter
Keep up on our always evolving product features and technology. Enter your e-mail and subscribe to our newsletter.

Email Address

Go!

Latest Tweet
Contact Us
Address: 2 Funny St, Narrabeen, Australia
Phone: Private
Email: sales@phpro.org (mailto:sales@phpro.org)

Follow Us

(index.html)
I would rather see a sermon than hear one any day. I'd rather have you walk with me, than merely point the way. The eye is a more ready pupil than ever was the ear, good advice
is often confusing, but example is always clear.
Copyright 2016. All Rights Reserved. Digitalia Media Consultants (http://www.digitalia.com.au)
FAQ's (/about)

Sitemap (sitemap.html)

Contact (/contact)

Вам также может понравиться