title: Yii - File validation rules sets JSON array to NULL when saving to DB
body: <p>When I added file type checking, things broke :)</p>
  
  <p>I originally had just this rule:</p>
  
  <pre><code>array('image, pictures, documents', 'default', 'setOnEmpty' =&gt; true, 'value' =&gt; ''),
  </code></pre>
  
  <p>It all worked fine, except there was no security on the types of files being uploaded. So I added the rules (seen below) to allow only certain file types, max size, and max number.</p>
  
  <p><strong>Problem:</strong> After adding the filetype checks, the update is all broken. Non used file fields on the form, are being set to NULL, instead of the old value that was in the database before.</p>
  
  <p><strong>Symptom:</strong> When I edit a record that has images or documents set (image, pictures, or documents), they ALL get reset! I have more fields, like name, description, ect. I could edit just the name, and not touch any of the uploaded file fields. Poof, they all are empty. So when the model saves, it replaces the existing values with nothing. So we lose the images, or documents, saved for that record!</p>
  
  <p>Now, if I do try to change one of the files. Say I have an image, but do not have pictures or documents... If I add a document, the document gets saved into the db, but the original image gets removed (the value in the db is gone). It should not have been touched.</p>
  
  <p>The other fields on the form are still there, so they are not magically getting reset. Name, Description, all of them are still there. Only the ones defined by the file validation rules are reset.</p>
  
  <p>When I create a new record, it works like it should.</p>
  
  <p>It seems to just be when updating a record, all the file fields get reset when saved in the database.</p>
  
  <p>Model:</p>
  
  <pre><code>public function rules()
  {
      return array(
          array('image','file', 'allowEmpty' =&gt; true, 'types'=&gt;'jpg, gif, png, jpeg', 'maxSize'=&gt;1024 * 1024 * 1, 'tooLarge'=&gt;'File has to be smaller than 1MB'),
          array('pictures','file', 'allowEmpty' =&gt; true, 'types'=&gt;'jpg, gif, png, jpeg', 'maxSize'=&gt;1024 * 1024 * 1, 'tooLarge'=&gt;'File has to be smaller than 1MB', 'maxFiles' =&gt; 10, 'tooMany'=&gt;'You have selected too many files!'),
          array('documents','file', 'allowEmpty' =&gt; true, 'types'=&gt;'doc, docx, pdf, ppt, psd, rtf, txt, xls, xlsx, csv', 'maxSize'=&gt;1024 * 1024 * 10, 'tooLarge'=&gt;'File has to be smaller than 10MB', 'maxFiles' =&gt; 10, 'tooMany'=&gt;'You have selected too many files!'),
      );
  }
  </code></pre>
  
  <p>Controller:</p>
  
  <pre><code>public function actionUpdate($id)
  {
      $uid = Yii::app()-&gt;user-&gt;id;
      $model=$this-&gt;loadModel($id);
  
      if ( $model-&gt;uid !== $uid ) {
          $this-&gt;redirect(array('index'));
      }
  
      // Uncomment the following line if AJAX validation is needed
      // $this-&gt;performAjaxValidation($model);
  
      $origImage = $model-&gt;image;
      $origPictures = $model-&gt;pictures;
      $origDocuments = $model-&gt;documents;
  
      if(isset($_POST['Titles']))
      {
          $model-&gt;attributes=$_POST['Titles'];
          $model-&gt;image = $origImage;             // we are not ready to reset them yet
          $model-&gt;pictures = $origPictures;       // we are not ready to reset them yet
          $model-&gt;documents = $origDocuments;     // we are not ready to reset them yet
  
          $imageInstance = CUploadedFile::getInstance($model, 'image');
          $picturesInstance = CUploadedFile::getInstances($model, 'pictures');
          $documentsInstance = CUploadedFile::getInstances($model, 'documents');
  
          if($model-&gt;validate())
          {
              //die(var_dump($model-&gt;image));  //POOF - Here is where it's reset
              if($model-&gt;save())
              {
                  // do more stuff here
              }
          }
      }
  }
  </code></pre>
  
  <p>You can see my "POOF - Here is where its reset" comment, which is where I have  a die command to show me the value of $model->image. Using die() allows me to hit refresh and makes testing uploads easier.</p>
  
  <p>That die command shows $model->image as NULL... It should be the old value that was in the database BEFORE updating (when it's not used in the form).</p>
  
  <p>Why is $model->validate setting 'image' to null?</p>
  
  <p>Example of 'image' value, JSON encoded array:</p>
  
  <pre><code>[{"image":"18a18923c449cb0b6f2326ea43f2aec6.jpg","thumb":"18a18923c449cb0b6f2326ea43f2aec6_thumb.jpg"}]
  </code></pre>
  
  <p>NOTE: documents store more info, like file extension and the files original name before the random hash.</p>
  
  <p>Maybe the JSON array (above) is failing the validation, and that's why it is set to NULL? If so, how do I allow saving the JSON arrays in these fields?</p>
  
  <p>The JSON allows me to track things like filename, thumbnail, extension, name, description. So later I could allow the user to add a custom name or description or each image (or document). So I DO NEED more info than just the filename.</p>
  
  <p>If it was not for needing the name, description, etc... I would just store the filename, and add "_thumb" to it for the thumbnail.. Unfortunately, I need to save more data.</p>
  
  <p>Any help is greatly appreciated!</p>