How do I allow multiple images to be uploaded a post and then display them in a gallery on the post page?


#1

I am creating a blogging system where I want the user to be able to upload multiple images that will then display in a gallery on the post page. I was wondering how I could go about getting multiple images to upload and then display only the images that are attributed to that specific post in the gallery?

This is not a WordPress blog.

This is my first PHP project I've done, so any help would be appreciated. Thank you in advance to anyone who can help point me in the right direction.

Here is my newpost.php that allows the user to create their post:

<?php
session_start();
$msg = "";
//connect to the database
include('../includes/db_connect.php');
if (!isset($_SESSION['user_id'])) {
	header('Location: login.php');
	exit();
}
if(isset($_POST['submit'])){
	$target ="images/".basename($_FILES['image']['name']);
	$uploads_dir = 'image/';
	$image = basename($_FILES['image']['name']);
	$title = $_POST['title'];
	$price = $_POST['price'];
	$description = $_POST['description'];
	$category = $_POST['category'];
	$title = $db->real_escape_string($title);
	$price = $db->real_escape_string($price);
	$description = $db->real_escape_string($description);
	$user_id = $_SESSION['user_id'];
	$description = htmlentities($description);

	if($title && $price && $description && $category && $image){
		$query = $db->query("INSERT INTO post (user_id, title, price, description, category_id, image) VALUES('$user_id', '$title', '$price', '$description', '$category', '$image')");
		if($query){
			echo "product posted";
		}else{
			echo "error";
		}
	}else{
		echo "missing data";
	}

	if(move_uploaded_file($_FILES['image']['tmp_name'], $target)){
		$msg = "Image uploaded successfully";
	}else{
		$msg = "There was an error uploading the file";
	}
}
?>

Here's the HTML form:

<form action="<?php echo $_SERVER['PHP_SELF']?>" method="POST" enctype="multipart/form-data">
                        <div class="form-group">
                            <label>IMAGE(S) *</label>
                            <input multiple="multiple" name="image[]" type="file" />
                        </div>
                        <div class="required">
                         * indicates a required field
                         </div>
                        <button type="submit" name="submit" value="Submit" class="btn btn-default">POST</button>
                    </form>

And here is the post.php where I want to display the multiple images:

PHP

<?php
//send user back to inventory page if page ids do not exist
if(!isset($_GET['id'])){
    header('Location: index.php');
    exit();
}else{
    $id = $_GET['id'];
}

include('includes/db_connect.php');

if(!is_numeric($id)){
    header('Location: index.php');
}

$sql = "SELECT title, description, price, image FROM post WHERE post_id='$id'";
$query = $db->query($sql);
if($query->num_rows !=1){
    header('Location: index.php');
    exit();
}

?>

HTML

<?php
			$row = $query->fetch_object();
			echo "<h1>".$row->title."</h1>";

      echo "<div class="carousel slide article-slide" id="article-photo-carousel">
      <!-- Wrapper for slides -->
      <div class="carousel-inner cont-slider">
        <!-- IMAGES -->
        <div class="item active">
          <img alt="" title="" src='admin/images/".$row->image."'>
        </div>
        <div class="item">
          <img alt="" title="" src='admin/images/".$row->image."'>
        </div>
      </div>
      <!-- THUMBNAILS -->
      <ol class="carousel-indicators">
        <li class="active" data-slide-to="0" data-target="#article-photo-carousel">
          <img alt="" src='admin/images/".$row->image."'>
        </li>
        <li class="" data-slide-to="1" data-target="#article-photo-carousel">
          <img alt="" src='admin/images/".$row->image."'>
        </li>
      </ol>
      </div>;

			echo "<div class='dollar'>$".$row->price."</div>";
			echo "<div class='descr'>".$row->description."</div>";
			echo "<center><a href='index.php' class='goback'> Go Back </a></center>";
			?>

And here is what my post table looks like:

CREATE TABLE `post` (
  `post_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `title` varchar(255) NOT NULL,
  `price` varchar(255) NOT NULL,
  `category_id` int(11) NOT NULL,
  `description` text NOT NULL,
  `image` varchar(500) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

#2

I believe there are a few posts on the forum for multiple upload; try a search.

You would need a separate table with the image paths linked to the post_id So you can remove the image column from the post table. You could then either have a table linking the post table to the image paths or it would probably be easier to add the post_id to the image in one table. I would have two queries on the upload: one you must already have and the second to save the image names into the second table with the post_id.

To select the images that go with the post I would select all images where the post_id = the post ID from the second table.

I assume you are doing some validation on the user data and checking the image is safe?

EDIT: I should explain the reason for the second table. You do not know how many images you are going to have and would need to reserve say five columns for every post even though there may be only one image. That means the main table is getting very large. Probably not a problem but two tables is a better solution.


#3

Thanks so much for your suggestions. I got everything working fine with using a second table. However, I am running into one little issue that I can't seem to figure out. How would I go about linking the post_id from the post table for the post that's being created to the post_id in the images table for the images that are being uploaded with that post?

Would I be adding it in this query for the images?

$sql = "INSERT INTO images (img_name, img_path, img_type) VALUES ('$filename', '$filepath', '$filetype')";

Or would it be going in this query?

	 $query = $db->query("INSERT INTO post (user_id, title, price, description, category_id, image) VALUES('$user_id', '$title', '$price', '$description', '$category', '$image')");

Or would I be better off writing a new query for it?


#4

Yes. Have a column in the images table that contains the post-id that those images refer to. That way, when you want to retrieve and display the post, it's easy to find the images that go with it.

If you do it the other way around, by having the list of image ids in the posts table, you will need to have sufficient columns in the posts table for each of the images. This means you'll have to set an upper limit on the number of images per post that it will be difficult to extend. It will also (IMO) make your queries a little more complicated.

There's no reason that you couldn't have another table that links post-ids and image-ids, but only if you can think of a specific need for it. One example might be if you were linking the same image to multiple posts, where you'd face the same problem of how many post-id columns to have in the images table.

On another matter, I'm not sure if it's still the case but when I started playing with PHP and MySQL there was an issue with having several columns of the same name in separate tables when those tables might be linked in a single query - in that when you retrieve the results as an array, you obviously can't have two array elements called, for example, $row['postid']. You can use "as" to rename one of them, but (again IMO) easier to not have clashing names in the first place.


#5

Okay, that makes sense. Thanks! I see what you mean about it being more complicated doing it the other way around. so far I haven't had any issues when having columns of the same name in tables, but I will go ahead and rename them since I understand what you're saying about that possibly causing issues.

I created the post_id column in the images table, and whatever I'm doing, I am not doing it right because whenever I upload images and submit them with the post form, they still have a post_id value of 0. How do I get the id from the post on submit so it can be inserted into the image table when those are uploaded on submit? I've been messing with the images query, and I am doing something wrong, but I am not sure what that is. Can you tell if the following iteration of what I've been messing with is even close to what I want to be doing?

$sql = "INSERT INTO images (img_name, img_path, img_type) 
        VALUES ('$filename', '$filepath', '$filetype') 
        SELECT * FROM images 
        INNER JOIN post 
        ON post.post_id=images.post_id ";

#6

I'm not 100% sure as you seem to be using mysqli and I use PDO. However, what you need to do is run the insert query for the posts table to create the new post, then get the post id, which I assume is an auto-incrementing column. As long as it is, you should be able to do something like

// run the posts insert query first, then
$postid = $db->insert_id;

This will get the value of the auto-incrementing id column from your insert query.

Then in your images insert query, you'd do something like

$sql = "insert into images (img_name, img_path, img_type, post_id)
  values ('$filename', '$filepath', '$filetype', '$postid')"

You should look at prepared statements, too, rather than sticking quoted strings in queries.


#7

This really helped me out, thank you so much! Your suggestions are always very useful and I learn a lot. I will also be checking out prepared statements.

I was wondering if you had any suggestions for how I would go about displaying the images in the PHP? On the post page, I'm already calling for one id (the post_is from the post table), so is it possible to call for multiple ids? Since I know I'll need to have post_id + img_id from the images table in order to actually display the images.

Here is the PHP I currently have on the page:

<?php
if(!isset($_GET['id'])){
	header('Location: index.php');
	exit();
}else{
	$id = $_GET['id'];
}

include('includes/db_connect.php');

if(!is_numeric($id)){
	header('Location: index.php');
}

$sql = "SELECT title, description, price, image FROM post WHERE post_id='$id'";
$query = $db->query($sql);
if($query->num_rows !=1){
	header('Location: index.php');
	exit();
}
?>

This is where I am displaying the post content in the html:

            <?php
			$row = $query->fetch_object();
			echo "<h1>".$row->title."</h1>";
			echo "<img src='admin/images/".$row->image."' width='100%' height='100%' >";
			echo "<div class='dollar'>$".$row->price."</div>";
			echo "<div class='descr'>".$row->description."</div>";
			echo "<center><a href='index.php' class='goback'> Go Back </a></center>";
			?>

And then when I actually display them in the HTML, I will probably have to include the <img> in a loop so all the images within that post display, right?


#8

Yes, that sounds about right. You'll need a query to retrieve all the images with the matching post_id value, then loop through them to display them.

$imsql = "select filename, filepath from images where post_id = '$id' ";
$q2 = $db->query($imsql);
if($q2->num_rows>0) { 
  while ($imrow = $q2->fetch_object();
  // echo the img tag here using the values from the database
  }
}

#9

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.