The task is simple: Let the user (or someone else) upload an image to your server and store it in a predefined location. Additionally you would like to store some information, e.g. an user name, an image title and a comment in a MySQL-Db. As an experienced programmer you will maybe take the Zend Framework.
To handle just a few images, this is no big thing. Make a Zend_Form and enable it to upload a file and store the information according to your model in the database. That is it.
Well thinking a little bit further you may think about the names of your files and what happens when there are two files (one on the server and one to be uploaded) with the same name. You have a conflict. To be more precise: without any intervention the newer file (the one to be uploaded) overwrites the existing file. You have to explain the user where the old image has gone and why there is another image twice in your database.
You have two solutions to this problem:
# Scan your directory upon validation if there already exists a file with this name (or maybe you have stored the filename in the database and query the database) and decide what to do: rename file or do not permit upload, e.g. return a false on validation.
# You can use own filenames based on a MySQL auto-increment value, e.g. the ID-Column which holds the additional information (user name, title, comment).
I will show you how to implement the latter solution. In a second tutorial I will show you how to access this files.
Setting up the application with Zend_Tool
To speed things up I have used Zend_Tool from command line to create my application. I have to say, that this is really nice. You will find some instructions on the Zend Devzone from Ralph Schindler.
Creating the models
After having a clean install from Zend_Tool you need to set up your model. Its a simple table as you can see in the following excerpt:
CREATE TABLE `images` ( `id` tinyint(100) NOT NULL auto_increment, `title` varchar(200) NOT NULL, `comment` varchar(400) default NULL, `updated` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
You could also set the comment as text if you want. I do not want to long comments, so I decided to use Varchar.
Routines for the model
You need three to four routines for your model:
- Read all entries (optional)
- Read one entry
- Write new entry
- Get last id.
My model looks like this:
protected $_name = 'images';
public function getImages()
{
}
public function getImage($id)
{
$id = (int)$id;
$row = $this->fetchRow('id = ' . $id );
if(!$row) {
throw new Exception("Could not find row $id");
}
return $row->toArray();
}
public function insertImage($title, $comment, $user)
{
$data = array(
'title' => $title,
'comment' => $comment,
'fbUser_id' => $user
);
$this->insert($data);
}
public function lastID()
{
return $this->_db->lastInsertId();
}
The most important part is the function I called lastID().
Setting up a form
I do not have to explain here how you can set up a form. Just make a new form of enctype="multipart/form-data" and use it in a controller you like.
Setting up the controller
As everybody knows does the upload "happen" in the controller in which the form is used. I have used an action called "Upload" as you can see in the code excerpt from the controller below:
public function uploadAction()
{
$this->view->title = "Upload new Image";
$this->view->headTitle($this->view->title, 'PREPEND');
$form = new Form_ImageUpload();
$form->submit->setLabel('Upload');
if(!$this->getRequest()->isPost())
{
$this->view->form = $form;
}
elseif(!$form->isValid($_POST))
{
$this->view->failedValidation = true;
$this->view->form = $form;
return;
}
else
{
$values = $form->getValues();
$uploadname = $form->image->getFileName();
chmod('<path info>/uploads/'.$uploadname, 755); // not necessary but worked fine for me
$table = new Model_DbTable_Images;
$table->insertImage($values['title'], $values['comment'], $this->user);
$fullFilePath = '<path info>/uploads/'.$table->lastID().self::findexts($uploadname);
$filterFileRename = new Zend_Filter_File_Rename(array('target' => $fullFilePath, 'overwrite' => true));
$filterFileRename->filter($uploadname);
$this->view->imageUploaded = true;
chmod($fullFilePath, 0755);
$this->_redirect('index');
}
}
As you can see are there some special functions involved:
- You need your last id which has been inserted in the database respectively on the table. You can get this by invoking the function on the model, we have created above.
- You need your filename and separately the file extension. But you need the extension only, if you allow multiple formats of images. If you only allow one format, then you do not need the extension, because you can add the default extension.
- Specify the path, where the file has been saved to (you do not need to use "->setValueDisabled(true)" on the file upload element in your form) and where it will go to. In my case this paths are identical (because we just rename the file and do not copy it). Of course I will not provide my paths here. Please just use your own path instead of _
_ in the script (be careful to provide a full path from the root). - Put together all the information for the new path and invoke the Zend_Filter_File_Rename on the uploaded image.
Last trick: Getting a file extension
To get your file extension I have a separate function. Quite handy and nice, which you will also find multiple times, when you search in Google. I used this one here from Angela Bradley
On the second page you will find the following code:
//This function separates the extension from the rest of the file name and returns it
function findexts ($filename)
{
$filename = strtolower($filename) ;
$exts = split("[/\\.]", $filename) ;
$n = count($exts)-1;
$exts = $exts[$n];
return $exts;
}
Declare it in your controller as private function and use it as shown above.
That is already all. You need a chmod() that your browser can read the image afterwards. Maybe you want like me a redirect or a success page then make another action or view to display to the user.
In the next tutorial I will show how to access the images and its information with a MySQL query and some directory-scanning.

Leave a comment