You seem to be struggling again. Here, I’ll just give you this because you seem to understand a little bit about PHP
and at least you tried. That’s what I like.
<?php
// Generate Random String function taken from
// http://stackoverflow.com/questions/4356289/php-random-string-generator
function generateRandomString($length) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';
for($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}
return $randomString;
}
$username = 'spaceshiptrooper'; // Assuming this is the username
// Check to see if the form was submitted
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$upload_directory = 'includes/uploads/avatar'; // The directory you want to store the avatars in.
$image = $_FILES['avatar']; // Create and append a new variable to $_FILES['avatar'] so that we don't have to manually type in the full variable for it.
$image_tmp_name = $image['tmp_name']; // Get the tmp file
$image = getimagesize($image['tmp_name']); // Get the image size of the tmp file
$image_mime = $image['mime']; // Create and append the mime array to $image_mime
// List the mime types you want to allow in your upload system.
$valid_image_mime = array('image/jpeg', 'image/jpg', 'image/png', 'image/gif');
$random = generateRandomString(16); // Generate the set of characters
$ext = '.jpg'; // The file extension we want it to end up being once it's uploaded.
$file_name = $random . $ext; // Append the generated string along with the desired extension to the new file name.
// Check to see if the mime type from the tmp file is in our array above.
if(in_array($image_mime, $valid_image_mime)) {
// So we are good to go. The mime type is listed in our array.
// Check to see moving the tmp file to our desired directory works.
if(move_uploaded_file($image_tmp_name, $upload_directory . '/' . $file_name)) {
// Since the file has been uploaded, we can now update our old avatar records
// And set it to the current one.
$sql = "UPDATE users SET avatar = :avatar WHERE username = :username";
$prepare = dbConnect()->prepare($sql);
$parameters = array(':avatar' => $file_name, ':username' => $username);
$prepare->execute($parameters);
// Check to see if the query executed.
if($prepare->rowCount()) {
// print('Good');
header('Location: ' . $_SERVER['REQUEST_URI']);
} else {
// print('Bad upload');
header('Location: ' . $_SERVER['REQUEST_URI']);
}
} else {
// print('Bad');
header('Location: ' . $_SERVER['REQUEST_URI']);
}
} else {
// print('Bad');
header('Location: ' . $_SERVER['REQUEST_URI']);
}
} else {
// run query to get users avatar - Only select the columns you need.
$sql = "SELECT avatar FROM users WHERE username = :username";
$getAvatar = dbConnect()->prepare($sql);
$parameters = array(':username' => $username);
// execute query
$getAvatar->execute($parameters);
// Check to see if rowCount returned any data
if($getAvatar->rowCount()) {
// Loop the data in a while loop and create/ append the variable $row to the while loop.
while($row = $getAvatar->fetch(PDO::FETCH_ASSOC)) {
// set $avatar as users set avatar
$avatar = $row['avatar']; // This data should be escaped.
if(empty($avatar)) {
// echo default avatar...
echo '<img src="http://i.imgur.com/QFxs0nX.png" class="user_avatar" alt="default avatar" />';
// if user has set an avatar:
} else {
// echo set avatar...
echo '<img src="includes/uploads/avatar/' .$avatar. '" class="user_avatar" alt="' .$username. ' avatar" />';
}
}
} else {
// The username doesn't exist. Either the user is not who they are.
// Or the user doesn't actually exist.
print('Something is wrong. The username does not exist.');
}
?>
<form action="" method="POST" enctype="multipart/form-data">
<input type="file" name="avatar">
<button type="submit">Submit</button>
</form>
<?php
}
So I’ll explain what we are doing here so you can understand what is needed and why that is.
So most of the explanation is already in the comments. To further your understanding. What we do first is, we check to see if the form was submitted. Most amateurs use if(isset($_POST))
or if(isset($_POST['submit']))
or if(isset($_POST['btn']))
or anything along those lines of if(isset)
and that is the wrong way of doing it. This is an amateur hack back from the 90’s. The actual way of checking for form submission is if($_SERVER['REQUEST_METHOD'] == 'POST')
.
Anyways, moving on.
We basically create the variable $image
and reference it whenever we want to use $_FILES['avatar']
instead of typing the full $_FILES['avatar']
. First couple of references are tmp_name
and mime
. These two, we use them for the sole purpose of finding out the contents within the file. So if say we want to limit the file height to 500px. You can limit it by doing
if($image[1] > 500) {
print('The file height is larger than 500px. Please resize it and re-upload it.');
}
So the reason why we are using mime
is so that people can’t upload files that aren’t what they say they are. Simply by checking for “file extensions” are flawed. I strongly suggest you DO NOT do this. Rather, you should be checking for the mime
content type. When a file is created by anything, it leaves a finger print which is mime
type or mime
content type. Basically, say I opened up a NotePad
and I write a bunch of gibberish in there and save the file as .txt
. When you upload it and check it using getimagesize()
, the mime
type returned is text/plain
. Say if someone were to change that .txt
file to .jpg
. The whole “check for file extensions” method will be flawed because the ACTUAL file was not created using an image editor or image creator. When you upload it and check the new file using getimagesize()
, the mime
type will still return text/plain
. Real genuine images have a mime
type header of either image/jpg
, image/jpeg
, image/png
, or image/gif
. There are a few more, but I don’t recall them. Basically, checking for file extensions can be abused and rather not trust worthy.
Next, we generate a 16 random string using the function found on StackOverflow
and append a .jpg
or whatever you want as the file extension. Reason why we add our own file extension to this newly generated file name is because when you generate the file name. You still need to have the file extension in there in order for it to be output as an image. So we use .jpg
since it’s a generic file extension that most people use.
After that, we check to see if the mime
type from the uploaded file is in our list of array. If it is not, redirect them back to the upload page and here, you can give them a custom error using $_SESSION
if you want. We basically halt and redirect them because again, the mime
type is not an actual image and this can lead to a lot of security vulnerabilities. Next, if the file is indeed a genuine image, we then wrap it around another if
statement to make sure that the file does indeed get uploaded. If it doesn’t get uploaded and it says “Success”, then we have a problem. So it’s a good thing to always check your work. I call this “Properly checking for errors”. Simply put, it’s a way to make sure that everything goes well. So say for example, you grab a user’s data from the database using a session cookie that sets their username to something. What if later, they delete their account and their information doesn’t exist on your website anymore? When this happens, if another user requests to look at that old user’s profile, you will end up with a blank page. This is why you should ALWAYS check your work. If you don’t put in the proper error handling, you basically will end up with a blank page. Basically, most of the time, if the data does not exist in the database and you don’t do proper error handling, you basically are giving your users a blank page. Here’s an example of how to do it wrong.
$id = $_GET['id'];
$sql = "SELECT name, location FROM users WHERE id = :id LIMIT 1";
$prepare = $db->prepare($sql);
$parameters = [':id' => $id];
$prepare->execute($parameters);
$row = $prepare->fetch(PDO::FETCH_ASSOC);
print($row['name']);
So in the above snippet, we are basically grabbing an ID from the URL
and doing a query to grab the data using that ID. Let’s say we only have about 12 rows of users. So basically saying that you ONLY have 12 users currently using your service. Let’s just put in the ID # 1.
So that goes through and prints out the current name for user #1 since it’s within the 12 users we have. Now let’s say someone requests for ID #13. That ID doesn’t exist in our database since our current user base is only set at 12 right now. Ohhhhhhhh oooopppppsssss. No data is output and nothing is output onto the screen, not even a “Sorry, you’ve reached the end of our results.” warning. Just a blank empty page. Nothing for the user to see. Nothing to tell the user anything. This is why “Properly checking for errors” is important. If the output is supposed to be say an image of the requested user. It would be something like this.
$id = $_GET['id'];
$sql = "SELECT name, location, avatar FROM users WHERE id = :id LIMIT 1";
$prepare = $db->prepare($sql);
$parameters = [':id' => $id];
$prepare->execute($parameters);
$row = $prepare->fetch(PDO::FETCH_ASSOC);
print('<img src="http://example.com/uploads/avatar/' . $row['avatar'] . '>');
What really gets output when you don’t do “Proper error handling” is this.
<img src="http://example.com/uploads/avatar/">
Is that what you really want your users to see? So simple isn’t always the best in every case.
Any who. Let’s get back to the topic. Now, the next thing we do is we basically update the old avatar to the new avatar. And once the user gets redirected to the upload page. They will see the new avatar instead of the old one.
The rest is basically the same thing, except for outputting data instead of updating data.