Lesson 5 - Making an object-oriented component in PHP - Image Gallery

PHP OOP Making an object-oriented component in PHP - Image Gallery

In the previous lesson, Encapsulation in PHP, we learned about encapsulation. As promised, today we will create something you may actually find useful for your websites, an image gallery.

Motivation

Image galleries are a common thing to include in a website. Whether it features vacation photos, application screenshots, or anything else, they are a crucial design tool... Coding an HTML table and adding images manually sounds like a drag, especially if we had lots of them (something over 50). What we want is to render images from a folder automatically into a clear table. Ideally, we would want this process to be done by an object so that the code would be reusable.

Creating project structure

Create a new folder and name it "gallery". Inside, create an index.php file and a "classes" folder, in which you will need to create a Gallery.php file. Last of all, create another folder, name it "photos", and drop several images into it. I used the default "Image samples" that the Windows OS provides. We also need to create a thumbnail for each image (using GIMP or any other image editor). PHP could do it for us while it uploads the images, but we could work with that sort of functionality some other time. My preview thumbnails will be 160px wide and have the suffix: "_thumb". Your folder should look something like this:

Photos folder for PHP gallery

Gallery

We have the data and the structure ready, now let's get to programming. Obviously, we'll start by defining the Gallery class, whose instances will represent an image gallery. Let's think about the properties it will need to have.

Properties

We want to be able to set the number of thumbnails per row, in other words, the number of columns the image table will have. Also, we will need to store the image folder's path (in programming, we mostly use the term directory when referring to a folder path). We'll keep all of the properties private, and set them through the constructor.

The class' code including the properties and the constructor is as follows:

class Gallery
{

        private $directory;
        private $columns;

        public function __construct($directory, $columns)
        {
                $this->directory = $directory;
                $this->columns = $columns;
        }

}

Methods

Now let's move on to the methods! We technically already have one down, the constructor, let's add 2 more.

Load

The load() method will search for a folder and store the thumbnails into memory. PHP provides a Directory class that searches for folders. Remember when I said that the latest versions of PHP provided objects for us to use? Directory is one of them. Unfortunately, we can only create an instance of the Directory class using the dir() function because, well, nothing is perfect. We'll be using 2 methods in particular on the instance:

  • read() - Loads the contents of next file or sub-directory in the current directory and returns it as string
  • close() - Ends directory reading

Our load() method now looks like this:

public function load()
{
        $directory = dir($this->directory);

        while ($item = $directory->read())
        {

        }
        $directory->close();
}

We create an instance of the Directory class. Then, with the help of the read() method, we get the sub-directories and files one by one. The method returns false once it reaches "the end" of a directory (once it reads the very last file or directory). Thanks to this behavior, we are able to read file names in a while loop, which ends when it reads the very last one. The filename will be stored in the $item variable from inside the loop. Assigning variables in the loop condition may be unheard of to you, but it's a very common thing to do.

We load each file twice (thumbnail + original). The function also returns two more spare directories named "." and "..", which stand for current and parent directory. We only want the thumbnails to be displayed, so we will have to add a condition into the loop. The condition will say that we're interested in files whose name ends in "_thumbnail", and store them into an array. The array will need to be accessible for the render() method, so we'll add it to the class as a private property.

private $files = array();

Now, let's move to the while loop body and add the filenames into our array with the aforementioned condition set up. To do so we will use the strpos() function, which returns a substring position. If "_thumb" is part of the filename, the item will be added into the array. Otherwise, the function will return false.

if (strpos($item, '_thumb.'))
{
        $this->files[] = $item;
}

The strpos() function returns 0 when a string starts out with the substring (0 as in the very first position). In our case, a value of 0 will be evaluated as false and will not satisfy the condition. That's right! If a file is named "_thumb.jpg", then it is likely bound to an unnamed image, which means it's invalid. If we wanted to check for a substring occurrence in the entire string, we would distinguish 0 and false values using the !== operator:

if (strpos($item, '_thumb.') !== false)
{
        $this->files[] = $item;
}

Here, the condition won't apply only when the function returns false and would apply when it returns 0. For our intents and purposes, the previous condition will do.

Printing out

We've bravely defeated the harder part! Now let's move on to printing out the HTML table using the render() method. Even though loading files and printing them into a table could be done in the same method, there are 2 different logical tasks so it's better to split them up into two methods. A method should only perform one task. In other words, we should be able to describe what it does without using the word "and". For example, "The display() method displays an HTML table with thumbnails", not "The display() method loads and displays an image gallery".

The first thing the render() method will do is echo out the start of a table. Then, it will iterate over the thumbnails using a foreach loop and echo them out as table cells using an img tag. Next, It will wrap the img tag with a link to the original image. Getting a link to the original image is very simple, all we'd have to do is replace the "_thumb" with a "." in the thumbnail's filename. To do so, we will use str_replace() function. We will count the columns we've printed out so as to not have the entire table in one row. Then, when we reach the value set in the $columns property, we will close the row, start a new one and reset the column counter.

The render() method will look something like this:

public function render()
{
        echo('<table id="gallery"><tr>');
        $column = 0;
        foreach ($this->files as $file)
        {
                $thumbnail = $this->directory . '/' . $file;
                $image = $this->directory . '/' . str_replace('_thumb.', '.', $file);
                echo('<td><a href="' . htmlspecialchars($image) . '"><img src="' . htmlspecialchars($thumbnail) . '" alt=""></a></td>');
                $column++;
                if ($column >= $this->columns)
                {
                        echo('</tr><tr>');
                        $column = 0;
                }
        }
        echo('</tr></table>');
}

Usage

Let's move over to index.php file. Add a basic HTML structure and create a gallery instance. Then, pass the directory path and the number of columns to the constructor. Once you've done that, call both the load() and render() methods.

<!DOCTYPE html>

<html lang="en">
    <head>
            <meta charset="utf-8" />
            <title>Image gallery</title>
    </head>

    <body>
        <h1>Image gallery from ICT.social</h1>
        <?php
        require_once('classes/Gallery.php');

        $gallery = new Gallery('photos', 4);
        $gallery->load();
        $gallery->render();

        ?>
    </body>
</html>

Done!

With a little bit of CSS, the gallery application ends up looking pretty decent (the code can be downloaded in the attachment below the article):

Object-oriented photo gallery in PHP

I also added the JavaScript Lightbox plugin to display the original images.

Object-oriented photo gallery in PHP with Lightbox

Possible enhancements

The render() method still has a couple of kinks. One of the main ones being that the HTML code is echoed out, which makes working with it kind of confusing. Another added improvement would be to incorporate an image uploading method, that uploads images to the gallery using FTP and creates thumbnails for them automatically. For our purposes, our app is fine the way it is now.

We've programmed an object-oriented component. One that can be added to any number of websites, using various directories and displayed as individual tables.

In the next lesson, Reference and primitive data types in PHP, we will continue working with our Human class instances, and will stick with them for a while. You will learn how PHP works with reference data types.


 

Download

Downloaded 110x (1.39 MB)
Application includes source codes in language PHP

 

 

Article has been written for you by David Capka
Avatar
Do you like this article?
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn College The author learned IT at the Unicorn College - a prestigious college providing education on IT and economics.
Activities (10)

 

 

Comments

Avatar
Aljon Olela
Member
Avatar
Aljon Olela:3. March 4:00

Change your while condition in Method load()
from
while ($directory = $directory->read())
to
while ($item= $directory->read())

 
Reply 3. March 4:00
Avatar
David Capka
ICT.social team
Avatar
Replies to Aljon Olela
David Capka:4. March 12:54

Hi Aljon, thanks for the info, we've fixed it. We also added 10 points to your account for reporting the mistake.

Reply 4. March 12:54
You can walk through a storm and feel the wind but you know you are not the wind.
To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

2 messages from 2 displayed.