Try Tuts+ Premium, Get Cash Back!
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.

    Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
    • Manji

      Thank you!

    • http://blog.insicdesigns.com insic

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

    • http://www.songinstant.com yusuf1

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

    • T Pham

      great, thanks for tut.

    • http://www.brainythink.com Amr

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

    • http://www.jankoatwarpspeed.com Janko

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

    • http://www.pixelsoul.com pixelsoul

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

    • http://klash.tumblr.com Kailash Gyawali

      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

    • Kim Dolleris

      Yay!!! Thanks!

    • http://www.freshclickmedia.com Shane

      Thanks Jeff – nice post.

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

    • http://www.islandzilla.com ashvin

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

      Thanx!

    • http://www.danharper.me Dan Harper

      Nice video, Jeffrey!

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

    • http://www.qzpstudios.com Melvin Walls

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

    • http://blog.brenelz.com Brenley Dueck

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

    • http://novus,byvolce.com Jonathan Solichin

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

    • http://www.milesj.me Miles Johnson

      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.

    • http://jkb.name/ Jonas

      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().

    • http://mokshasolutions.com Moksha

      great video thanks,

    • Chris

      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.

    • http://www.furtzdesigns.com Ryan

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

    • http://jkb.name/ Jonas

      @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.

    • Pingback: NETTUTS.com: Building the Back-End of a Photo Site : WebNetiques

    • Pingback: NETTUTS.com: Building the Back-End of a Photo Site : Dragonfly Networks

    • http://URL(Optional) Danc

      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,

    • Joao Clerigo

      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.

    • http://www.1pixelbrush.com Dan

      Cool indeed

    • http://danbowles.com/blog Dan

      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!

    • http://www.benblogged.com/ Ben Blogged

      Jeffrey you are the man!

    • mindkkane

      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!!!!!

    • http://jkb.name/ Jonas

      @ 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).

    • Pingback: Revue de web semaine 48 | Higherweb ::: Le BLOG

    • http://www.jauhari.net/ Jauhari

      Just Perfect Tutorials..

    • grrrrrr8

      awsome

    • arma9

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

    • Daniel

      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.

    • http://www.neoseeker.com Jamie Taniguchi

      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!

    • http://bayu.freelancer.web.id/ silent

      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!

    • http://www.as7ap4you.com kareem

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

    • Pingback: Craig Farrall’s Blog » Blog Archive » November Roundup

    • http://www.akaratalarab.com AKARATALARAB

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

    • Rodge

      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…

    • http://tendou86.blogspot.com/ Takumi86

      Cool tips dude, keep them coming

    • Uncle

      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?

    • http://alloutgeek.com Torben Rasmussen

      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..

    • http://www.ac-coven.net coven

      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

    • Hahn

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

    • http://www.mediashake.nl Jeroen

      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?

    • Benn Garnish

      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 :)

    • http://organikdesigns.com Mike Schneider

      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

    • Aaron

      @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