There is much debate about the best way to handle images in a system. Images related to the look of the site itself are best treated as assets and stored as files in the file system with other assets. Images which are uploaded by users, however, can reasonably be base64 encoded and stored as a Binary Large OBject in the database. This will incur a significant performance hit and will require the database to be able to grow to a much bigger size then it would with simple transactional data. The advantage of putting the image in the database is that it stores all data in one place and makes backup and data management much simpler. This can be a big advantage, particularly where organizations are subject to compliance issues in relation to how they store and manage user data. Many developers believe that as the system starts to scale that the optimum solution is to store the images on the file system and store the name of the image hashed in the database. This poses its own challenges. Some very large organizations use a combination of both - with caching of images used to improve performance but images ultimately stored in the database for backup and control purposes.
This series of posts will describe how to store an image in the database as a BLOB and then render that image. For this, we will use the tennisClub - extending the example to include images for members of the tennisClub.
To begin with - run the following SQL command which will modify the member table adding an additional column of type longblob which will store the member image.
alter table member add column memberpic longblob;
phalcon model member --force --get-set --namespace=tennisClub
The --force switch will ensure the model class updates even if it already exists. The beauty of this option is that it doesn't overwrite the existing model - it just updates it. So any customizations you have made, such as a __toString() magic method, will stay in place.
If you don't already have the member table you can generate one with the following script taken from the Getting Started section
create database tennisClub; use tennisClub; Create table Member( id integer auto_increment, firstname Varchar(30), surname Varchar(30), membertype Varchar(6), dateofbirth date, Primary Key(id) ); INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Oliver','Kerr','Senior','2000-01-31'); INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Morgan','Bartlett','Senior','1985-10-28'); INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Rebecca','House','Senior','1993-08-01'); INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Leslie','Hammond','Senior','1999-03-03'); INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Axel','Gibson','Senior','2007-09-29'); INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Bo','Bradshaw','Senior','1979-12-19');
Next, we will modify app/views/member/new.phtml to allow the user upload an image of themselves when they register as a new member in the system. Initially, we need to modify the form tag to include a multipart-form data setting. This will allow a file to be uploaded as part of the form. Replace the existing form tag at the top of the file with the following code.
<?php echo $this->tag->form( [ "member/create", "autocomplete" => "off", "class" => "form-horizontal", "enctype" => "multipart/form-data" ] ); ?>
Add the following <div></div> element at the bottom of the form before the end form tag.
<div class="form-group"> <label for="fieldImageFile" class="col-sm-2 control-label">Upload your Image</label> <div class="col-sm-10"> <?php echo $this->tag->fileField(["imageFile", "size" => 30, "class" => "form-control", "id" => "fieldImageFile"]) ?> </div> </div>
The member/views/new.phtml view will now look like this:
The final step is to add a line in the createAction() function of app/controllers/MemberController.php which will base64 encode the image and add it to the database into the blob field which was created to store it. Add the following line with the other setters in the createAction() function
A multipart form data post will upload an array of files and store them as temporary files. The above command gets the file name, passes it to file_get_contents() which in turn will pass the resultant information to be base64 encoded and uploaded to the database. As the user will only have the opportunity to upload one file, that file will be passed in getUplodadedFiles as the first element in the array.
In the next step, I will explain how to display this image on a view.