Handling Files for a Project Management Application

In this article we will be discussing how to handle the files that a project needs. We will also be looking at how to upload files using standard PHP functions. This article is the sixth part of a seven-part tutorial that explains how to build a project management application. Be sure to check out the other articles in the series.

The first script that we will discuss is the view_files.php script. This script will be responsible for listing all the files that are used in a given project. When a user uploads a file, the name of the file and project id are stored in the database. The physical file is stored in a folder called ‘p_files’.



Below is the entire code that makes up this script:


<?php

include "dbcon.php";

include "functions.php";


if(isset($_GET['pid'])){

//clean pid

if(!is_numeric($_GET['pid'])){

//the value received is not numeric. redirect the user to login

header("location:login.php");

}


//otherwise clean the received value for query use


$cpid = mysql_escape_string($_GET['pid']);


//get project name


$getname = "SELECT title FROM projects WHERE pid = ‘".$cpid."’";

$g_result = mysql_query($getname);

if(!$g_result){

echo mysql_error()

}else{

$rowname = mysql_fetch_assoc($g_result);

$title = $row['title'];

}

//get the files

$getfiles="SELECT * FROM files WHERE p_id = ‘".$cpid."’ ORDER BY fid";

$result = mysql_query($getfiles);

if(!$result){

echo mysql_error();

}else{

$num=mysql_num_rows($result);

}


?>

<!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"><!– InstanceBegin template="/Templates/PM_Main.dwt.php" codeOutsideHTMLIsLocked="false" –>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<!– InstanceBeginEditable name="doctitle" –>

<title>Untitled Document</title>

<!– InstanceEndEditable –>

<!– InstanceBeginEditable name="head" –><!– InstanceEndEditable –>

<link href="Templates/main.css" rel="stylesheet" type="text/css" />

</head>


<body>

<table width="100%" border="0">

<tr>

<td width="33%">&nbsp;</td>

<td width="28%">&nbsp;</td>

<td width="39%">Logged in: <!– InstanceBeginEditable name="login" –><? echo $_SESSION['name'];?> | <a href="logout.php">Logout</a><!– InstanceEndEditable –></td>

</tr>

<tr>

<td colspan="3" bgcolor="#6699CC" class="headertxt">Project Management Software </td>

</tr>

<tr>

<td colspan="3"><!– InstanceBeginEditable name="main" –>

<table width="99%" border="0">

<tr>

<td colspan="2" class="loginheader"><?php echo $title;?> </td>

</tr>

<tr>

<td>Files used by this project: </td>

<td>&nbsp;</td>

</tr>

<tr>

<td>&nbsp;</td>

<td>&nbsp;</td>

</tr>

<tr>

<td><strong>File Name</strong></td>

<td><strong>Action</strong></td>

</tr>

<?php

if($num > 0){

while($row = mysql_fetch_assoc($result)){?>

<tr>

<td><?php echo $row['filename']?> </td>

<td><a href="delete_file.php?fid=<?php echo $row['fid']?> & cpid=<?php echo $cpid?> ">Delete</a></td>

</tr>

<?php

}

}else{

?>

<tr>

<td colspan="2"><p>There are no files uploaded for this project.</p></td>

</tr>

<?php }

 

?>

</table>

<!– InstanceEndEditable –></td>

</tr>

<tr>

<td colspan="3"><!– InstanceBeginEditable name="nav" –><a href="main.php">View Project List</a> | <a href="admin/login.php">Administrators Corner </a><!– InstanceEndEditable –></td>

</tr>

<tr>

<td align="right" class="cright" colspan="3">copyright &copy; 2007 PM </td>

</tr>

</table>

</body>

<!– InstanceEnd –></html>


{mospagebreak title=Script Explained}

Since the script simply displays the name of the files, it is a matter of running a query and listing the returned names in a HTML table. This is more or less what the script does in the code below:


<?php

include "dbcon.php";

include "functions.php";


The code checks to see if the received project id is actually a number. If it is not, the user is redirected to the login page. The project id is tested with the ‘is_numeric()’ function, but a regex pattern checking function will do just as well:


if(isset($_GET['pid'])){

//clean pid

if(!is_numeric($_GET['pid'])){

//the value received is not numeric. redirect the user to login

header("location:login.php");

}


If the project id is indeed a number, it is then cleaned and used in a query:


//otherwise clean the received value for query use

$cpid = mysql_escape_string($_GET['pid']);

//get project name


The first query that is run, is to retrieve the title of the project for which you want to view the files. So the project id is used to retrieve that specific project’s details and if the title is found, it is then stored in a variable called $title:


$getname = "SELECT title FROM projects WHERE pid = ‘".$cpid."’";

$g_result = mysql_query($getname);

if(!$g_result){

echo mysql_error()

}else{

$rowname = mysql_fetch_assoc($g_result);

$title = $row['title'];

}


The project id is used again to retrieve a list of files that belong to this project:


//get the files

$getfiles="SELECT * FROM files WHERE p_id = ‘".$cpid."’ ORDER BY fid";

$result = mysql_query($getfiles);

if(!$result){

echo mysql_error();

}else{


The number of rows that have been returned are stored in the $num variable:


$num=mysql_num_rows($result);

}


?>


In the HTML below, the $num variable is going to be used to create a dynamic table. This table will list all the files of this project, and give the user the option to remove the files. This will be done dynamically based on the number of rows returned in the query above:


<!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"><!– InstanceBegin template="/Templates/PM_Main.dwt.php" codeOutsideHTMLIsLocked="false" –>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<!– InstanceBeginEditable name="doctitle" –>

<title>Untitled Document</title>

<!– InstanceEndEditable –>

<!– InstanceBeginEditable name="head" –><!– InstanceEndEditable –>

<link href="Templates/main.css" rel="stylesheet" type="text/css" />

</head>


<body>

<table width="100%" border="0">

<tr>

<td width="33%">&nbsp;</td>

<td width="28%">&nbsp;</td>

<td width="39%">Logged in: <!– InstanceBeginEditable name="login" –><? echo $_SESSION['name'];?> | <a href="logout.php">Logout</a><!– InstanceEndEditable –></td>

</tr>

<tr>

<td colspan="3" bgcolor="#6699CC" class="headertxt">Project Management Software </td>

</tr>

<tr>

<td colspan="3"><!– InstanceBeginEditable name="main" –>

<table width="99%" border="0">

<tr>

<td colspan="2" class="loginheader"><?php echo $title;?> </td>

</tr>


The main headers for this table are written first, and then the dynamic rows are created:


<tr>

<td>Files used by this project: </td>

<td>&nbsp;</td>

</tr>

<tr>

<td>&nbsp;</td>

<td>&nbsp;</td>

</tr>

<tr>

<td><strong>File Name</strong></td>

<td><strong>Action</strong></td>

</tr>

 


PHP checks to see if the $num variable is greater than zero. If it is, then it will determine how many dynamic rows are going to be created. At the same time, a while() loop will be started to retrieve all the results from the query and display them until the loop ends:

 

<?php

if($num > 0){

while($row = mysql_fetch_assoc($result)){?>

<tr>

<td><?php echo $row['filename']?> </td>

<td><a href="delete_file.php?fid=<?php echo $row['fid']?> & cpid=<?php echo $cpid?> ">Delete</a></td>

</tr>

<?php

}

 

If the $num variable contains a value that is less than one, then the message below is displayed:


}else{

?>

<tr>

<td colspan="2"><p>There are no files uploaded for this project.</p></td>

</tr>

<?php }

 

?>

</table>

<!– InstanceEndEditable –></td>

</tr>

<tr>

<td colspan="3"><!– InstanceBeginEditable name="nav" –><a href="main.php">View Project List</a> | <a href="admin/login.php">Administrators Corner </a><!– InstanceEndEditable –></td>

</tr>

<tr>

<td align="right" class="cright" colspan="3">copyright &copy; 2007 PM </td>

</tr>

</table>

</body>

<!– InstanceEnd –></html>



There are two headers presented to the user by this form. One is the file name and the other is "action." Under the action header, the option to delete the file is presented, with a link to the delete_file.php file. The code for this file is below:



<?php

include "dbcon.php";

include "functions.php";

$remove = "DELETE FROM files WHERE fid = ‘".$_GET['fid']."’";

mysql_query($remove);

header("localtion:view_files.php?pid=".$_GET['cpid']."");


?>


The query removes the file name from the files database table, using the fid (file id) that is sent over from the "view_files" script.


{mospagebreak title=The add_file script}


The next script that we will be looking at is the add_file script. It is responsible for adding files to a project. The page consists of a form that provides a file field. This is a special field that is specifically designed for uploading files. The form also has one additional attribute, as you will see in the HTML section of the page. Below is a screen shot of the form and also the code that built the script:



And the code for the page:


<?php

include "dbcon.php";

include "functions.php";




if(isset($_GET['pid'])){


//clean pid

if(!is_numeric($_GET['pid'])){

//the value received is not numeric. redirect the user to login

header("location:login.php");

}

//otherwise clean the received value for query use

$cpid = mysql_escape_string($_GET['pid']);

$getname = "SELECT title FROM projects WHERE pid = ‘".$cpid."’";

$g_result = mysql_query($getname);

if(!$g_result){

echo mysql_error();

}else{

$rowname = mysql_fetch_assoc($g_result);

$title = $row['title'];

}


}//end pid check


if(isset($_POST['submit'])){

//check vars

if(!$_FILES['userfile']['name']) {

$err = true;

$msg .= "<BR>Please upload a image file.";

}

$fname=mysql_escape_string($_FILES['userfile']['name']);

$p_pid=mysql_escape_string($_POST['p_pid']);


//insert

if(!$err){

$insert = "INSERT INTO files SET filename = ‘".$fname."’,";

$insert .= "p_id= ‘".$p_pid."’";

if(!mysql_query($insert)){

echo mysql_error();

}else{

$newid=mysql_insert_id();

$msg= "Data inserted.".$p_pid."<br>";

}

}//err check




//upload file

if($new_id > 0){

$uploadpath = "p_files/";

$filename = trim(addslashes($_FILES['userfile']['name']));

if(move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadpath . $filename)) {

$msg .= "File uploaded.".$filename."";

 

}else{

$msg .= "File not uploaded.";

 

}

}


}

?>


<!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"><!– InstanceBegin template="/Templates/PM_Main.dwt.php" codeOutsideHTMLIsLocked="false" –>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<!– InstanceBeginEditable name="doctitle" –>

<title>Untitled Document</title>

<!– InstanceEndEditable –>

<!– InstanceBeginEditable name="head" –>

<!– InstanceEndEditable –>

<link href="Templates/main.css" rel="stylesheet" type="text/css" />

</head>


<body>

<table width="100%" border="0">

<tr>

<td width="33%">&nbsp;</td>

<td width="28%">&nbsp;</td>

<td width="39%">Logged in: <!– InstanceBeginEditable name="login" –><? echo $_SESSION['name'];?> | <a href="logout.php">Logout</a><!– InstanceEndEditable –></td>

</tr>

<tr>

<td colspan="3" bgcolor="#6699CC" class="headertxt">Project Management Software </td>

</tr>

<tr>

<td colspan="3"><!– InstanceBeginEditable name="main" –>

<form id="form1" name="form1" method="post" action="add_file.php" enctype="multipart/form-data">

<table width="100%" border="0">

<tr>

<td colspan="2" class="loginheader"><?php echo $title;?></td>

</tr>

<tr>

<td colspan="2"><?php if(isset($msg)){

echo $msg;

}?> </td>

</tr>

<tr>

<td width="10%">File Name </td>

<td width="90%"><label>

<input name="userfile" type="file" id="userfile" />

<input type="hidden" name="p_pid" value="<?php echo $_GET['pid'];?>"/>

</label></td>

</tr>

<tr>

<td>&nbsp;</td>

<td><label>

<input type="submit" name="submit" value="Upload File" />

</label></td>

</tr>

</table>

</form>

<!– InstanceEndEditable –></td>

</tr>

<tr>

<td colspan="3"><!– InstanceBeginEditable name="nav" –><a href="main.php">View Project List</a> | <a href="admin/login.php">Administrators Corner </a><!– InstanceEndEditable –></td>

</tr>

<tr>

<td align="right" class="cright" colspan="3">copyright &copy; 2007 PM </td>

</tr>

</table>

</body>

<!– InstanceEnd –></html>



The code does a couple of familiar things. First it makes the usual checks to make sure that we don’t crash the application, then it retrieves the project name and stores it in a variable called $title:

<?php

include "dbcon.php";

include "functions.php";




if(isset($_GET['pid'])){


//clean pid

if(!is_numeric($_GET['pid'])){

//the value received is not numeric. redirect the user to login

header("location:login.php");

}

//otherwise clean the received value for query use

$cpid = mysql_escape_string($_GET['pid']);

$getname = "SELECT title FROM projects WHERE pid = ‘".$cpid."’";

$g_result = mysql_query($getname);

if(!$g_result){

echo mysql_error();

}else{

$rowname = mysql_fetch_assoc($g_result);

$title = $row['title'];

}


}//end pid check

{mospagebreak title=Form Explained}

PHP then checks to see if the form is submitted:


if(isset($_POST['submit'])){


Then the form variables are checked and escaped for use in the insert query:


//check vars

if(!$_FILES['userfile']['name']) {

$err = true;

$msg .= "<BR>Please upload a file.";

}


$fname=mysql_escape_string($_FILES['userfile']['name']);

$p_pid=mysql_escape_string($_POST['p_pid']);


Then the form values are inserted into the files table:


//insert

if(!$err){

$insert = "INSERT INTO files SET filename = ‘".$fname."’,";

$insert .= "p_id= ‘".$p_pid."’";

if(!mysql_query($insert)){

echo mysql_error();

}else{


The next line stores the record id of the newly inserted record, and then a message is set in the $msg variable:


$newid=mysql_insert_id();

$msg= "Data inserted.".$p_pid."<br>";

}

}//err check



The code then checks to see if the $new_id variable value is greater then zero. If it is, the file upload process is started. The assumption is that, if the $new_id variable value is less then one, then the insert query was not successful and therefore the upload process will not be started:


//upload file

if($new_id > 0){

$uploadpath = "p_files/";

$filename = trim(addslashes($_FILES['userfile']['name']));

if(move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadpath . $filename)) {

$msg .= "File uploaded.".$filename."";

 

}else{

$msg .= "File not uploaded.";

 

}

}


}

?>


The $_FILES['userfile']['name'] variable is the special variable that is designed for file uploads (think of it as the file equivalent of $_POST). The $_FILE array has five elements, of which tmp_name is one. It refers to the temporary name of the file on the server. If you look closely at the upload code above you will see that I’ve used it there as well. The move_uploaded_file() function is also used in the code. This function, as the name suggests, does the work of moving the file from one place to another.

There are only two things that I think are worth pointing out in the HTML form below. First, if you look at the opening form element, you will notice that an additional attribute has been added. It is called:

enctype="multipart/form-data”

The above merely informs the browser to expects different types of data from the form. This piece of code needs to be there whenever you are going to upload a file. Second, the actual form field needs to be of type ‘file.’ This has the effect of creating a “browse” button when the form is shown. Both of these pieces of code are highlighted below:


<!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"><!– InstanceBegin template="/Templates/PM_Main.dwt.php" codeOutsideHTMLIsLocked="false" –>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<!– InstanceBeginEditable name="doctitle" –>

<title>Untitled Document</title>

<!– InstanceEndEditable –>

<!– InstanceBeginEditable name="head" –>

<!– InstanceEndEditable –>

<link href="Templates/main.css" rel="stylesheet" type="text/css" />

</head>


<body>

<table width="100%" border="0">

<tr>

<td width="33%">&nbsp;</td>

<td width="28%">&nbsp;</td>

<td width="39%">Logged in: <!– InstanceBeginEditable name="login" –><? echo $_SESSION['name'];?> | <a href="logout.php">Logout</a><!– InstanceEndEditable –></td>

</tr>

<tr>

<td colspan="3" bgcolor="#6699CC" class="headertxt">Project Management Software </td>

</tr>

<tr>

<td colspan="3"><!– InstanceBeginEditable name="main" –>

<form id="form1" name="form1" method="post" action="add_file.php" enctype="multipart/form-data">

<table width="100%" border="0">

<tr>

<td colspan="2" class="loginheader"><?php echo $title;?></td>

</tr>

<tr>

<td colspan="2"><?php if(isset($msg)){

echo $msg;

}?> </td>

</tr>

<tr>

<td width="10%">File Name </td>

<td width="90%"><label>

<input name="userfile" type="file" id="userfile" />

<input type="hidden" name="p_pid" value="<?php echo $_GET['pid'];?>"/>

</label></td>

</tr>

<tr>

<td>&nbsp;</td>

<td><label>

<input type="submit" name="submit" value="Upload File" />

</label></td>

</tr>

</table>

</form>

<!– InstanceEndEditable –></td>

</tr>

<tr>

<td colspan="3"><!– InstanceBeginEditable name="nav" –><a href="main.php">View Project List</a> | <a href="admin/login.php">Administrators Corner </a><!– InstanceEndEditable –></td>

</tr>

<tr>

<td align="right" class="cright" colspan="3">copyright &copy; 2007 PM </td>

</tr>

</table>

</body>

<!– InstanceEnd –></html>

Be sure to come back next week for the conclusion to this article series!

[gp-comments width="770" linklove="off" ]

chat