We're going to be performing the same file handling operations multiple time, so we should take advantage of encapsulation and create a separate script for dealing with our file handling needs for our Student Listing application.
However, before we do that, we have some constant values we plan on using again, it's a good idea to create a file to hold these as constants as well:
Now let's create a script called studentimagefileutil.php with functions that will validate an uploaded student image file, move it from the temporary location to the images/ folder if there are no errors, and remove a student image file:
<?phprequire_once'studentlistingfileconstants.php';/** * Purpose: Validates an uploaded student image file * * Description: Validates an uploaded student image file is not greater than SL_MAX_FIE (1/2 MB), * and is either a jpg or png image type, and has no errors. If the image file * validates to these constraints, an error message containing an empty string is * returned. If there is an error, a string containing constraints the file failed * to validate to are returned. * * @return string Empty if validation is successful, otherwise error string containing * constraints the image file failed to validate to. */functionvalidateStudentImageFile(){$error_message="";// Check for $_FILES being set and no errors.if(isset($_FILES)&&$_FILES['student_image_file']['error']==UPLOAD_ERR_OK){// Check for uploaded file < Max file size AND an acceptable image typeif($_FILES['student_image_file']['size']>SL_MAX_FILE_SIZE){$error_message="The student file image must be less than ".SL_MAX_FILE_SIZE." Bytes";}$image_type=$_FILES['student_image_file']['type'];if($image_type!='image/jpg'&&$image_type!='image/jpeg'&&$image_type!='image/pjpeg'&&$image_type!='image/png'&&$image_type!='image/gif'){if(empty($error_message)){$error_message="The student file image must be of type jpg, png, or gif.";}else{$error_message.=", and be an image of type jpg, png, or gif.";}}}elseif(isset($_FILES)&&$_FILES['student_image_file']['error']!=UPLOAD_ERR_NO_FILE&&$_FILES['student_image_file']['error']!=UPLOAD_ERR_OK){$error_message="Error uploading student image file.";}return$error_message;}/** * Purpose: Moves an uploaded student image file to the SL_UPLOAD_PATH (images/) folder and * return the path location. * * Description: Moves an uploaded student image file from the temporary server location to the * SL_UPLOAD_PATH (images/) folder IF a student image file was uploaded and returns * the path location of the uploaded file by appending the file name to the * SL_UPLOAD_PATH (e.g. images/student_image.png). IF a student image file was NOT * uploaded, an empty string will be returned for the path. * * @return string Path to student image file IF a file was uploaded AND moved to the SL_UPLOAD_PATH * (images/) folder, otherwise and empty string. */functionaddStudentImageFileReturnPathLocation(){$student_file_path="";// Check for $_FILES being set and no errors.if(isset($_FILES)&&$_FILES['student_image_file']['error']==UPLOAD_ERR_OK){$student_file_path=SL_UPLOAD_PATH.$_FILES['student_image_file']['name'];if(!move_uploaded_file($_FILES['student_image_file']['tmp_name'],$student_file_path)){$student_file_path="";}}return$student_file_path;}/** * Purpose: Removes a file given a path to that file. * * Description: Removes the file referenced by $student_file_path. Supresses error * if file cannot be removed. * * @param $student_file_path */functionremoveStudentImageFile($student_file_path){@unlink($student_file_path);}
Modifications to addstudent.php
Modify the Form to Allow Uploads
In order to allow file upload capabilities, we need to make a couple of modifications to our form. Let's head back over to the lecture notes to discuss this.
Make the following modifications to the Add a Student form to allow a user to upload an image file:
addstudent.php - Add Student: Add File Upload Capability to Form
After the user submits the form data by selecting the Add Student button , the form data is available within the if block checking to see if the form data is set in the $_POST superglobal variable:
We want to validate the file inside this if block, moving it to the images/ folder, and save the path to the database table. Make the following modifications to addstudent.php:
if(isset($_POST['add_student_submission'],$_POST['student_first_name'],$_POST['student_last_name'],$_POST['student_email'])){require_once('dbconnection.php');require_once('studentimagefileutil.php');$student_first_name=$_POST['student_first_name'];$student_last_name=$_POST['student_last_name'];$student_email=$_POST['student_email'];/* Here is where we will deal with the file by calling validateStudentImageFile(). This function will validate that the student image file is not greater than 128 characters, is the right image type (jpg/png/gif), and not greater than 512KB. This function will return an empty string ('') if the file validates successfully, otherwise, the string will contain error text to be output to the web page before redisplaying the form. */$file_error_message=validateStudentImageFile();if(empty($file_error_message)){$dbc=mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME)ortrigger_error('Error connecting to MySQL server for'.DB_NAME,E_USER_ERROR);$student_image_file_path=addStudentImageFileReturnPathLocation();$query="INSERT INTO studentListing (first_name, last_name, email, image_file) "." VALUES ('$student_first_name', '$student_last_name', "."'$student_email', '$student_image_file_path')";mysqli_query($dbc,$query)ortrigger_error('Error querying database studentListing: Failed to insert student data',E_USER_ERROR);$display_add_student_form=false;?> <h3 class="text-info">The Following Student Details were Added:</h3><br/> <h1><?="$student_first_name$student_last_name"?></h1> <div class="row"> <div class="col-2"> <img src="<?=$student_image_file_path?>" class="img-thumbnail" style="max-height: 200px;" alt="Student image"> </div> <div class="col"> <table class="table table-striped"> <tbody> <tr> <th scope="row">First Name</th> <td><?=$student_first_name?></td> </tr> <tr> <th scope="row">Last Name</th> <td><?=$student_last_name?></td> </tr> <tr> <th scope="row">Email</th> <td><?=$student_email?></td> </tr> </tbody> </table> </div> </div> <hr/> <p>Would you like to <a href='<?=$_SERVER['PHP_SELF']?>'> add another student</a>?</p><?php}else{// echo error messageecho"<h5><p class='text-danger'>".$file_error_message."</p></h5>";}}
Finally, we want to make the form fields sticky in case there is an error (as you see handled in the else case above), and the user needs to resubmit the form because of a file upload error. Make the following modifications to the form in addstudent.php:
First add variables for the fields we want to make sticky and set them to empty strings:
addstudent.php - Add Student: Make Form Fields sticky - add variables
1 2 3 4 5 6 7 8 9101112
<hr/><?php$display_add_student_form=true;$student_first_name="";$student_last_name="";$student_email="";// pro-tip: you can test multiple variables within a single isset() callif(isset($_POST['add_student_submission'],$_POST['student_first_name'],$_POST['student_last_name'],$_POST['student_email'])){
addstudent.php - Add Student: Make Form Fields sticky - add variables to value attribute
<!DOCTYPE html><html> <head> <title>Add Student</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous"> </head> <body> <div class="card"> <div class="card-body"> <h1>Add a Student</h1> <nav class="nav"> <a class="nav-link" href="index.php">Students</a> </nav> <hr/><?php$display_add_student_form=true;$student_first_name="";$student_last_name="";$student_email="";// pro-tip: you can test multiple variables within a single isset() callif(isset($_POST['add_student_submission'],$_POST['student_first_name'],$_POST['student_last_name'],$_POST['student_email'])){require_once('dbconnection.php');require_once('studentimagefileutil.php');$student_first_name=$_POST['student_first_name'];$student_last_name=$_POST['student_last_name'];$student_email=$_POST['student_email'];/* Here is where we will deal with the file by calling validateStudentImageFile(). This function will validate that the student image file is not greater than 128 characters, is the right image type (jpg/png/gif), and not greater than 512KB. This function will return an empty string ('') if the file validates successfully, otherwise, the string will contain error text to be output to the web page before redisplaying the form. */$file_error_message=validateStudentImageFile();if(empty($file_error_message)){$dbc=mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME)ortrigger_error('Error connecting to MySQL server for'.DB_NAME,E_USER_ERROR);$student_image_file_path=addStudentImageFileReturnPathLocation();$query="INSERT INTO studentListing (first_name, last_name, email, image_file) "." VALUES ('$student_first_name', '$student_last_name', "."'$student_email', '$student_image_file_path')";mysqli_query($dbc,$query)ortrigger_error('Error querying database studentListing: Failed to insert student data',E_USER_ERROR);$display_add_student_form=false;?> <h3 class="text-info">The Following Student Details were Added:</h3><br/> <h1><?="$student_first_name$student_last_name"?></h1> <div class="row"> <div class="col-2"> <img src="<?=$student_image_file_path?>" class="img-thumbnail" style="max-height: 200px;" alt="Student image"> </div> <div class="col"> <table class="table table-striped"> <tbody> <tr> <th scope="row">First Name</th> <td><?=$student_first_name?></td> </tr> <tr> <th scope="row">Last Name</th> <td><?=$student_last_name?></td> </tr> <tr> <th scope="row">Email</th> <td><?=$student_email?></td> </tr> </tbody> </table> </div> </div> <hr/> <p>Would you like to <a href='<?=$_SERVER['PHP_SELF']?>'> add another student</a>?</p><?php}else{// echo error messageecho"<h5><p class='text-danger'>".$file_error_message."</p></h5>";}}if($display_add_student_form){?> <form enctype="multipart/form-data" class="needs-validation" novalidate method="POST" action="<?=$_SERVER['PHP_SELF']?>"> <div class="form-group row"> <label for="student_first_name" class="col-sm-3 col-form-label-lg">First Name</label> <div class="col-sm-8"> <input type="text" class="form-control" id="student_first_name" name="student_first_name" value= '<?=$student_first_name?>' placeholder="First Name" required> <div class="invalid-feedback"> Please provide a valid first name. </div> </div> </div> <div class="form-group row"> <label for="student_last_name" class="col-sm-3 col-form-label-lg">Last Name</label> <div class="col-sm-8"> <input type="text" class="form-control" id="student_last_name" name="student_last_name" value= '<?=$student_last_name?>' placeholder="Last Name" required> <div class="invalid-feedback"> Please provide a valid last name. </div> </div> </div> <div class="form-group row"> <label for="student_email" class="col-sm-3 col-form-label-lg">Email</label> <div class="col-sm-8"> <input type="email" class="form-control" id="student_email" name="student_email" value= '<?=$student_email?>' placeholder="Email" required> <div class="invalid-feedback"> Please provide a valid email address. </div> </div> </div> <div class="form-group row"> <label for="student_image_file" class="col-sm-3 col-form-label-lg"> Student Image File</label> <div class="col-sm-8"> <input type="file" class="form-control-file" id="student_image_file" name="student_image_file"> </div> </div> <button class="btn btn-primary" type="submit" name="add_student_submission">Add Student</button> </form> <script> // JavaScript for disabling form submissions if there are invalid fields (function() { 'use strict'; window.addEventListener('load', function() { // Fetch all the forms we want to apply custom Bootstrap validation styles to var forms = document.getElementsByClassName('needs-validation'); // Loop over them and prevent submission var validation = Array.prototype.filter.call(forms, function(form) { form.addEventListener('submit', function(event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }); }, false); })(); </script><?php}// Display add student form?> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script> </body></html>