Uploading an Image and Saving it to a Database in Yii

Uploading an Image and Saving it to a Database in Yii

Last updated:

DISCLAIMER: Most of the time it is not recommended to store images on a database. This tutorial/guide is meant to explain how to do it in the few cases where it is ok to store images in a database.

Assuming you have a table in a database with an attribute called "logo" which is of type "BLOB" and you're using the ActiveRecord model as a FormModel, here's how you should proceed:

In your AR Model:

  • add this line to the rules() method
 <?php
 ['logo', 'file', 'types' => 'jpg,jpeg,png,gif', 'allowEmpty' => true]
  • add a beforeSave() method:

    <?php
    public function beforeSave() {
        if ($file = CUploadedFile::getInstance($this, 'logo')) {
            $this->logo = file_get_contents($file->tempName);
        }
        return parent::beforeSave();
    }
    

In the Controller

  • save the model as follows: ("Client" is what my AR model is called. You replace it with your model's name)

    <?php
    if (isset($_POST['Client'])) {
        $model = $_POST['Client'];
        $ar = new Client;
        $ar->attributes = $model;
        if ($ar->save()) {
            Yii::app()->user->setFlash('success', 'Client successfully added.');
            $this->redirect(['client/index', 'id' => $ar->id]);
        } else {
            Yii::app()->user->setFlash('error', 'There was an error. Please correct your input and/or try again later');
            $this->refresh();
        }
    }
    

    In the View (where you will place the upload form)

  • make sure your form is of the right type: (pay attention to the "stateful" and "enctype" properties)

    <?php
    $form = $this->beginWidget('CActiveForm', [
        'id' => 'Client-form',
        'enableAjaxValidation' => true,
        'enableClientValidation' => true,
        'stateful' => true,
        'htmlOptions' => ['enctype' => 'multipart/form-data'],
    ]);
    
  • the form item itself should be of type "fileField":

    <div class="row">
        <?php echo $form->labelEx($model, 'logo'); ?>
        <?php echo $form->fileField($model, 'logo'); ?>
        <?php echo $form->error($model, 'logo'); ?>
    </div>
    

In the View (where you will display the image)

  • base64_encode your image data and send it using this neat trick: (again, "logo" is what my attribute is called. Replace it with yours). Also, the mime type used here should match your image's format. There are many php functions that help you do that.

        <img src="data:image/jpeg;base64,<?= base64_encode($model->logo) ?>" height="100%" width="100%" />
    

Dialogue & Discussion