How do I change the assigned name of the uploaded file to match the id of user filling out the form?

Hi,

I've created a php form which uploads files to a location on my server.  In my form, I direct (formaction) to another php page which assigns the image a name based on the time then uploads it to the location in the server.

However, the file relates to a profile and I wanted to name the file accordingly so I can match the image in the folder location with the corresponding entry in the database.

I wanted to name the file after the id associated with the form (the record created on the previous page), so was trying somthing like -

$image_name = ($teacher['firstname']).".".$ext; 

Open in new window


(I had passed the id associated with the form created at the top of the page):

$id = isset($_GET['id']) ? $_GET['id'] : '1'; //not sure this is needed - just says if it's a get requirest assign it a value of 1?
$teacher = find_teacher_by_id($id);

Open in new window


And when directing to the page, I was passing the teacher id value using this...

<form action="'uploadpro.php?id=' . $teacher['id'];" enctype="multipart/form-data" class="form-horizontal" method="post">

Open in new window


But it doesn't work...

Firstly, when I add '?id=' . $teacher['id'];' to the end of the form, the form doesn't correctly display a preview of the image as it's supposed to.  And when I check the name of the file which has been uploaded, it has no name.

Is there anything obvious I am not doing correctly - is the idea wrong, or is it just how I've written the code? I've pasted the code below:

Page form2.php (this is the form page)
<?php

 require_once('private/initialize.php'); 
 include('header.php');
 $page_title = 'Orango Teacher'; 
 include('navbar.php');

 ?>
 
 <?php
$id = isset($_GET['id']) ? $_GET['id'] : '1'; //not sure this is needed - just says if it's a get requirest assign it a value of 1?
$teacher = find_teacher_by_id($id);

?>
    
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script> 
    <script src="http://malsup.github.com/jquery.form.js"></script> 
    <script> 
        $(document).ready(function() { 


         var progressbar     = $('.progress-bar');


            $(".upload-image").click(function(){
            	$(".form-horizontal").ajaxForm(
		{
		  target: '.preview',
		  beforeSend: function() {
			$(".progress").css("display","block");
			progressbar.width('0%');
			progressbar.text('0%');
                    },
		    uploadProgress: function (event, position, total, percentComplete) {
		        progressbar.width(percentComplete + '%');
		        progressbar.text(percentComplete + '%');
		     },
		})
		.submit();
            });


        }); 
    </script>
</head>
<body>
	
	
	
	
	<div class="container text-center">
	<br><br><br><br><br><br>
		<h2>Upload your Profile Photo <?php echo h($teacher['firstname']); ?></h2>
		<br>
		<div style="border: 1px solid #a1a1a1;text-align: center;width: 500px;padding:30px;margin:0px auto">
			<form action="uploadpro.php" enctype="multipart/form-data" class="form-horizontal" method="post">


				<div class="preview"></div>
				 <div class="progress" style="display:none">
				  <div class="progress-bar" role="progressbar" aria-valuenow="0"
				  aria-valuemin="0" aria-valuemax="100" style="width:0%">
				    0%
				  </div>
				</div>


				<input type="file" name="image" class="form-control" />
				<br>
				<button class="btn btn-primary upload-image">Upload Image</button>

				
			</form>
			
			<a href="<?php echo 'form3.php?id=' . $teacher['id'];?>" class="btn btn-info" role="button">Submit</a>
			
	
		
		</div>
	</div>
	
	
</body>
</html>

Open in new window



And this is the page I refer to within that page...
<?php

 require_once('private/initialize.php'); 
 include('header.php');
 $page_title = 'Orango Teacher'; 
 include('navbar.php');
 
 $id = isset($_GET['id']) ? $_GET['id'] : '1'; //not sure this is needed - just says if it's a get requirest assign it a value of 1?
$teacher = find_teacher_by_id($id);

	if(isset($_POST) && !empty($_FILES['image']['name'])){

		$name = $_FILES['image']['name'];

		list($txt, $ext) = explode(".", $name);

		$image_name = time().".".$ext;

		$tmp = $_FILES['image']['tmp_name'];

		if(move_uploaded_file($tmp, 'upload/'.$image_name)){

			mysqli_query($db_connection,"INSERT INTO items (title)

			VALUES ('".$image_name."')");

			echo "<img width='200px' src='upload/".$image_name."' class='preview'>";
			
			?>
			<br><br>
			<p> Yay! Image uploaded. If you're happy with the mini-preview press the blue submit button below </p>
			
<?php			

		}else{

			echo "image uploading failed";

		}

	}

?>
<br>

Open in new window


Many thanks.
AdamTrying to learn phpAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Julian HansenCommented:
Let's try and unravel this a bit.

You have a form (call it UploadForm). The purpose of this form is to upload a file to the server.
You want the uploaded file to be a combination of
a) The time
b) The id of the user

The id of the user is contained within the $teacher['id'] variable available on the UploadForm

You have tried adding the $teacher['id'] to the action for the UploadForm as a GET parameter - but you say this does not work.

What you did not say is does not work - how? In what way - is there an error - it does not give the expected results?

You should be able to do this (form2.php)
...
<form action="uploadpro.php?id=<?php echo $teacher['id']?>" enctype="multipart/form-data" class="form-horizontal" method="post">

Open in new window

And on the server side
$id = isset($_GET['id']) ? $_GET['id'] : false;
$teacher = find_teacher_by_id(id);
if ($teacher) {
   // This you will need to decide - if no ID is submitted how do you want to handle that
   // I am treating the id as mandatory so we only do the upload if it is present (Refer note below)
   $name = explode('.',$_FILES['image']['name']);
   $ext = $name[1] ? '.' . $name[1] : '';
   $filename = $teacher['name'] . $ext;
   move_uploaded_file($_FILES['image']['tmp_name'], $filename);
}
else {
  // handle teacher not found
}

Open in new window


You might also want to look at the security around passing the teacher id as part of the form. Form data is always suspect as it can be tampered with. If it is a risk if the id is tampered with then you should consider setting the teacher ID in the session so the server knows who it is dealing with.
1
AdamTrying to learn phpAuthor Commented:
Many thanks Julian.

I think the text in my form action wasn't correct (unnecessary single quotes) as I am now getting what I was hoping for after using your slightly different code.

The file now uploads to the correct location and also the name of the file is also as I want.

I also have created a string called '$photoid' to which I have assigned the full name of the file including the extension (i.e - user_pic_12348.jpg)   which I want to add to my table in a row corresponding to that field name.  

I have used the following to insert this into my table (teachers_table) in the column photoid:

global $db_connection;
$sql = "INSERT INTO teachers_table (photoid) VALUES ($photoid)";

Open in new window


I have defined the connection in another file.

However, when I upload my picture, $photoid isn't being entered into column photoid in my table(teachers_table). I echoed photo $photoid and it is reading as it should, but it is just not being entered into my table? Is there something wrong with my SQL, or is it because of other code on that php page which is interefering? I have pasted the full upload.pro php code below.

Many thanks, and will happily award points and close off and re-submit if that's the better way to do things.

Adam

<?php

 require_once('private/initialize.php'); 
 include('header.php');
 $page_title = 'Orango Teacher'; 
 include('navbar.php');
 
$id = isset($_GET['id']) ? $_GET['id'] : '1'; //not sure this is needed - just says if it's a get requirest assign it a value of 1?
$teacher = find_teacher_by_id($id);


//The list() function is used to assign values to a list of variables in one operation
//list(var1,var2...)

//The explode() function breaks a string into an array.
//explode(separator,string,limit)


	if(isset($_POST) && !empty($_FILES['image']['name'])){

		$name = $_FILES['image']['name'];

		list($txt, $ext) = explode(".", $name);

		$image_name = "user_pic_". $teacher['id'] .".". $ext;
		
		$photoid = "user_pic_". $teacher['id'] .".". $ext;
		
		
		
		$tmp = $_FILES['image']['tmp_name'];
		

		if(move_uploaded_file($tmp, 'upload/'.$image_name)){

		global $db_connection;
		$sql = "INSERT INTO teachers_table (photoid) VALUES ($photoid)";
			
			
			
			echo "<img width='200px' src='upload/".$image_name."' class='preview'>";
			echo "$photoid";
			?>
			<br><br>
			<p> Yay! Image uploaded. If you're happy with the mini-preview press the blue submit button below </p>
			
<?php			

		}else{

			echo "image uploading failed";

		}

	}

?>

Open in new window

0
Julian HansenCommented:
The problem is that photo_id is a string and you are inserting it raw into the table (i.e. now quotes around the string)
Line 37 needs to be
$sql = "INSERT INTO teachers_table (photoid) VALUES ('{$photoid}')";

Open in new window

Note the use of the '' around $photoid.
The { } are optional - they are used when inserting variables into strings to remove ambiguity around where the variable name ends and the rest of the string starts. I use them all the time - it makes it easier to see and ensures you won't ever end up with issues stemming from an unintended concatenation of a variable name to a part of a string.

Then the key thing - on line 37 you are building a query - but you never execute it.
Somewhere you need
mysqli_query($sql);

Open in new window

You might also want to look at using prepared statements for your insert
global $db_connection;
// NOTE NO QUOTES AND WE USE A ? PLACEHOLDER
$sql = "INSERT INTO teachers_table (photoid) VALUES (?)";
$statement = mysqli_prepare($db_connection, $sql);
if ($statement) {
  // HERE WE BIND OUR VARIABLES TO THE ?'s IN THE QUERY
  // "s" MEANS A SINGLE STRING VALUE. IF WE HAD A STRING
  // AND A NUMBER WE WOULD DO "sd". REFER TO THE DOCS
  // FOR MORE INFO
  mysqli_statement_bind_param($stmt, "s", $photoid);
  // EXECUTE THE QUERY
  mysqli_stmt_execute($stmt);
}

Open in new window

Prepared statements have a number of advantages. One main one being they are more secure against SQL injection attacks.

Then final bit of advice - I would wrap your entire process from line 21 in a try / catch block and implement a DB transaction around the process as well.

What does this mean?
try / catch - exception handling makes it much easier for you to bug out when you hit an error. The catch allows you to control how you deal with each condition without a nightmare of nested if statements. This would look something like
try {
   // start DB transaction
   // do your file move and insert code exactly as you have it
   // at any point in the process if you encounter an error you do this
   // throw new Exception('Failed to move file or some similar relevant message');
   ...
   // At the very end you commit the transaction
}
catch(Exception $e)
{
   // If you get here there was an error - you can see the message in $e->message
   // This also means that your process only partly finished - so you want to do some
   // clean up to make sure you don't end up with orphans
   // 1. Rollback your DB - this restores your database to the same state it was in
   //      before you started the transaction
   //  2. Remove the file (if required) in case the move worked and the INSERT failed
   // Handle / report the error
   // When we get here the state of the system will be as if the file upload did not happen.
}

Open in new window


More information can be found here
mysqli_prepare()
PHP Exceptions
PHP Transaction begin_transaction()
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

AdamTrying to learn phpAuthor Commented:
Hi Julian,

Many thanks for your detailed and informative response. Apologies for the delay in replying to this post.

Yes - I should have realised I had to execute the sql function which I had created. This together with the quotes and curly brackets in the INSERT line of code made the difference and I could see the information entered into the database.

I also tried using the prepared statement and that too worked - I'll look to read up on this a bit more and start to incorporate into my code.

With my code however, I realised I wanted to insert the photoid into an existing row and not create a new row, so I changed my INSERT command into an UPDATE which worked as hoped.

$sql = "UPDATE teachers_table SET photoid = '{$photoid}' WHERE id = '{$teacher['id']}'";

Open in new window


 I will now try to improve upon this by applying prepared statements to that UPDATE function,

Many thanks again for your help with this issue. When something doesn't work for me straight away, I immediately feel totally lost - so EE and (experts like yourself) is a great resource to keep me going. Cheers.

Have a good day!
0
AdamTrying to learn phpAuthor Commented:
.
0
Julian HansenCommented:
You are most welcome, Adam
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Development

From novice to tech pro — start learning today.