Get $500+ of the best After Effects files, video templates and music for only $20!
Building the back-end of a photo site
videos

Building the Back-End of a Photo Site

For those of you who have been following the last few screencasts, you must have noticed that each tutorial has been centered around a “photo site” theme. (See Scanning Folders With PHP, How to Dynamically Create Thumbnails, and Create a Photo-Admin Site Using PHP and jQuery. Today, we’ll build the backend for a photo site. This tutorial will teach you how to add, delete, and update photos.

Our Mission

  • Create a database that will store our images.
  • Create a home page that retrieves all of the photos that are stored in our database.
  • Allow the user to upload photos.
  • Write some validation to ensure that the user enters a proper description and chooses an image
  • Use jQuery to allow the user to asynchronously update and delete specific photos.

There is simply too much to cover as a written tutorial. I’ve included a few key points. Refer to the screencast for the complete tutorial.

The Database Structure

The database structure

Get the Photos From the Database

Get Photos Function
function getPhotos() {
	require 'database.php';
	$q = "SELECT id, tn_src FROM photo ORDER BY id desc";

	$result = $mysqli->query($q) or die($mysqli_error($mysqli));

	if($result) {
		while($row = $result->fetch_object()) {
			$tn_src = $row->tn_src;
			$src = $row->src;
			$id = $row->id;

			print '
  • <a href="review_image.php?id=' . $id . '"> <img src="' . $tn_src . '" alt="images" id="' . $id . '" /> </a> </li>'; print "\n"; } } }
  • Upload Photos

    Get Photos Function

    Form Validation

        if(strlen($_POST['description']) < 4)
        $error['description'] = '
    

    Please enter a description for your photo. '; if($filename == '' || !preg_match('/[.](jpg)|(gif)|(png)|(jpeg)$/', $filename)) $error['no_file'] = '

    Please select an image, dummy! ';

    Update the Photo’s Description Asynchronously

    Get Photos Function
    $('#description').click(function() {
                var originalelement = this;
                var currentText = $(this).text();
    
    			$(this).fadeOut(100).before('');
    
    		    $('#input').livequery('change', function() {
    	            var id = <?php echo $_GET['id'] ?>;
    			    var thisparam = this;
                    var newText = $(this).val();
    
                    if (newText == '') {
                       newText = 'Please enter a description';
                    }
    
    	            $.ajax({
    	                type: 'post',
    	                url: 'updatePhoto.php',
    	                data: 'id=' + id + '&description=' + newText,
    
    	                success: function() {
                            $(thisparam).remove();
    	                    $(originalelement).text(newText).fadeIn(1000);
    	                }
    	           });
    
    		    });
    		});
    	});
    

    UpdatePhoto.PHP

    require 'database.php';
    
    $id = $_POST['id'];
    $d = addslashes($_POST['description']);
    
    if ($d == '') $d = 'Click here to enter a description.';
    
    $q = "UPDATE photo SET description='$d' WHERE id = $id";
    $result = $mysqli->query($q) or die('There was a problem updating this information.');
    
    if($result) echo "Your photo has been successfully updated.";
    

    Delete a Photo

    Get Photos Function
    	$(function() {
    		$('img').click(function() {
    		   	var id = $(this).attr('id');
    		   	var thisparam = $(this);
    
    			$.ajax({
    				type: 'post',
    				url: 'delete.php',
    				data: 'id=' + id,
    
    				success: function() {
    
    					$(thisparam).parent('li').fadeOut('slow');
                        $('#result').remove();
    					var response = '
    

    Success. The image has now been removed!

    '; response += 'Return to Home Page
    '; $('body').append(response); } }); }); })

    Delete.PHP

    require 'database.php';
    
    $id = $_POST['id'];
    
    $q = "DELETE from photo WHERE id = $id";
    $result = $mysqli->query($q) or die("There was a problem!");
    
    if($result) header("location: index.php");
    

    Completion

    So that does it. You could implement a bit more security into this application. But the idea is that these pages would already be secured by using something similar to an ht-access file. From here on, the sky is the limit. You should consider adding tags to your images, creating albums, etc. This should get you started.

    Add Comment

    Discussion 97 Comments

    Comment Page 1 of 21 2
    1. Manji says:

      Thank you!

    2. insic says:

      this tutorial is sweet! its very helpful, perfect for my next project.

    3. yusuf1 says:

      thats really nice, was looking for something along this lines.cheers!

    4. T Pham says:

      great, thanks for tut.

    5. Amr says:

      3 in 1 tut … ;)
      thanks for this tut!

    6. Janko says:

      Nice one. Would be interesting to do one in ASP.NET

    7. pixelsoul says:

      Very nice. I know that this would come in handy when the turn key solutions just won’t work for the project.

    8. wow, this is what i have been looking for to learn and this is just perfect, thanks a lotttttt, nettuts RULESSS!!!!, keep up the work guys

    9. Kim Dolleris says:

      Yay!!! Thanks!

    10. Shane says:

      Thanks Jeff – nice post.

      I see you’ve updated the getPhotos function so that it writes out lower case tags now :)

    11. ashvin says:

      Jeff u r the man and nettuts u r the blog!!

      Thanx!

    12. Dan Harper says:

      Nice video, Jeffrey!

      Although I find the American way of pronouncing “database” annoying for some reason haha. It’s day-ta-base.

    13. Melvin Walls says:

      Thanks Jeff you rule! I followed it from start to finish great work

    14. Outstanding tutorial. It is amazing what you can all accomplish with JQuery. AJAX is pretty simple when using it.

    15. Awesome tut! Thanks, I was looking for something like this.

    16. The PHP in this tutorial is a bit weak but the jQuery is good. You should NEVER print/echo information within a function, only do returns. You should also never put the php and html in the same files, it should be separated using a template system.

    17. Jonas says:

      Delete.php allows for SQL injections by malicious users. It would be so easy to delete tables or alter data using that file alone.

      Try mysqli_real_escape_string().

    18. Moksha says:

      great video thanks,

    19. Chris says:

      The argument from Miles Johnson about the print/echo within a function and from Jonas about the SQL injections are good ones, but its not the topic here.
      Very clear and helpful cast, thanks for sharing.

    20. Ryan says:

      Very helpful, will be great to use for clients who want to be able to maintain the website themselves!

    21. Jonas says:

      @Chris: Sure security/SQL injections isn’t the topic here, but since making the script secure would only take one more line of code *and* this site is read by a lot of newbie developers who might not know about security, it’s important that the scripts shown here are secure.

      Given that the security problem of SQL injections has been talked about since … forever, I’m frankly a little shocked that there are experienced or semi-experienced developers out there who write code that allows for SQL injections.

    22. Danc says:

      Excellent tutorial, many thanks, but I was wondering if it was possible to edit multiple entries on one page with this code?

      I have tried and failed but any tips would be welcome!

      Cheers,

    23. Joao Clerigo says:

      Excelent TUT. Maybe this is a stupid question, but why not use imagecopyresampled instead of imagecopyresized in the function createThumbnail? I’ve picked up your tut to test and noticed that the thumbs have jagged edges. I’ve already had built an auto thumb creator for some websites I’ve made and have been using the function imagecopyresampled instead of imagecopyresized that makes the resized thumbs resampled smoothly by interpolating pixel values so that, in particular, reducing the size of an image still retains a great deal of clarity.

    24. Dan says:

      At 29:51 in the screencast, you mention that getting the it is “probably not best practice to embed this PHP” when setting the id variable in javascript to .

      I’m curious, if that isn’t best practice, what would be a preferred alternative? Is there one?

      All in all Jeff, this was an awesome screencast. It was relaxing to watch as with most screencasts I’m trying to write code as fast as you type it…and not succeeding (but that’s just me :-P).

      Thanks again!

    25. Ben Blogged says:

      Jeffrey you are the man!

    26. mindkkane says:

      THanks!!!
      For the guys who see not so best practice in the php code please give us novice some pointers so we can change it on our own. I would be thankful for any coding corrections,alternatives,or best practice pointers. Thanks again!!!!!

    27. Jonas says:

      @ mindkkane:

      Here’s a description of SQL injections and how to avoid them: http://www.tizag.com/mysqlTutorial/mysql-php-sql-injection.php.

      As for other problems with the code: The getPhotos() function mixes XHTML with PHP. Ideally, the function should just return an object to a template. The template would then iterate over the object and print out the contents. This sort of functionality is included in MVC frameworks such as CakePHP (http://cakephp.org/) and Django (http://djangoproject.com/), so if you learn how to use them, you get that separation of code and XHTML automatically (because the systems enforce the separation).

    28. Jauhari says:

      Just Perfect Tutorials..

    29. grrrrrr8 says:

      awsome

    30. arma9 says:

      Keep it up with Jquery and Ajax !!!Thanx again

    31. Daniel says:

      Very nice tutorial. I really appreciate the hands on “real application” style tutorials here. You’re doing a great job Jeff. (and the others of course). This site is my no.1 bookmark if refreshing my memory on everyday tasks.

      I do agree with Jonas on the sql injection parts though. It takes very little extra code and time to add protection against this and it should be done at a site like this.

      Keep up the fantastic work, looking forward to the “plus” programme.

    32. Like Jonas mention with the vulnerability in Delete.php the same vulnerability exists in UpdatePhoto.php I believe it’s just the lax assumption on the authors part that $id will always be clean and will be what is expected (a number). I would hope that the tutorial is updated to at least put in the suggestion Jonas gave because a lot of users don’t read the comments section.

      While I agree with Chris that the comment made by Miles Johnson isn’t necessarily on topic to the tutorial the comment made by Jonas and security is a very important topic and what Jonas has pointing out is very much related to the tut. Aside from that great topic for a tut!

    33. silent says:

      I’ve been creating many photo site for my customer and I naver imagine that back-end could be this user friendly!

      Thank you for sharing it!

    34. kareem says:

      this is wonderful topic …. i will put acopy of this topic on
      my site here
      http://www.as7ap4you.com

    35. AKARATALARAB says:

      GOOD, this is wonderful tutorial
      fantastic results AND IT will help me im my site
      http://www.akaratalarab.com

    36. Rodge says:

      Very nice tut!!

      However, when I click the delete photo button (on the index page) I get this error:

      No input file specified.

      On the review page clicking on the delete button wont redirect me to index…

    37. Takumi86 says:

      Cool tips dude, keep them coming

    38. Uncle says:

      Hi Guys I’m a serious PHP Newbie so please be kind.

      I’ve created the database with the “photo” table and the fields above.

      When i run index.php all that gets outputted is this “”

      Can anyone offer some advice as to what i’ve done wrong?

    39. Ok so i’ve tested it on xp, vista, running wamp with php 2,26 and on one.com’s servers, and its not working, not as intended anyway. theres something wrong with the upload / or move_uploaded_photo part, it write to the database with the image andress and you can delete it again, but theres no image in /images (or anywhere else) and i’m getting no errors on localhost (and yeah i got E_ALL on)

      Also on a sidenote, a sqldump would be appreciated for the lazy types like me :D but i like the whole idea around this tut, just gotta make it work..

    40. coven says:

      this is wonderful tutorial .. i read it 3 times and get a fantastic results and sure i put a
      copy of this lesson on my site here

      http://www.ac-coven.net

    41. Hahn says:

      i enjoy learning this good tutorial. can you please teach how to tag and search for photos too?

    42. Jeroen says:

      Awesome tutorial! Thanks a lot Jeff, you’re doing a great job on Nettuts.

      I also noticed the problem Torben Rasmussen was talking about.

      But i already found the cause,…. FILESIZE.
      If the image filesize is too big, the picture won’t be uploaded, but the database will add a record for it. Ack!
      Perhaps the filesize should also get a validation. Any suggestions on how to do this?

    43. Benn Garnish says:

      Im really struggling with this one, I’ve watched all the screencasts that are related to this one and im still in no-mans land about it all.

      It starts right at the begining really, the database is kicking out a mysqli error

      I have the correct information in my db_name and db_user and db_pass
      but this is as far as the script will go.

      Can anyone help me with this please and thank you :)

    44. Benn I’m in the same boat as you. I’ll look over the code to see if there is an error or something. If I find anything I’ll post it here

    45. Aaron says:

      @Benn and Mike

      I think you are referring to this error:

      Fatal error: Function name must be a string

      I got it too. Did some research and found out that there was a ‘$’ in front of mysqli_error on line 9 in functions.php where there shouldn’t be. That fixed it for me. Hope this helps

    46. Benn Garnish says:

      Hey guys

      I worked out that for this to work you need php5 switched on your hosting server. How embarrassing.

      I was also struggling with images being added to the site but not displaying a thumbnail. But this was sorted as there wasn’t a final ‘else’ statement in the function for making the thumbnail image. Also the preg_match statements are case sensitive, so files with .JPG were not being added.
      So for this to be fixed i added this to the preg_match statements:

      if(preg_match(‘/[.]jpg$/’, strtolower($filename))) {
      $im = imagecreatefromjpeg($path_to_image_directory . $filename);
      } else if (preg_match(‘/[.]gif$/’, strtolower($filename))) {
      $im = imagecreatefromgif($path_to_image_directory . $filename);
      } else if (preg_match(‘/[.]png$/’, strtolower($filename))) {
      $im = imagecreatefrompng($path_to_image_directory . $filename);
      } else {
      print(“Error: The file ‘$filename’ is not a supported file type”);
      }
      }

      Hope this helps some of you.

    47. Greg says:

      What if the users need to email their photos as attachments instead of uploading via a form?

    48. whiskeyfrances says:

      This is great… With some extra coding and an ffmpeg-enabled hosting one could also take this to create a video site…

    49. pauli says:

      hi, im looking for some kind of plugin that let users upload their images on my website(wordpress) and as the admin it lets me choose which one to display
      also when uploading the images the users can put some text.

    Comment Page 1 of 21 2

    Add a Comment

    To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.