Create a Portfolio Client Area Using PHP and MySQL: Part 4
Since Part 3, we’ve gotten through all the membership stuff — basically something you could find on any PHP/MySQL tutorial. Now, though, we will finally get into the part of this tutorial that makes it a “client area.” In this tutorial, we’ll cover the “shared documents” section of the client area.
Sharing documents back and forth between clients can be a real hassle via email, and other online tools to handle this can get expensive. Having your own client area manage documents is a great way to combat both issues.
To begin, let’s brainstorm what we’ll need this page to do:
- It should allow the client to upload documents — text, images, Word docs, etc.
- It should process the uploaded file to determine the size, type, and place it in the correct area. It should also be smart enough to avoid attacks or huge files that would hurt things on your end.
- It should display any already uploaded documents, and let the client view/download them again.
With the bit of organization we have now, we jump right in and get started.
Read up on the other parts of this tutorial below.
Create the “documents.php” File
Before we get into any real coding, let’s create a new file for the shared documents area. I’ll call it “documents.php” for this tutorial. Let’s also remember to determine if the client is logged in, otherwise redirecting them to the log in page.
This was also done on the profile page, (previous tutorial) so we can just do a bit of copying and pasting for this page, and any page we want protected.
<?php
session_start();
if(!isset($_SESSION['username'])){
header( 'Location: loginform.html' );
}
require('db.php'); // Connect to the database since we'll be needing it later.
Notice I’ve also deleted the comments that we originally had on the profile page for this section of code. As we get more familiar with our code, it may not be necessary to keep all the comments. (Although it should always be decently documented.) This will save space in our file.
The Upload Script
We’re going to want to keep all of the uploaded files in one folder, preferably called “uploads.” Because of our unique goal for this script, though, we’re going to need to find a way to associate a client with their own files.
To do this, let’s create a new table in our database, and store the path to the uploaded file along with the same ID as our current client. Here’s a breakdown of how it can work:
- The client is logged in, with their session variables set. Although we never set the client’s ID into the session’s variables, we can still easily find it.
- When the client uploads a file, our upload script will make a copy of the file and save it to a new location. We place both this URL and the same number as the client ID in a new table called “uploads.”
- Whenever a client uploads a new document, it will have that same ID number to reference. So, when the time comes to retrieve the information, we can use this ID number to display the files’ information.
- With a loop, we can easily find all of the client’s uploads, and with their link stored, we can display them accordingly with a download link.
Let’s begin this process now. We will need to add more basic security once we have a first working draft of our script ready.
The Upload HTML Form
For our upload form, I’ve used the basic form from the File Upload tutorial on Tizag. There is explanation below of our form, but feel free to check out that tutorial in it’s entirety for more insight.
<form enctype="multipart/form-data" action="uploader.php" method="POST"> <input type="hidden" name="MAX_FILE_SIZE" value="100000" /> Choose a file to upload: <input name="uploadedfile" type="file" /><br /> <input type="submit" value="Upload File" /> </form>
Here is a brief description of the important parts of the above code:
- enctype=”multipart/form-data” – Necessary for our to-be-created PHP file to function properly.
- action=”uploader.php” – The name of our PHP page that will be created, shortly.
- method=”POST” – Informs the browser that we want to send information to the server using POST.
- input type=”hidden” name=”MA… – Sets the maximum allowable file size, in bytes, that can be uploaded. This safety mechanism is easily bypassed and we will show a solid backup solution in PHP. We have set the max file size to 100KB in this example.
- input name=”uploadedfile” – uploadedfile is how we will access the file in our PHP script.
Now, let’s customize it a bit to fit our own needs. In the first line, we’re going to do something we haven’t done throughout the whole tutorial. We haven’t done it yet to keep things simple, but doing it now can help you organize your code better for past scripts and for this one:
<form enctype='multipart/form-data' action='documents.php' method='POST'>
Notice we changed the form from “uploader.php” to call itself with “documents.php”. This way, we can include our code on the same page. We will now have one page instead of our normal two. It can be a good practice to go through all our old files so far and change them to this format if you wish.
Create a Database Table to Hold Our URL’s
Before we go into the script, we’ll need to create our database table that will hold two things: an ID number that matches the client’s ID, and the URL to the saved file. After creating this, we can first store the information into this table, and then use it later to create the rest of our documents area.
- First log into phpMyAdmin, and go into the ClientArea database.
- Create a new table, and call it “uploads”. Enter in “2″ fields, and hit “Go.”
- I filled in the following information below. Below the image are additional notes for specifying this to your own needs:
Everything in the above image should be the same, or at least similar depending on what you want to name your values, except for the “Length/Values”. By putting the length of ID at two, this gives room for 99 clients. If you feel you will be having more than that over the lifetime of this script, feel free to bump it up to three. This will give you potential for 999 clients.
The URL length depends on where you’re going to store the uploads, and what you’ll name the folder. The character length will have to include your upload folder’s name, the filename, the extension, and any punctuation throughout that. A sample file name would be “uploads/contentforwebsite.doc”, which would be 29 characters. Give the client enough leeway for the file name length, but also not so long that it could be spam.
- It will say “No Index Defined!” once we go through and create this table, but that’s fine for now.

The Upload Script
We continue to follow the tutorial over at Tizag:
When the documents.php file is executed, the uploaded file exists in a temporary storage area on the server. If the file is not moved to a different location it will be destroyed! To save our precious file we are going to need to make use of the $_FILES associative array.
The $_FILES array is where PHP stores all the information about files. There are two elements of this array that we will need to understand for this example.
- uploadedfile – uploadedfile is the reference we assigned in our HTML form. We will need this to tell the $_FILES array which file we want to play around with.
- $_FILES['uploadedfile']['name'] – name contains the original path of the user uploaded file.
- $_FILES['uploadedfile']['tmp_name'] – tmp_name contains the path to the temporary file that resides on the server. The file should exist on the server in a temporary directory with a temporary name.
Now we can finally start to write a basic PHP upload manager script! Here is how we would get the temporary file name, choose a permanent name, and choose a place to store the file.
Create a new folder called “uploads” in the directory containing all of your other client area files. This script will not do it for you, and you must create if before the script is ever run.
Add the code below to the PHP portion of the page. This should still be in “documents.php” under where we checked if the user was logged in.
// Where the file is going to be placed $target_path = "uploads/"; // Add the original filename to our target path. // Result is "uploads/filename.extension" $target_path = $target_path . basename( $_FILES['uploadedfile']['name']);
Basically, we’ve used a few lines of code to create just one variable: “$target_path”. This will be the pathname to where we want to save our temporary uploaded file. It will be permanently saved here.
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
The code above uses the “move_uploaded_file() function to do all the work for us. It takes two parameters: the current temporary path ($_FILES['uploadedfile']['tmp_name']) and our new path we’d like to save the file to ($target_path).
The entire thing is in an if/else statement. If the function works and the file is moved, it was a success and will tell us so. Otherwise, it tells us that there was an error.
We’re going to want to change the happenings of the if/else statement to better meet our goal. The error message is fine, but we’ll want to do more if the file was successfully moved. Below is what we still need to do:
- Insert the client’s ID and path URL into our new table in our database.
- Return the client to the documents.php page. We will be displaying the files later in the tutorial, and this refresh should show the new file.
Let’s first insert the data into our table using a MySQL query:
$client_ID = mysql_query("SELECT 'client_ID'
FROM 'clients'
WHERE username='".$_SESSION['username']."'");
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
mysql_query(“INSERT INTO uploads(ID, URL) VALUES (‘$client_ID’, ‘$target_path’)”);
} else{
echo “There was an error uploading the file, please try again!”;
}
Ok, so we created a variable called “client_ID” and selected our client’s ID from our database using a MySQL query. We were able to retrieve the correct information by selecting the field client_ID where our username was equal to the username in our session variable (from when the user logs in). Also, note we put it outside of the if/else statement so we can use it later.
Finally, we used another MySQL query to insert the client ID and path into the database within the table “uploads.” Now all we have to do is redirect the user to the same page.
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
require('db.php'); // We havn't connected to the database yet, so we'll do it now.
$client_ID = mysql_query("SELECT client_ID
FROM clients
WHERE username='".$_SESSION['username']."'");
mysql_query("INSERT INTO uploads(ID, URL) VALUES ('$client_ID', '$target_path')");
header( 'Location: documents.php' ) ;
} else{
echo "There was an error uploading the file, please try again!";
}
Be sure to test it out by trying to upload a file. To check if it worked, viewing the database and then the uploads folder.
Securing the Code
To begin, let’s think about our structure. For this portion, we’re just going to check the file type and size. It may be necessary for other users of the tutorial to look into further methods of security.
After identifying what we need to check, we have to identify our problem: We have to check the file type and file size, but if there is something wrong with either one of them, we can’t let the script input any data. To solve this problem, let’s use another simple if/else statement:
if(The file is not of the right type or of the right size){
Then display an error message.
else{Or else we can go ahead with the rest of the script that we've already written.}
Simple enough, right? Now we just need to put it into action.
if((!$_FILES["file"]["type"] == "image/gif") ||(!$_FILES["uploadedfile"]["type"] == "image/png") ||(!$_FILES["uploadedfile"]["type"] == "image/jpeg") // "jpeg" for Firefox ||(!$_FILES["uploadedfile"]["type"] == "image/pjpeg") // "jpeg" for IE ||(!$_FILES["uploadedfile"]["type"] == "text/css") ||(!$_FILES["uploadedfile"]["type"] == "text/html") ||(!$_FILES["uploadedfile"]["type"] == "text/javascript") ||(!$_FILES["uploadedfile"]["type"] == "application/msword") ||(!$_FILES["uploadedfile"]["type"] == "application/pdf") &&(!$_FILES["file"]["size"] < 100000)){ echo "The file is not of the right type or size. It should be a .gif, .png, .jpeg/.jpg, .css, .html, .javascript, .doc, or .pdf and under 100kb."; echo "/n If you need to send me a file different from these specification, feel free to email it to me at you@domain.com. These specifications are for the website's safety."; }else{}
Before doing the rest, let’s take a closer look at what we did for the basic “if” part of the if/else statement. For ease of use, it is in orange. In our $_FILES associative array, “$_FILES["uploadedfile"]["type"]” gives us our MIME type for the file type we’ve uploaded. A MIME type is basically a way of telling a browser what kind of file we’re dealing with. You can get a list of available Window’s MIME types here. By checking to see if the file type of our given file ($_FILES["uploadedfile"]["type"]) is equal to (==) our wanted MIME type (eg. image/png) we can specify what files we want to include.
Note that there is an exclamation point before each comparison (!). This is because we are checking to see if it’s NOT this MIME type. If it’s not, then the client has uploaded the wrong type of file. In addition, “||” means “or” and “&&” means “and”. So what we’re saying in this conditional is: “If our file type is not equal to gif, or png, or jpg, or jpeg, or pjpeg, or css, or html, or javascript, or msword, or pdf, AND it is not under the file size we need, then they have uploaded a bad file and we will display that message. The message is in blue to differentiate the code.
Also note that this isn’t the most efficient way to do this, considering how many file types we are allowing. A better way would be to store the allowed MIME types in an array, and go through the array when comparing the current file. I’ve done it this way above for simplicity since I realize most readers of this tutorial are fairly new to PHP. It would be smart (and good practice) to find ways to make this code more efficient. In other cases though, if we would only want to include a few file types, this way of coding would be completely fine.
Next, we’ll include the “else” portion, which is just going to be our code that inserts our document’s data into our new table.
if((!$_FILES["file"]["type"] == "image/gif")
||(!$_FILES["uploadedfile"]["type"] == "image/png")
||(!$_FILES["uploadedfile"]["type"] == "image/jpeg") // "jpeg" for Firefox
||(!$_FILES["uploadedfile"]["type"] == "image/pjpeg") // "jpeg" for IE
||(!$_FILES["uploadedfile"]["type"] == "text/css")
||(!$_FILES["uploadedfile"]["type"] == "text/html")
||(!$_FILES["uploadedfile"]["type"] == "text/javascript")
||(!$_FILES["uploadedfile"]["type"] == "application/msword")
||(!$_FILES["uploadedfile"]["type"] == "application/pdf")
&&(!$_FILES["file"]["size"] < 100000){
echo "The file is not of the right type or size. It should be a
.gif, .png, .jpeg/.jpg, .css, .html, .javascript, .doc, or .pdf and under 100kb.";
echo "/n If you need to send me a file different from these specification, feel free to
email it to me at you@domain.com. These specifications are for the website's safety.";
}else{
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
mysql_query("INSERT INTO uploads(ID, URL) VALUES ('$client_ID', '$target_path')");
} else{
echo "There was an error uploading the file, please try again!";
}
}
Check to Make Sure We’ve Uploaded a File
Since we’re going to be loading this code every time the client accesses the page, it wouldn’t be smart to run the code for uploading a document unless the client did indeed try to upload a document. So, around our upload code, we can add a simple if statement making sure our $_FILES associative array is not empty. If it is empty it will ignore the code, and move onto the rest of the page.
if(!empty($_FILES)){ // Add the original filename to our target path. // Result is "uploads/filename.extension" $target_path = $target_path . basename( $_FILES['uploadedfile']['name']); if((!$_FILES["file"]["type"] == "image/gif") ||(!$_FILES["uploadedfile"]["type"] == "image/png") ||(!$_FILES["uploadedfile"]["type"] == "image/jpeg") // "jpeg" for Firefox ||(!$_FILES["uploadedfile"]["type"] == "image/pjpeg") // "jpeg" for IE ||(!$_FILES["uploadedfile"]["type"] == "text/css") ||(!$_FILES["uploadedfile"]["type"] == "text/html") ||(!$_FILES["uploadedfile"]["type"] == "text/javascript") ||(!$_FILES["uploadedfile"]["type"] == "application/msword") ||(!$_FILES["uploadedfile"]["type"] == "application/pdf") &&(!$_FILES["file"]["size"] < 100000){ echo "The file is not of the right type or size. It should be a .gif, .png, .jpeg/.jpg, .css, .html, .javascript, .doc, or .pdf and under 100kb."; echo "/n If you need to send me a file different from these specification, feel free to email it to me at you@domain.com. These specifications are for the website's safety." }else{ if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { mysql_query("INSERT INTO uploads(ID, URL) VALUES ('$client_ID', '$target_path')"); } else{ echo "There was an error uploading the file, please try again!"; } } }
Display the Client’s Documents
Throughout the next few steps, we’ll be actually displaying the client’s uploaded documents, and allowing them to download them as needed.
Display the Files
In order to display the files, every time the documents.php page is loaded it should check to see if there are any files in our uploads table with the same ID as our logged in client’s ID. If there is, we can use a loop to display all of them. In addition, we can use basic HTML to format this.
$getDocuments = mysql_query("SELECT * FROM uploads WHERE ID='".$client_ID."'");
while($row = mysql_fetch_array($getDocuments, MYSQL_ASSOC))
{
echo "File URL: " . $row['URL'];
}
What we did first was use a MySQL query to select all from the uploads folder where “ID” was equal to our $client_ID variable (defined earlier in the script). Then, we went through a while loop. Remember, the mysql_fetch_array creates an associative array we can work with from our $getDocuments variable. By assigning this function to the variable $row, it will put each row of the array into this variable as we go through that while loop. At each iteration through the loop, we are simply displaying the file’s URL.
Download Files
To download the file, we just need to link it to it’s original source. We have the original source as the path name, so with a mix of HTML and our PHP, we can create a successful download link.
<a href="document.doc">document.doc</a>
Above is the plain HTML way to create a download link. Let’s see how we can integrate PHP to dynamically pull all the download links needed:
$getDocuments = mysql_query("SELECT * FROM uploads WHERE ID='$client_ID'");
while($row = mysql_fetch_array($getDocuments, MYSQL_ASSOC))
{
echo "Download: <a href='" . $row['URL'] . "'>" . $row['URL'] . "</a>";
}
Our Final Script
<?php
session_start();
if(!isset($_SESSION['username'])){
header( 'Location: loginform.html' );
}
require('db.php'); // Connect to the database since we'll be needing it later.
// Where the file is going to be placed
$target_path = "uploads/";
$client_ID = mysql_query("SELECT 'client_ID'
FROM 'clients'
WHERE username='".$_SESSION['username']."'");
if(!empty($_FILES)){
// Add the original filename to our target path.
// Result is "uploads/filename.extension"
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);
if((!$_FILES["uploadedfile"]["type"] == "image/gif")
||(!$_FILES["uploadedfile"]["type"] == "image/png")
||(!$_FILES["uploadedfile"]["type"] == "image/jpeg") // "jpeg" for Firefox
||(!$_FILES["uploadedfile"]["type"] == "image/pjpeg") // "jpeg" for IE
||(!$_FILES["uploadedfile"]["type"] == "text/css")
||(!$_FILES["uploadedfile"]["type"] == "text/html")
||(!$_FILES["uploadedfile"]["type"] == "text/javascript")
||(!$_FILES["uploadedfile"]["type"] == "application/msword")
||(!$_FILES["uploadedfile"]["type"] == "application/pdf")
&&(!$_FILES["file"]["size"] < 100000)){
echo "The file is not of the right type or size. It should be a
.gif, .png, .jpeg/.jpg, .css, .html, .javascript, .doc, or .pdf and under 100kb.";
echo "
If you need to send me a file different from these specification, feel free to
email it to me at you@domain.com. These specifications are for the website's safety.";
}else{
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
mysql_query("INSERT INTO uploads(ID, URL) VALUES ('$client_ID', '$target_path')");
} else{
echo "There was an error uploading the file, please try again!";
}
}
}
// Displays all current files
$getDocuments = mysql_query("SELECT * FROM uploads WHERE ID='".$client_ID."'");
while($row = mysql_fetch_array($getDocuments, MYSQL_ASSOC))
{
echo "Download: <a href='" . $row['URL'] . "'>" . $row['URL'] . "</a><br />";
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Client Documents</title>
</head>
<body>
<form enctype='multipart/form-data' action='documents.php' method='POST'>
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
Choose a file to upload: <input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
</body>
</html>
* This final script should be a correct version that works. I had some confusion when fixing minor errors throughout the script in the end, so if anything doesn’t match from this version and any of the code above, please let me know in the comments!
Wrapping Up
We now have a basic uploading script and a way to manage documents on the client’s end. This seems a bit unnecessary though — but don’t worry — the admin area is coming soon, and then the admin (you) and the client will be able to seamlessly share documents back and forth.
Instead of making the admin area next, though, we’ll be finishing everything up from the client’s perspective, so we can better plan and create the admin area once we get around to it. Next time, we’ll create a very simple message board structure, or “note board” if you will, where both you and the client can post notes to each other, communicating back and forth without the hassle of email.

2447
3778
Get Updates by Email







Dzinepress
August 8th, 2009 at 04:41 amthat’s really stuff you sharing here Kayla. thanks
Nick
August 9th, 2009 at 11:41 amTerrific tutorial, Kayla! It’s easy to understand, plus I love the fact that what I’m learning in these tutorials has so much practical use for designers like me who would like to set up a client area in their portfolio. Thanks- I can’t wait for the next one!
Justin
August 10th, 2009 at 01:10 amThanks again Kayla! I cant wait for the final tutorial to come out, so I can use it on my own website for a client portfolio. Once again, great work!
John
August 10th, 2009 at 06:08 amAnother nice tutorial!
I would reccomend placing “Exit();” after using the header location function though!
unicendatte
August 18th, 2009 at 03:54 pmyeh right.. great post, Thank You
jez
August 21st, 2009 at 04:53 pmParts 1 & 2 are missing…hope to see them up soon..?
create-a-portfolio-client-area-using-php-and-mysql-part-
arriane
September 30th, 2009 at 08:35 amhi there! your tutorials are great!i just want to ask if its output is like facebook profile?i need it badly for my project.its like the user logs in and he/she can view,edit his/her profile.up;oad primary photo too. thank you so much!
taufik
May 30th, 2010 at 12:15 amsmall but powerfull….best for newbie. thanks so much..
KK
September 28th, 2010 at 01:35 amIt was nice tutorial will be adding same to my site soon !!
However couple of question
* do we need to provide the login // Pass to client ?
* Separate folder get created where files are uploaded for each client ?
Rob Macintosh
January 6th, 2011 at 03:47 pmGreat tutorials – i’m building a robust clients area using this as a basis – Thanks!
Dee
February 6th, 2011 at 02:05 amHey, Im having a issue with documents.php… I dont think that queries are correct. the ID in uploads table is zero for all urls. Therefore every client can see every upload. Can you or anyone please help me with this ? Thanks in advance.
euan
February 7th, 2011 at 05:27 pmHey,thanks for this tutorial. Found it really useful, however I’m a total noob at this and i’m struggling to get the database up and running at the db.php file stage. I’m not too sure where I find my database information as mine is on my server. Sorry, I know this is probably really basic, stuff but i’mstill new to this! Any suggestions?
Thanks
Euan
euan
February 8th, 2011 at 07:35 amHi there,
Should have added to the query above, this is the sign up form i’m struggling with…
http://megmackayphoto.com/V2/V2/signupform.html
Any help would be massively appreciated.
thanks
Euan
Eldiavolo
March 8th, 2011 at 07:20 pmVery useful tutorial, five star…
Vikx
April 28th, 2011 at 02:51 amJUST AMAZING.
Thank you. thank you.
kyriakos
May 8th, 2011 at 04:34 amThank you Kayla, it is a nice and useful tutorial.
I ‘d like to suggest a small change in your code, where you get client’s id from the database.
Instead of:
$client_ID = mysql_query(“SELECT ‘client_ID’ FROM ‘clients’ WHERE username=’”.$_SESSION['username'].”‘”);
use:
$result = mysql_query(“SELECT client_ID FROM clients WHERE username = ‘”.$_SESSION['username'].”‘”);
$client_ID = mysql_result($result, 0, ‘client_ID’);
Through this you get the ID otherwise you get something different that is not the client’s ID.
Tuesday
September 26th, 2011 at 06:52 pmMe and this aticrle, sitting in a tree, L-E-A-R-N-I-N-G!