How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

27
2/26/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+ 1/27 net.tutsplus.com/tutorials/php/h ow-to-create-a-php mysql-powered-foru m-from-scrat ch/ Advertise Here Ho o Ceae a PHP/MSQL Poeed Fo m fom Sca ch Evert Padje on Mar 17th 2010 with 520 comments Toial Deail Technolog: PHP Difficl: Intermediate-Advanced Eimaed Compleion Time: 5 Hours In this tutorial, we’re going to build a PHP/MySQL powered forum from scratch. This tutorial is perfect for getting used to basic PHP and database usage. Let’s dive right in! Sep 1: Ceaing Daabae Table It’s always a good idea to start with creating a good data model when building an application. Let’s describe our application in one sentence: We are going to make a forum which has e who create opic in various caegoie. Other users can po replies. As you can see, I highlighted a couple of nouns which represent our table names. Ue Categories Topics Posts These three objects are related to each other, so we’ll process that in our table design. Take a look at the scheme below.

Transcript of How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 1/27

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 2/27

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 3/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

e _name

This is a text field, called a VARCHAR field in MySQL. The number between brackets is the maximum length. A user can choose a username upto 30 characters long. This field cannot be NULL. At the bottom of the table you can see this field is declared UNIQUE, which means the sameusername cannot be registered twice. The UNIQUE INDEX part tells the database we want to add a unique key. Then we define the name of the unique key, user_name_unique in this case. Between brackets is the field the unique key applies to, which is user_name.

e _paThis field is equal to the user_name field, except the maximum length. Since the user password, no matter what length, is hashed with sha1(), the

password will always be 40 characters long.

e _email

This field is equal to the user_pass field.

e _da e

This is a field in which we’ll store the date the user registered. It’s type is DATETIME and the field cannot be NULL.

e _le el

This field contains the level of the user, for example: ’0 for a regular user and ’1 for an admin. More about this later.

Ca ego ie Tableview plaincopy to clipboardprint?

1. CREATE TABLE categories (

2. cat_id INT(8) NOT NULL AUTO_INCREMENT,3. cat_name VARCHAR(255) NOT NULL ,4. cat_description VARCHAR(255) NOT NULL ,5. UNIQUE INDEX cat_name_unique (cat_name),6. PRIMARY KEY (cat_id)7. ) TYPE=INNODB;

These data types basically work the same way as the ones in the users table. This table also has a primary key and the name of the category must be an unique one.

Topic Tableview plaincopy to clipboardprint?

1. CREATE TABLE topics (2. topic_id INT(8) NOT NULL AUTO_INCREMENT,3. topic_subject VARCHAR(255) NOT NULL ,4. topic_date DATETIME NOT NULL ,5. topic_cat INT(8) NOT NULL ,6. topic_by INT(8) NOT NULL ,7. PRIMARY KEY (topic_id)8. ) TYPE=INNODB;

This table is almost the same as the other tables, except for the topic_by field. That field refers to the user who created the topic. The topic_cat

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 4/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

refers to the category the topic belongs to. We cannot force these relationships by just declaring the field. We have to let the database know thisfield must contain an existing user_id from the users table, or a valid cat_id from the categories table. We’ll add some relationships after I’vediscussed the posts table.

Po Tableview plaincopy to clipboardprint?

1. CREATE TABLE posts (

2. post_id INT(8) NOT NULL AUTO_INCREMENT,3. post_content TEXT NOT NULL ,4. post_date DATETIME NOT NULL ,5. post_topic INT(8) NOT NULL ,6. post_by INT(8) NOT NULL ,7. PRIMARY KEY (post_id)8. ) TYPE=INNODB;

This is the same as the rest of the tables; there’s also a field which refers to a user_id here: the post_by field. The post_topic field refers to thetopic the post belongs to.

“A foreign key is a referential constraint between two tables. The foreign key identifies a column or a set of columns in one(referencing) table that refers to a column or set of columns in another (referenced) table.”

Now that we’ve executed these queries, we have a pretty decent data model, but the relations are still missing. Let’s start with the definition of arelationship. We’re going to use something called a foreign key. A foreign key is a referential constraint between two tables. The foreign keyidentifies a column or a set of columns in one (referencing) table that refers to a column or set of columns in another (referenced) table. Someconditions:

The column in the referencing table the foreign key refers to must be a primary keyThe values that are referred to must exist in the referenced table

By adding foreign keys the information is linked together which is very important for database normalization. Now you know what a foreign keyis and why we’re using them. It’s time to add them to the tables we’ve already made by using the ALTER statement, which can be used tochange an already existing table.

We’ll link the topics to the categories first:

view plaincopy to clipboardprint?

1. ALTER TABLE topics ADD FOREIGN KEY(topic_cat) REFERENCES categories(cat_id) ON DELETE CASCADE ON UPDATE C

The last part of the query already says what happens. When a category gets deleted from the database, all the topics will be deleted too. If thecat_id of a category changes, every topic will be updated too. That’s what the ON UPDATE CASCADE part is for. Of course, you can reversethis to protect your data, so that you can’t delete a category as long as it still has topics linked to it. If you would want to do that, you couldreplace the ‘ON DELETE CASCADE’ part with ‘ON DELETE RESTRICT’. There is also SET NULL and NO ACTION, which speak for themselves.

Every topic is linked to a category now. Let’s link the topics to the user who creates one.

view plaincopy to clipboardprint?

1. ALTER TABLE topics ADD FOREIGN KEY(topic_by) REFERENCES users(user_id) ON DELETE RESTRICT ON UPDATE CASC

This foreign key is the same as the previous one, but there is one difference: the user can’t be deleted as long as there are still topics with the user id of the user. We don’t use CASCADE here because there might be valuable information in our topics. We wouldn’t want that information toget deleted if someone decides to delete their account. To still give users the opportunity to delete their account, you could build some feature thatanonymizes all their topics and then delete their account. Unfortunately, that is beyond the scope of this tutorial.

Link he po o he opic :

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 5/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

view plaincopy to clipboardprint?

1. ALTER TABLE posts ADD FOREIGN KEY(post_topic) REFERENCES topics(topic_id) ON DELETE CASCADE ON UPDATE CA

And finall , link each po o he e ho made i :

view plaincopy to clipboardprint?

1. ALTER TABLE posts ADD FOREIGN KEY(post_by) REFERENCES users(user_id) ON DELETE RESTRICT ON UPDATE CASC

That’s the database part! It was quite a lot of work, but the result, a great data model, is definitely worth it.

S ep 2: In od c ion o he Heade /Foo e S emEach page of our forum needs a few basic things, like a doctype and some markup. That’s why we’ll include a header.php file at the top of each

page, and a footer.php at the bottom. The header.php contains a doctype, a link to the stylesheet and some important information about theforum, such as the title tag and metatags.

heade .phpview plaincopy to clipboardprint?

1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"2. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">3. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl" lang="nl">4. <head>5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />6. <meta name="description" content="A short description." />7. <meta name="keywords" content="put, keywords, here" />8. <title>PHP-MySQL forum</title>9. <link rel="stylesheet" href="style.css" type="text/css">

10. </head>11. <body>

12. <h1>My forum</h1>13. <div id="wrapper">14. <div id="menu">15. <a class="item" href="/forum/index.php">Home</a> -16. <a class="item" href="/forum/create_topic.php">Create a topic</a> -17. <a class="item" href="/forum/create_cat.php">Create a category</a>18.19. <div id="userbar">20. <div id="userbar">Hello Example. Not you? Log out.</div>21. </div>22. <div id="content">23.

The wrapper div will be used to make it easier to style the entire page. The menu div obviously contains a menu with links to pages we still haveto create, but it helps to see where we’re going a little bit. The userbar div is going to be used for a small top bar which contains some informationlike the username and a link to the logout page. The content page holds the actual content of the page, obviously.

The attentive reader might have already noticed we’re missing some things. There is no </body> or </html> tag. They’re in the footer.php page,as you can see below.

view plaincopy to clipboardprint?

1. </div><!-- content -->2. </div><!-- wrapper -->3. <div id="footer">Created for Nettuts+</div>

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 6/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

4. </body>5. </html>6.

When we include a header and a footer on each page the rest of the page get embedded between the header and the footer. This method has gotsome advantages. First and foremost, everything will be styled correctly. A short example:

view plaincopy to clipboardprint?

1. <?php

2. $error = false;3. if($error = false)4. {5. //the beautifully styled content, everything looks good6. echo '<div id="content">some text</div>';7. }8. else9. {

10. //bad looking, unstyled error :-(11. }12. ?>13.

As you can see, a page without errors will result in a nice page with the content. But if there’s an error, everything looks really ugly; so that’s whyit’s better to make sure not only real content is styled correctly, but also the errors we might get.

Another advantage is the possibility of making quick changes. You can see for yourself by editing the text in footer.php when you’ve finished thistutorial; you’ll notice that the footer changes on every page immediately. Finally, we add a stylesheet which provides us with some basic markup

– nothing too fancy.

view plaincopy to clipboardprint?

1. body {2. background-color: #4E4E4E ;3. text-align: center; /* make sure IE centers the page too */

4. }5.6. #wrappe r {7. width: 900px;8. margin: 0 auto; /* center the page */9. }

10.11. #content {12. background-color: #fff ;13. border: 1px solid #000 ;14. float: left;15. font-family: Arial;16. padding: 20px 30px;17. text-align: left;18. width: 100%; /* fill up the entire div */19. }20.21. #menu {22. float: left;23. border: 1px solid #000 ;24. border-bottom: none; /* avoid a double border */25. clear: both; /* clear:both makes sure the content div doesn't float next to this one but stays under it */26. width:100%;27. height:20px;28. padding: 0 30px;

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 7/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

29. background-color: #FFF ;30. text-align: left;31. font-size: 85%;32. }33.34. #menu a:hover {35. background-color: #009FC1 ;36. }37.38. #userba r {39. background-color: #fff ;40. float: rightright;41. width: 250px;42. }43.44. #footer {45. clear: both;46. }47.48. /* begin table styles */49. table {50. border-collapse: collapse;51. width: 100%;52. }53.54. table a {55. color: #000;56. }57.58. table a:hover {59. color: #373737 ;60. text-decoration: none;61. }62.

63. th {64. background-color: #B40E1F ;65. color: #F0F0F0 ;66. }67.68. td {69. padding: 5px;70. }71.72. /* Begin font styles */73. h1, #footer {74. font-family: Arial;

75. color: #F1F3F1 ;76. }77.78. h3 {margin: 0; padding: 0;}79.80. /* Menu styles */81. .item {82. background-color: #00728B ;83. border: 1px solid #032472 ;84. color: #FFF ;85. font-family: Arial;86. padding: 3px;

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 8/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

87. text-decoration: none;88. }89.90. .leftpart {91. width: 70%;92. }93.94. .rightpart {95. width: 30%;96. }97.98. .small {99. font-size: 75%;

100. color: #373737 ;101. }102. #footer {103. font-size: 65%;104. padding: 3px 0 0 0;105. }106.107. .topic-post {108. height: 100px;109. overflow: auto;110. }111.112. .post-content {113. padding: 30px;114. }115.116. textarea {117. width: 500px;118. height: 200px;119. }120.

S ep 3: Ge ing Read fo Ac ionBefore we can read anything from our database, we need a connection. That’s what connect.php is for. We’ll include it in every file we are goingto create.

view plaincopy to clipboardprint?

1. <?php2. //connect.php3. $server = 'localhost';4. $username = 'usernamehere';5. $password = 'passwordhere';6. $database = 'databasenamehere';7.8. if(!mysql_connect($server, $username, $password))9. {

10. exit('Error: could not establish database connection');11. }12. if(!mysql_select_db($database)13. {14. exit('Error: could not select the database');15. }

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 9/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

16. ?>17.

Simply replace the default values of the variables at the top of the page with your own date, save the file and you’re good to go!

S ep 4: Di pla ing he Fo m O e ieSince we’re just started with some basic techniques, we’re going to make a simplified version of the forum overview for now.

view plaincopy to clipboardprint?

1. <?php2. //create_cat.php3. include 'connect.php';4. include 'header.php';5.6. echo '<tr>';7. echo '<td class="leftpart">';8. echo '<h3><a href="category.php?id=">Category name</a></h3> Category description goes here';9. echo '</td>';

10. echo '<td class="rightpart">';11. echo '<a href="topic.php?id=">Topic subject</a> at 10-10';12. echo '</td>';13. echo '</tr>';14. include 'footer.php';15. ?>16.

There you have it: a nice and clean overview. We’ll be updating this page throughout the tutorial so that it becomes more like the end result, step by step!

S ep 5: Signing p a U e Let’s start by making a simple HTML form so that a new user can register.

A PHP page is needed to process the form. We’re going to use a $_SERVER variable. The $_SERVER variable is an array with values that areautomatically set with each request. One of the values of the $_SERVER array is ‘REQUEST_METHOD’. When a page is requested with GET,this variable will hold the value ‘GET’. When a page is requested via POST, it will hold the value ‘POST’. We can use this value to check if aform has been posted. See the signup.php page below.

view plaincopy to clipboardprint?

1. <?php2. //signup.php3. include 'connect.php';4. include 'header.php';5.6. echo '<h3>Sign up</h3>';7.8. if($_SERVER['REQUEST_METHOD'] != 'POST')9. {

10. /*the form hasn't been posted yet, display it11. note that the action="" will cause the form to post to the same page it is on */12. echo '<form method="post" action="">

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 10/27

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 11/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

71. //notice the use of mysql_real_escape_string, keep everything safe!72. //also notice the sha1 function which hashes the password73. $sql = "INSERT INTO74. users(user_name, user_pass, user_email ,user_date, user_level)75. VALUES('" . mysql_real_escape_string($_POST['user_name']) . "',76. '" . sha1($_POST['user_pass']) . "',77. '" . mysql_real_escape_string($_POST['user_email']) . "',78. NOW(),79. 0)";80.81. $result = mysql_query($sql);82. if(!$result)83. {84. //something went wrong, display the error 85. echo 'Something went wrong while registering. Please try again later.';86. //echo mysql_error(); //debugging purposes, uncomment when needed87. }88. else89. {90. echo 'Successfully registered. You can now <a href="signin.php">sign in</a> and start posting! :-)';91. }92. }93. }94.95. include 'footer.php';96. ?>97.

A lot of explanation is in the comments I made in the file, so be sure to check them out. The processing of the data takes place in three parts:

Validating the dataIf the data is not valid, show the form againIf the data is valid, save the record in the database

The PHP part is quite self-explanatory. The SQL-query however probably needs a little more explanation.

view plaincopy to clipboardprint?

1. INSERT INTO2. users(user_name, user_pass, user_email ,user_date, user_level)3. VALUES('" . mysql_real_escape_string($_POST['user_name']) . "',4. '" . sha1($_POST['user_pass']) . "',5. '" . mysql_real_escape_string($_POST['user_email']) . "',6. NOW(),7. 0);8.

On line 1 we have the INSERT INTO statement which speaks for itself. The table name is specified on the second line. The words between the brackets represent the columns in which we want to insert the data. The VALUES statement tells the database we’re done declaring columnnames and it’s time to specify the values. There is something new here: mysql_real_escape_string. The function escapes special characters in anunescaped string , so that it is safe to place it in a query. This function MUST always be used, with very few exceptions. There are too manyscripts that don’t use it and can be hacked real easy. Don’t take the risk, use mysql_real_escape_string().

“Never insert a plain password as-is. You MUST always encrypt it.”

Also, you can see that the function sha1() is used to encrypt the user’s password. This is also a very important thing to remember. Never insert a plain password as-is. You MUST always encrypt it. Imagine a hacker who somehow manages to get access to your database. If he sees all the plain-text passwords he could log into any (admin) account he wants. If the password columns contain sha1 strings he has to crack them firstwhich is almost impossible.

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 12/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

Note: it’s also possible to use md5(), I always use sha1() because benchmarks have proved it’s a tiny bit faster, not much though. You canreplace sha1 with md5 if you like.

If the signup process was successful, you should see something like this:

Try refreshing your phpMyAdmin screen, a new record should be visible in the users table.

S ep 6: Adding A hen ica ion and U e Le elAn important aspect of a forum is the difference between regular users and admins/moderators. Since this is a small forum and adding featureslike adding new moderators and stuff would take way too much time, we’ll focus on the login process and create some admin features likecreating new categories and closing a thread.

Now that you’ve completed the previous step, we’re going to make your freshly created account an admin account. In phpMyAdmin, click onthe users table, and then ‘Browse’. Your account will probably pop up right away. Click the edit icon and change the value of the user_level fieldfrom 0 to 1. That’s it for now. You won’t notice any difference in our application immediately, but when we’ve added the admin features anormal account and your account will have different capabilities.

The sign-in process works the following way:

A visitor enters user data and submits the formIf the username and password are correct, we can start a sessionIf the username and password are incorrect, we show the form again with a message

The signin.php file is below. Don’t think I’m not explaining what I’m doing, but check out the comments in the file. It’s much easier to understandthat way.

view plaincopy to clipboardprint?

1. <?php

2. //signin.php3. include 'connect.php';4. include 'header.php';5.6. echo '<h3>Sign in</h3>';7.8. //first, check if the user is already signed in. If that is the case, there is no need to display this page9. if(isset($_SESSION['signed_in']) && $_SESSION['signed_in'] == true)

10. {11. echo 'You are already signed in, you can <a href="signout.php">sign out</a> if you want.';12. }13. else

14. {15. if($_SERVER['REQUEST_METHOD'] != 'POST')16. {17. /*the form hasn't been posted yet, display it18. note that the action="" will cause the form to post to the same page it is on */19. echo '<form method="post" action="">20. Username: <input type="text" name="user_name" />21. Password: <input type="password" name="user_pass">22. <input type="submit" value="Sign in" />23. </form>';24. }25. else

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 13/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

26. {27. /* so, the form has been posted, we'll process the data in three steps:28. 1. Check the data29. 2. Let the user refill the wrong fields (if necessary)30. 3. Varify if the data is correct and return the correct response31. */32. $errors = array(); /* declare the array for later use */33.34. if(!isset($_POST['user_name']))35. {36. $errors[] = 'The username field must not be empty.';37. }38.39. if(!isset($_POST['user_pass']))40. {41. $errors[] = 'The password field must not be empty.';42. }43.44. if(!empty($errors)) /*check for an empty array, if there are errors, they're in this array (note the ! operator)*/45. {46. echo 'Uh-oh.. a couple of fields are not filled in correctly..';47. echo '<ul>';48. foreach($errors as $key => $value) /* walk through the array so all the errors get displayed */49. {50. echo '<li>' . $value . '</li>'; /* this generates a nice error list */51. }52. echo '</ul>';53. }54. else55. {56. //the form has been posted without errors, so save it57. //notice the use of mysql_real_escape_string, keep everything safe!58. //also notice the sha1 function which hashes the password59. $sql = "SELECT

60. user_id,61. user_name,62. user_level63. FROM64. users65. WHERE66. user_name = '" . mysql_real_escape_string($_POST['user_name']) . "'67. AND68. user_pass = '" . sha1($_POST['user_pass']) . "'";69.70. $result = mysql_query($sql);71. if(!$result)

72. {73. //something went wrong, display the error 74. echo 'Something went wrong while signing in. Please try again later.';75. //echo mysql_error(); //debugging purposes, uncomment when needed76. }77. else78. {79. //the query was successfully executed, there are 2 possibilities80. //1. the query returned data, the user can be signed in81. //2. the query returned an empty result set, the credentials were wrong82. if(mysql_num_rows($result) == 0)83. {

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 14/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

84. echo 'You have supplied a wrong user/password combination. Please try again.';85. }86. else87. {88. //set the $_SESSION['signed_in'] variable to TRUE89. $_SESSION['signed_in'] = true;90.91. //we also put the user_id and user_name values in the $_SESSION, so we can use it at various pages92. while($row = mysql_fetch_assoc($result))93. {94. $_SESSION['user_id'] = $row['user_id'];95. $_SESSION['user_name'] = $row['user_name'];96. $_SESSION['user_level'] = $row['user_level'];97. }98.99. echo 'Welcome, ' . $_SESSION['user_name'] . '. <a href="index.php">Proceed to the forum overview</a>.';

100. }101. }102. }103. }104. }105.106. include 'footer.php';107. ?>108.

This is the query that’s in the signin.php file:

view plaincopy to clipboardprint?

1. SELECT2. user_id,3. user_name,4. user_level

5. FROM6. users7. WHERE8. user_name = '" . mysql_real_escape_string($_POST['user_name']) . "'9. AND

10. user_pass = '" . sha1($_POST['user_pass'])11.

It’s obvious we need a check to tell if the supplied credentials belong to an existing user. A lot of scripts retrieve the password from the databaseand compare it using PHP. If we do this directly via SQL the password will be stored in the database once during registration and never leave itagain. This is safer, because all the real action happens in the database layer and not in our application.

If the user is signed in successfully, we’re doing a few things:

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 15/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

view plaincopy to clipboardprint?

1. <?php2. //set the $_SESSION['signed_in'] variable to TRUE3. $_SESSION['signed_in'] = true;4. //we also put the user_id and user_name values in the $_SESSION, so we can use it at various pages5. while($row = mysql_fetch_assoc($result))6. {7. $_SESSION['user_id'] = $row['user_id'];8. $_SESSION['user_name'] = $row['user_name'];9. }

10. ?>11.

First, we set the ‘signed_in’ $_SESSION var to true, so we can use it on other pages to make sure the user is signed in. We also put theusername and user id in the $_SESSION variable for usage on a different page. Finally, we display a link to the forum overview so the user canget started right away.

Of course signing in requires another function, signing out! The sign-out process is actually a lot easier than the sign-in process. Because all theinformation about the user is stored in $_SESSION variables, all we have to do is unset them and display a message.

Now that we’ve set the $_SESSION variables, we can determine if someone is signed in. Let’s make a last simple change to header.php:

Replace:

view plaincopy to clipboardprint?

1. <di id="userbar">Hello Example. Not you? Log out. </di > 2.

With:

view plaincopy to clipboardprint?

1. <?php2. <div id="userbar">

3. if($_SESSION['signed_in'])4. {5. echo 'Hello' . $_SESSION['user_name'] . '. Not you? <a href="signout.php">Sign out</a>';6. }7. else8. {9. echo '<a href="signin.php">Sign in</a> or <a href="sign up">create an account</a>. ';

10. }11. </div>12.

If a user is signed in, he will see his or her name displayed on the front page with a link to the signout page. Our authentication is done! By now

our forum should look like this:

S ep 7: C ea ing a Ca egoWe want to create categories so let’s start with making a form.

view plaincopy to clipboardprint?

1. <fo m method ="post" action=""> 2. Category name: <inp type="text" name ="cat_name" />

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 16/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

3. Category description: < e a ea name="cat_description" /></ e a ea> 4. <inp type="submit" value="Add category" /> 5. </fo m> 6.

This step looks a lot like Step 4 (Signing up a user’), so I’m not going to do an in-depth explanation here. If you followed all the steps you should be able to understand this somewhat quickly.

view plaincopy to clipboardprint?

1. <?php2. //create_cat.php3. include 'connect.php';4.5. if($_SERVER['REQUEST_METHOD'] != 'POST')6. {7. //the form hasn't been posted yet, display it8. echo '<form method='post' action=''>9. Category name: <input type='text' name='cat_name' />

10. Category description: <textarea name='cat_description' /></textarea>11. <input type='submit' value='Add category' />12. </form>';

13. }14. else15. {16. //the form has been posted, so save it17. $sql = ìINSERT INTO categories(cat_name, cat_description)18. VALUES('' . mysql_real_escape_string($_POST['cat_name']) . ì',19. '' . mysql_real_escape_string($_POST['cat_description']) . ì')';20. $result = mysql_query($sql);21. if(!$result)22. {23. //something went wrong, display the error 24. echo 'Error' . mysql_error();25. }26. else27. {28. echo 'New category successfully added.';29. }30. }31. ?>32.

As you can see, we’ve started the script with the $_SERVER check, after checking if the user has admin rights, which is required for creating acategory. The form gets displayed if it hasn’t been submitted already. If it has, the values are saved. Once again, a SQL query is prepared andthen executed.

S ep 8: Adding Ca ego ie o inde .phpWe’ve created some categories, so now we’re able to display them on the front page. Let’s add the following query to the content area of index.php.

view plaincopy to clipboardprint?

1. SELECT2. categories.cat_id,

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 17/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

3. categories.cat_name,4. categories.cat_description,5. FROM6. categories7.

This query selects all categories and their names and descriptions from the categories table. We only need a bit of PHP to display the results. If we add that part just like we did in the previous steps, the code will look like this.

view plaincopy to clipboardprint?

1. <?php2. //create_cat.php3. include 'connect.php';4. include 'header.php';5.6. $sql = "SELECT7. cat_id,8. cat_name,9. cat_description,

10. FROM11. categories";

12.13. $result = mysql_query($sql);14.15. if(!$result)16. {17. echo 'The categories could not be displayed, please try again later.';18. }19. else20. {21. if(mysql_num_rows($result) == 0)22. {23. echo 'No categories defined yet.';24. }25. else26. {27. //prepare the table28. echo '<table border="1">29. <tr>30. <th>Category</th>31. <th>Last topic</th>32. </tr>';33.34. while($row = mysql_fetch_assoc($result))35. {36. echo '<tr>';37. echo '<td class="leftpart">';38. echo '<h3><a href="category.php?id">' . $row['cat_name'] . '</a></h3>' . $row['cat_description'];39. echo '</td>';40. echo '<td class="rightpart">';41. echo '<a href="topic.php?id=">Topic subject</a> at 10-10';42. echo '</td>';43. echo '</tr>';44. }45. }46. }47.48. include 'footer.php';

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 18/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

49. ?>50.

Notice how we’re using the cat_id to create links to category.php. All the links to this page will look like this: category.php?cat_id=x, where xcan be any numeric value. This may be new to you. We can check the url with PHP for $_GET values. For example, we have this link:

view plaincopy to clipboardprint?

1. category.php? cat_id =23 2.

The statement echo $_GET[ëcat_id'];’ will display ’23 . In the next few steps we’ll use this value to retrieve the topics when viewing a singlecategory, but topics can’t be viewed if we haven’t created them yet. So let’s create some topics!

S ep 9: C ea ing a TopicIn this step, we’re combining the techniques we learned in the previous steps. We’re checking if a user is signed in, we’ll use an input query tocreate the topic and create some basic HTML forms.

The structure of create_topic.php can hardly be explained in a list or something, so I rewrote it in pseudo-code.

view plaincopy to clipboardprint?

1. <?php2. if(user is signed in)3. {4. //the user is not signed in5. }6. else7. {8. //the user is signed in9. if(form has not been posted)

10. {11. //show form12. }13. else14. {15. //process form16. }17. }18. ?>19.

Here’s the real code of this part of our forum, check the explanations below the code to see what it’s doing.

view plaincopy to clipboardprint?

1. <?php2. //create_cat.php3. include 'connect.php';4. include 'header.php';5.6. echo '<h2>Create a topic</h2>';7. if($_SESSION['signed_in'] == false)8. {9. //the user is not signed in

10. echo 'Sorry, you have to be <a href="/forum/signin.php">signed in</a> to create a topic.';11. }

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 19/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

12. else13. {14. //the user is signed in15. if($_SERVER['REQUEST_METHOD'] != 'POST')16. {17. //the form hasn't been posted yet, display it18. //retrieve the categories from the database for use in the dropdown19. $sql = "SELECT20. cat_id,21. cat_name,22. cat_description23. FROM24. categories";25.26. $result = mysql_query($sql);27.28. if(!$result)29. {30. //the query failed, uh-oh :-(31. echo 'Error while selecting from database. Please try again later.';32. }33. else34. {35. if(mysql_num_rows($result) == 0)36. {37. //there are no categories, so a topic can't be posted38. if($_SESSION['user_level'] == 1)39. {40. echo 'You have not created categories yet.';41. }42. else43. {44. echo 'Before you can post a topic, you must wait for an admin to create some categories.';45. }

46. }47. else48. {49.50. echo '<form method="post" action="">51. Subject: <input type="text" name="topic_subject" />52. Category:';53.54. echo '<select name="topic_cat">';55. while($row = mysql_fetch_assoc($result))56. {57. echo '<option value="' . $row['cat_id'] . '">' . $row['cat_name'] . '</option>';

58. }59. echo '</select>';60.61. echo 'Message: <textarea name="post_content" /></textarea>62. <input type="submit" value="Create topic" />63. </form>';64. }65. }66. }67. else68. {69. //start the transaction

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 20/27

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 21/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

128. else129. {130. $sql = "COMMIT;";131. $result = mysql_query($sql);132.133. //after a lot of work, the query succeeded!134. echo 'You have successfully created <a href="topic.php?id='. $topicid . '">your new topic</a>.';135. }136. }137. }138. }139. }140.141. include 'footer.php';142. ?>143.

I’ll discuss this page in two parts, showing the form and processing the form.

Sho ing he fo mWe’re starting with a simple HTML form. There is actually something special here, because we use a dropdown. This dropdown is filled withdata from the database, using this query:

view plaincopy to clipboardprint?

1. SELECT2. cat_id,3. cat_name,4. cat_description5. FROM6. categories7.

That’s the only potentially confusing part here; it’s quite a piece of code, as you can see when looking at the create_topic.php file at the bottom of this step.

P oce ing he fo m

The process of saving the topic consists of two parts: saving the topic in the topics table and saving the first post in the posts table. This requiressomething quite advanced that goes a bit beyond the scope of this tutorial. It’s called a transaction, which basically means that we start byexecuting the start command and then rollback when there are database errors and commit when everything went well. More about transactions .

view plaincopy to clipboardprint?

1. <?php2. //start the transaction3. $query = "BEGIN WORK;";4. $result = mysql_query($query);

5. //stop the transaction6. $sql = "ROLLBACK;";7. $result = mysql_query($sql);8. //commit the transaction9. $sql = "COMMIT;";

10. $result = mysql_query($sql);11. ?>12.

The first query being used to save the data is the topic creation query, which looks like this:

view plaincopy to clipboardprint?

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 22/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

1. INSERT INTO2. topics(topic_subject,3. topic_date,4. topic_cat,5. topic_by)6. VALUES('" . mysql_real_escape_string($_POST['topic_subject']) . "',7. NOW(),8. " . mysql_real_escape_string($_POST['topic_cat']) . ",9. " . $_SESSION['user_id'] . ")

10.

At first the fields are defined, then the values to be inserted. We’ve seen the first one before, it’s just a string which is made safe by usingmysql_real_escape_string(). The second value, NOW(), is a SQL function for the current time. The third value, however, is a value we haven’tseen before. It refers to a (valid) id of a category. The last value refers to an (existing) user_id which is, in this case, the value of $_SESSION[ëuser_id']. This variable was declared during the sign in process.

If the query executed without errors we proceed to the second query. Remember we are still doing a transaction here. If we would’ve got errorswe would have used the ROLLBACK command.

view plaincopy to clipboardprint?

1. INSERT INTO2. posts(post_content,3. post_date,4. post_topic,5. post_by)6. VALUES7. ('" . mysql_real_escape_string($_POST['post_content']) . "',8. NOW(),9. " . $topicid . ",

10. " . $_SESSION['user_id'] . ")11.

The first thing we do in this code is use mysql_insert_id() to retrieve the latest generated id from the topic_id field in the topics table. As you mayremember from the first steps of this tutorial, the id is generated in the database using auto_increment.

Then the post is inserted into the posts table. This query looks a lot like the topics query. The only difference is that this post refers to the topicand the topic referred to a category. From the start, we decided to create a good data model and here is the result: a nice hierarchical structure.

S ep 10: Ca ego VieWe’re going to make an overview page for a single category. We’ve just created a category, it would be handy to be able to view all the topicsin it. First, create a page called category.php.

A short list of the things we need:

Needed fo di pla ing he ca egocat_namecat_description

Needed for displa ing all the topics

topic_idtopic_subject

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 23/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

topic_datetopic_cat

Let’s create the two SQL queries that retrieve exactly this data from the database.

view plaincopy to clipboardprint?

1. SELECT2. cat_id,3. cat_name,

4. cat_description5. FROM6. categories7. WHERE8. cat_id = " . mysql_real_escape_string($_GET['id'])9.

The query above selects all the categories from the database.

view plaincopy to clipboardprint?

1. SELECT2. topic_id,

3. topic_subject,4. topic_date,5. topic_cat6. FROM7. topics8. WHERE9. topic_cat = " . mysql_real_escape_string($_GET['id'])

10.

The query above is executed in the while loop in which we echo the categories. By doing it this way, we’ll see all the categories and the latesttopic for each of them.The complete code of category.php will be the following:

view plaincopy to clipboardprint?

1. <?php2. //create_cat.php3. include 'connect.php';4. include 'header.php';5.6. //first select the category based on $_GET['cat_id']7. $sql = "SELECT8. cat_id,9. cat_name,

10. cat_description

11. FROM12. categories13. WHERE14. cat_id = " . mysql_real_escape_string($_GET['id']);15.16. $result = mysql_query($sql);17.18. if(!$result)19. {20. echo 'The category could not be displayed, please try again later.' . mysql_error();21. }22. else

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 24/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

23. {24. if(mysql_num_rows($result) == 0)25. {26. echo 'This category does not exist.';27. }28. else29. {30. //display category data31. while($row = mysql_fetch_assoc($result))32. {33. echo '<h2>Topics in ' . $row['cat_name'] . ' category</h2>';34. }35.36. //do a query for the topics37. $sql = "SELECT38. topic_id,39. topic_subject,40. topic_date,41. topic_cat42. FROM43. topics44. WHERE45. topic_cat = " . mysql_real_escape_string($_GET['id']);46.47. $result = mysql_query($sql);48.49. if(!$result)50. {51. echo 'The topics could not be displayed, please try again later.';52. }53. else54. {55. if(mysql_num_rows($result) == 0)56. {

57. echo 'There are no topics in this category yet.';58. }59. else60. {61. //prepare the table62. echo '<table border="1">63. <tr>64. <th>Topic</th>65. <th>Created at</th>66. </tr>';67.68. while($row = mysql_fetch_assoc($result))

69. {70. echo '<tr>';71. echo '<td class="leftpart">';72. echo '<h3><a href="topic.php?id=' . $row['topic_id'] . '">' . $row['topic_subject'] . '</a><h3>';73. echo '</td>';74. echo '<td class="rightpart">';75. echo date('d-m-Y', strtotime($row['topic_date']));76. echo '</td>';77. echo '</tr>';78. }79. }80. }

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 25/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

81. }82. }83.84. include 'footer.php';85. ?>86.

And here is the final result of our categories page:

S ep 11: Topic VieThe SQL queries in this step are complicated ones. The PHP-part is all stuff that you’ve seen before. Let’s take a look at the queries. The firstone retrieves basic information about the topic:

view plaincopy to clipboardprint?

1. SELECT2. topic_id,3. topic_subject

4. FROM5. topics6. WHERE7. topics.topic_id = " . mysql_real_escape_string($_GET['id'])8.

This information is displayed in the head of the table we will use to display all the data. Next, we retrieve all the posts in this topic from thedatabase. The following query gives us exactly what we need:

view plaincopy to clipboardprint?

1. SELECT2. posts.post_topic,3. posts.post_content,4. posts.post_date,5. posts.post_by,6. users.user_id,7. users.user_name8. FROM9. posts

10. LEFT JOIN 11. users12. ON13. posts.post_by = users.user_id14. WHERE

15. posts.post_topic = " . mysql_real_escape_string($_GET['id'])16.

This time, we want information from the users and the posts table – so we use the LEFT JOIN again. The condition is: the user id should be thesame as the post_by field. This way we can show the username of the user who replied at each post.

The final topic view looks like this:

S ep 12: Adding a Repl

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 26/27

6/12 How to Create a PHP/MySQL Powered Forum from Scratch Nettuts+

.tutsplus.com/tutorials/php/how-to-create-a-phpmysql-powered-forum-from-scratch/

Let’s create the last missing part of this forum, the possibility to add a reply. We’ll start by creating a form:

view plaincopy to clipboardprint?

1. <fo m method ="post" action="reply.php?id=5" > 2. < e a ea name ="reply-content" ></ e a ea> 3. <inp type="submit" value="Submit reply" /> 4. </fo m> 5.

The complete reply.php code looks like this.

view plaincopy to clipboardprint?

1. <?php2. //create_cat.php3. include 'connect.php';4. include 'header.php';5.6. if($_SERVER['REQUEST_METHOD'] != 'POST')7. {

8. //someone is calling the file directly, which we don't want9. echo 'This file cannot be called directly.';

10. }11. else12. {13. //check for sign in status14. if(!$_SESSION['signed_in'])15. {16. echo 'You must be signed in to post a reply.';17. }18. else19. {

20. //a real user posted a real reply21. $sql = "INSERT INTO22. posts(post_content,23. post_date,24. post_topic,25. post_by)26. VALUES ('" . $_POST['reply-content'] . "',27. NOW(),28. " . mysql_real_escape_string($_GET['id']) . ",29. " . $_SESSION['user_id'] . ")";30.31. $result = mysql_query($sql);

32.33. if(!$result)34. {35. echo 'Your reply has not been saved, please try again later.';36. }37. else38. {39. echo 'Your reply has been saved, check out <a href="topic.php?id=' . htmlentities($_GET['id']) . '">the topic</a>.';40. }41. }42. }43.44. include 'footer.php';

8/2/2019 How to Create a PHP_MySQL Powered Forum From Scratch _ Nettuts+

http://slidepdf.com/reader/full/how-to-create-a-phpmysql-powered-forum-from-scratch-nettuts 27/27