Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

PHP Lessons - Lesson 4 - Working with Images, GD2 Library

16/04/2025, by Ivan

In the previous lessons, we learned how to write database queries, so now we'll focus less on writing queries and more on practicing them. We'll also combine writing queries with learning other PHP features, starting with image processing. In one of the previous lessons, we already uploaded files and even created a Files table for uploaded files. Now, let’s upload images to the same table. But first, we need to add a photo upload field to the content creation form.

$content .= '<label for="bodytext">Message:</label><br />';
$content .= '<textarea name="bodytext" id="bodytext"></textarea><br />';
$content .= '<label for="bodytext">Attach a file:</label><br /><input type="file" name="filename"><br />';
$content .= '<label for="bodytext">Attach an image:</label><br /><input type="file" name="image">';

Now we need to write file handling logic, but first let’s add a new column to the Messages table, where we'll store the image file ID (fid). We'll store the image metadata in the Files table, just like other files. The new column is named image_fid, with type INT(11), and defaults to NULL. Let’s insert the form processing code in the write() method:

if($_FILES["image"]["size"] > 1024*3*1024){
    echo ("File size exceeds three megabytes");
    exit;
}
if(is_uploaded_file($_FILES["image"]["tmp_name"])){
    move_uploaded_file($_FILES["image"]["tmp_name"], "./files/".$_FILES["filename"]["name"]);
} else {
    echo("File upload error");
}	

$sql = 'INSERT INTO Files (filename, filepath, filemime, filesize, timestamp) 
VALUES ("'. $_FILES['image']['name'] . '", 
 "files/' . $_FILES['image']['name'] . '",
 "'. $_FILES['image']['type'] .'",
 '. $_FILES['image']['size'] .',
 '. time() . ')';  

mysql_query($sql);

This processing is no different from uploading regular files, although in a future lesson, we’ll look at how to validate file types to prevent uploading, for example, PDF files disguised as images.

Now both files will be uploaded, one of them an image. Here’s the $_POST and $_FILES arrays printed with print_r():

Array ( 
  [title] => test 
  [bodytext] => asdfasf 
) 
Array (
  [filename] => Array ( 
    [name] => ip.txt 
    [type] => text/plain 
    [tmp_name] => Y:\tmp\php2C5.tmp 
    [error] => 0 [size] => 13 
  ) 
  [image] => Array (
    [name] => Coat_of_arms_of_Vladimiri_Oblast.png 
    [type] => image/png 
    [tmp_name] => Y:\tmp\php2C6.tmp 
    [error] => 0 [size] => 393743 
  ) 
)

Now change the insert query for the message:

$sql = 'INSERT INTO Messages (title, bodytext, created, fid, image_fid) VALUES ("'. $p["title"] . '", "' . $p["bodytext"] . '", ' . time() . ',LAST_INSERT_ID()-1, LAST_INSERT_ID())';

To identify the fid of the regular file and the image, we use LAST_INSERT_ID(). Since the regular file is inserted before the image, we subtract one from the last ID.

Now that images are inserted into the database, we can display them. To handle images, we’ll create a stub class called simpleImage. Create a new file simpleImage.php in the class folder and write the following:

<?php

class simpleCMS {

}

?>

Now that we’ve created a new class for image processing, we need to define methods. But first, let’s talk about variable visibility in PHP classes.

PHP 5 Class Properties

In PHP4 everything was simple—class properties were declared with var. But in PHP5, you have more control using public, protected, and private.

Public

The public keyword declares a property accessible from outside the class. For example:

<?php
  $obj = new simpleCMS(); 
  $obj->db='newDB';
?>

Protected

protected means the property is accessible only within the class and its subclasses (we’ll cover inheritance later). If you try to access a protected property from outside, you’ll get an error.

simpleCMS.php
...
protected $db = 'testDB';
...

index.php
...
$obj = new simpleCMS(); 
$obj->db='newDB';
...

Now let’s add a protected variable $path and use a constructor to set it when creating an image object.

Class Constructor

The constructor initializes the object’s state. We’ll pass the file path to the constructor and store it:

class simpleCMS {
  protected $path;
  
  public function __construct($image){
    $this->path = $image;
  }
}

Now update the public_display() method of simpleCMS to output image data:

if(!empty($row['image_fid'])){
  $sql = "SELECT * FROM Files WHERE fid=".$row['image_fid'];
  $image_query = mysql_query($sql) or die(mysql_error());  
  $image = mysql_fetch_array($image_query);
  $content .= '<div class="image">';
    $image = new simpleImage($image['filepath']);
    $content .= $image->scale(100,100);
  $content .= '</div>';
  unset($image);
}

This code retrieves the file path from the database. Let’s now write the scale() method:

public function scale($width, $height){
  ...
  return '<img src="'. $newImagePath . '" width="'. $destWidth.'" height="'. $destHeight . '" />';
}

Make sure the files/presets folder exists and has write permissions (777).

Now for the scale_and_crop() method, which works similarly:

public function scale_and_crop($width, $height){
  ...
  return '<img src="'. $newImagePath . '" />';
}

Also change the display method output:

$content .= '<div class="image">';
  $image = new simpleImage($image['filepath']);
  $content .= $image->scale_and_crop(100,100);
$content .= '</div>';

This makes the images square and cropped proportionally.

In both cases, images are generated on the fly. Since image processing takes time, their paths are often saved in the database to skip regeneration. We won’t cover this optimization here, because in the CMS build we'll eventually use Zend Framework. These PHP lessons are intended to teach you the basics of PHP.