Не работает загрузка файлов после добавления поля в таблицу.

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Закрыто
lordius
Сообщения: 25
Зарегистрирован: 2013.01.15, 15:25

Не работает загрузка файлов после добавления поля в таблицу.

Сообщение lordius »

Всем привет, в общем ситуация такова, делал загрузку файлов по рецепту
http://www.yiiframework.ru/doc/cookbook ... .fat.model
Все раньше работало ок, добавил в бд 1 поле и поправил вюхи, контролери, модели под него.
После этого перестала работать загрузка файлов. Думал права на папку, но не так. Пока что вижу проблему
в том что не передает в пост запросе название файла и логи такие.
Позже вардампом проверил что не можна взять ($file=CUploadedFile::getInstance($this->owner,'image1')) там пустое значения, а раньше работало.
Как и было сказано в рецепте убрал валидацию на поле файла в моделе.
2013/03/29 13:00:38 [warning] [application] Не удалось присвоить небезопасный атрибут "image1" класса "Vips".
in /var/www/release/ukrburshtyn.com/protected/modules/admin/controllers/VipsController.php (102)
in /var/www/release/ukrburshtyn.com/index.php (16)
код модели:

Код: Выделить всё

<?php

/**
 * This is the model class for table "vips".
 *
 * The followings are the available columns in table 'vips':
 * @property string $index
 * @property string $category
 * @property string $name
 * @property string $artno
 * @property string $description
 * @property string $url
 * @property double $price
 * @property string $image1
 * @property string $image2
 * @property string $image3
 * @property string $image4
 * @property string $image5
 * @property string $new
 * @property string $main
 * @property integer $priority
 * @property string $meta_title
 * @property string $meta_keywords
 * @property string $meta_description
 * @property string $lider
 * @property string $special
 */
class Vips extends CActiveRecord
{
    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Vips the static model class
     */
        public $savePathAlias='webroot.media';
        public $groupName='vips';
        public $saveDir ='media';
        public $originals ='originals';
        public $sizes = array('thumb','big','tiny');
        
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'vips';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('price, meta_keywords, meta_description', 'required'),
            array('priority', 'numerical', 'integerOnly'=>true),
            array('price', 'numerical'),
            array('category, new, main, lider, special', 'length', 'max'=>10),
            array('meta_title, url,alt1', 'length', 'max'=>255),
            array('name, artno, description,  alt1', 'safe'),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('index, category, name, artno, description, url, price, alt1, new, main, priority, meta_title, meta_keywords, meta_description, lider, special', 'safe', 'on'=>'search'),
        );
    }

     /**
         * @return array relational rules.
         */
        public function relations()
        {
                // NOTE: you may need to adjust the relation name and the related
                // class name for the relations automatically generated below.
                return array(
                        'category' => array(self::BELONGS_TO, 'VipsCategories', 'index'),
                );
        }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'index' => 'Index',
            'category' => 'Category',
            'name' => 'Name',
            'artno' => 'Artno',
            'description' => 'Description',
            'price' => 'Price',
                        'url' => 'Url',
            'image1' => 'Image1',
                        'alt1' => 'alt1',
            'image2' => 'Image2',
            'image3' => 'Image3',
            'image4' => 'Image4',
            'image5' => 'Image5',
            'new' => 'New',
            'main' => 'Main',
            'priority' => 'Priority',
            'meta_title' => 'Meta Title',
            'meta_keywords' => 'Meta Keywords',
            'meta_description' => 'Meta Description',
            'lider' => 'Lider',
            'special' => 'Special',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;

        $criteria->compare('index',$this->index,true);
        $criteria->compare('category',$this->category,false);
        $criteria->compare('name',$this->name,true);
        $criteria->compare('artno',$this->artno,true);
        $criteria->compare('description',$this->description,true);
        $criteria->compare('price',$this->price);
                $criteria->compare('url',$this->url);
        $criteria->compare('image1',$this->image1,true);
                $criteria->compare('alt1',$this->alt1,true);
        $criteria->compare('image2',$this->image2,true);
        $criteria->compare('image3',$this->image3,true);
        $criteria->compare('image4',$this->image4,true);
        $criteria->compare('image5',$this->image5,true);
        $criteria->compare('new',$this->new,true);
        $criteria->compare('main',$this->main,true);
        $criteria->compare('priority',$this->priority);
        $criteria->compare('meta_title',$this->meta_title,true);
        $criteria->compare('meta_keywords',$this->meta_keywords,true);
        $criteria->compare('meta_description',$this->meta_description,true);
        $criteria->compare('lider',$this->lider,true);
        $criteria->compare('special',$this->special,true);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
        ));
    }
         public function behaviors(){
                return array(
                    // наше поведение для работы с файлом
                    'uploadableFile'=>array(
                        'class'=>'application.modules.admin.components.UploadableFileBehavior',
                        'savePathAlias' =>  $this->savePathAlias,
                        'groupName'    => $this->groupName,
                        'sizes' => $this->sizes,
                         'originals' => $this->originals,
                        // конфигурируем нужные свойства класса UploadableFileBehavior
                        // ...
                    ),
                );
        }
} 
Код контролера.

Код: Выделить всё

<?php

class VipsController extends Controller
{
    /**
     * @var string the default layout for the views. Defaults to '//layouts/column2', meaning
     * using two-column layout. See 'protected/views/layouts/column2.php'.
     */
    public $layout='/layouts/column2';

    public function filters()
    {
        return array(
            'accessControl', // perform access control for CRUD operations
            'postOnly + delete', // we only allow deletion via POST request
        );
    }

    /**
     * Specifies the access control rules.
     * This method is used by the 'accessControl' filter.
     * @return array access control rules
     */
    public function accessRules()
    {
            return array(
                array('allow',
                'actions'=>array('*'),
                'expression'=>'$user->getIsAdmin()',
            ),                
        );
    }
        
        
    /**
     * Displays a particular model.
     * @param integer $id the ID of the model to be displayed
     */
    public function actionView($id)
    {
        $this->render('view',array(
            'model'=>$this->loadModel($id),
        ));
    }

    
    
        /**
     * Creates a new model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     */
    public function actionCreate()
    {
        $model=new Vips;

        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);

        if(isset($_POST['Vips']))
        {
            $model->attributes=$_POST['Vips'];
            if($model->save())
                $this->redirect(array('view','id'=>$model->index));
        }

        $this->render('create',array(
            'model'=>$model,
        ));
    }

    /**
     * Updates a particular model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id the ID of the model to be updated
     */
    public function actionUpdate($id)
    {
        $model=$this->loadModel($id);

        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);

        if(isset($_POST['Vips']))
        {
            $model->attributes=$_POST['Vips'];
                        //var_dump($model->attributes);exit();
            if($model->save())
                $this->redirect(array('view','id'=>$model->index));
        }

        $this->render('update',array(
            'model'=>$model,
        ));
    }

    /**
     * Deletes a particular model.
     * If deletion is successful, the browser will be redirected to the 'admin' page.
     * @param integer $id the ID of the model to be deleted
     */
    public function actionDelete($id)
    {
        $this->loadModel($id)->delete();

        // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
        if(!isset($_GET['ajax']))
            $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
    }

    /**
     * Lists all models.
     */
    public function actionIndex()
    {
        $dataProvider=new CActiveDataProvider('Vips');
        $this->render('index',array(
            'dataProvider'=>$dataProvider,
        ));
    }

        /**
     * Manages all models.
     */
    public function actionAdmin()
    {
        $model=new Vips('search');
        $model->unsetAttributes();  // clear any default values
        if(isset($_GET['Vips']))
            $model->attributes=$_GET['Vips'];

        $this->render('admin',array(
            'model'=>$model,
        ));
    }
    

    /**
     * Returns the data model based on the primary key given in the GET variable.
     * If the data model is not found, an HTTP exception will be raised.
     * @param integer the ID of the model to be loaded
     */
    public function loadModel($id)
    {
        $model=Vips::model()->findByPk($id);
        if($model===null)
            throw new CHttpException(404,'The requested page does not exist.');
        return $model;
    }

    /**
     * Performs the AJAX validation.
     * @param CModel the model to be validated
     */
    protected function performAjaxValidation($model)
    {
        if(isset($_POST['ajax']) && $_POST['ajax']==='vips-form')
        {
            echo CActiveForm::validate($model);
            Yii::app()->end();
        }
    }
}
 
Код формы:

Код: Выделить всё

<?php
/* @var $this VipsController */
/* @var $model Vips */
/* @var $form CActiveForm */
?>

<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'vips-form',
    'enableAjaxValidation'=>false,
)); ?>

    <p class="note">Fields with <span class="required">*</span> are required.</p>

    <?php echo $form->errorSummary($model); ?>

    
    

      
    <div class="row">
        <?php echo $form->labelEx($model,'category'); ?>
        <?php // echo $form->textField($model,'category',array('size'=>10,'maxlength'=>10)); ?>
                <?php echo $form->dropDownList($model,'category', CHtml::listData(VipsCategories::model()->findAll(array('order' => 'name')),'index','name'));?>
        <?php echo $form->error($model,'category'); ?>
    </div>
        
        <div class="row">
        <?php echo $form->labelEx($model,'price'); ?>
        <?php echo $form->textField($model,'price'); ?>
        <?php echo $form->error($model,'price'); ?>
    </div>

    <div class="row">
        <?php echo $form->labelEx($model,'name'); ?>
        <?php echo $form->textArea($model,'name',array('rows'=>6, 'cols'=>50)); ?>
        <?php echo $form->error($model,'name'); ?>
    </div>

    <div class="row">
        <?php echo $form->labelEx($model,'url'); ?>
        <?php echo $form->textArea($model,'url',array('rows'=>6, 'cols'=>50)); ?>
        <?php echo $form->error($model,'url'); ?>
    </div>

    <div class="row">
        <?php echo $form->labelEx($model,'artno'); ?>
        <?php echo $form->textArea($model,'artno',array('rows'=>6, 'cols'=>50)); ?>
        <?php echo $form->error($model,'artno'); ?>
    </div>

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

    <div class="row">
        <?php echo $form->labelEx($model,'meta_title'); ?>
        <?php echo $form->textField($model,'meta_title',array('size'=>60,'maxlength'=>255)); ?>
        <?php echo $form->error($model,'meta_title'); ?>
    </div>

    <div class="row">
        <?php echo $form->labelEx($model,'meta_keywords'); ?>
        <?php echo $form->textArea($model,'meta_keywords',array('rows'=>6, 'cols'=>50)); ?>
        <?php echo $form->error($model,'meta_keywords'); ?>
    </div>

    <div class="row">
        <?php echo $form->labelEx($model,'meta_description'); ?>
        <?php echo $form->textArea($model,'meta_description',array('rows'=>6, 'cols'=>50)); ?>
        <?php echo $form->error($model,'meta_description'); ?>
    </div>
        
          <div class="row">
        <?php echo $form->labelEx($model,'new'); ?>
                <?php echo $form->checkBox($model,'new', array('value'=>1, 'uncheckValue'=>0)); ?>
        <?php echo $form->error($model,'new'); ?>
    </div>

    <div class="row">
        <?php echo $form->labelEx($model,'main'); ?>
                <?php echo $form->checkBox($model,'main', array('value'=>1, 'uncheckValue'=>0)); ?>
        <?php echo $form->error($model,'main'); ?>
    </div>
            
    <div class="row">
        <?php echo $form->labelEx($model,'lider'); ?>
                <?php echo $form->checkBox($model,'lider', array('value'=>1, 'uncheckValue'=>0)); ?>
        <?php echo $form->error($model,'lider'); ?>
    </div>

    <div class="row">
        <?php echo $form->labelEx($model,'special'); ?>
                <?php echo $form->checkBox($model,'special', array('value'=>1, 'uncheckValue'=>0)); ?>
        <?php echo $form->error($model,'special'); ?>
    </div>
        
        <div class="row">
        <?php echo $form->labelEx($model,'description'); ?>
        <?php echo $form->textArea($model,'description',array('rows'=>6, 'cols'=>50,'class'=>'tinymce ')); ?>
        <?php echo $form->error($model,'description'); ?>
    </div>

         <div class="field">
            <?php if($model->image1): ?>
                        
                
                     
                
            <?php endif; ?>
            <?php echo $form->labelEx($model,'image1'); ?>
            <?php echo $form->fileField($model,'image1'); ?>
            <?php echo $form->error($model,'image1'); ?>
        </div>
        
        <div class="row">
        <?php echo $form->labelEx($model,'alt1'); ?>
        <?php echo $form->textField($model,'alt1',array('size'=>60,'maxlength'=>255)); ?>
        <?php echo $form->error($model,'alt1'); ?>
    </div>

    <div class="field">
            <?php if($model->image2): ?>
           
            <?php endif; ?>
            <?php echo $form->labelEx($model,'image2'); ?>
            <?php echo $form->fileField($model,'image2'); ?>
            <?php echo $form->error($model,'image2'); ?>
        </div>

    <div class="field">
            <?php if($model->image3): ?>
              
            <?php endif; ?>
            <?php echo $form->labelEx($model,'image3'); ?>
            <?php echo $form->fileField($model,'image3'); ?>
            <?php echo $form->error($model,'image3'); ?>
        </div>

    <div class="field">
            <?php if($model->image4): ?>
             
            <?php endif; ?>
            <?php echo $form->labelEx($model,'image4'); ?>
            <?php echo $form->fileField($model,'image4'); ?>
            <?php echo $form->error($model,'image4'); ?>
        </div>

    <div class="field">
            <?php if($model->image5): ?>
               
            <?php endif; ?>
            <?php echo $form->labelEx($model,'image5'); ?>
            <?php echo $form->fileField($model,'image5'); ?>
            <?php echo $form->error($model,'image5'); ?>
        </div>


      <div class="form-actions">
            <?php $this->widget('bootstrap.widgets.TbButton', array('buttonType'=>'submit', 'type'=>'primary', 'label'=>$model->isNewRecord ? 'Create' : 'Save')); ?>
            <?php $this->widget('bootstrap.widgets.TbButton', array('buttonType'=>'reset', 'label'=>'Reset')); ?>
        </div>
<?php $this->endWidget(); ?>

</div><!-- form -->
Код поведения:

Код: Выделить всё

<?php

/**
 * @property string $savePath путь к директории, в которой сохраняем файлы
 */
class UploadableFileBehavior extends CActiveRecordBehavior{
    /**
     * @var string название атрибута, хранящего в себе имя файла и файл
     */
    public $attributesName=array('image1','image2','image3','image4','image5');
    /**
     * @var string алиас директории, куда будем сохранять файлы
     */
    public $savePathAlias='webroot.media';
    /**
     * @var array сценарии валидации к которым будут добавлены правила валидации
     * загрузки файлов
     */
    public $scenarios=array('insert','update');
    /**
     * @var string типы файлов, которые можно загружать (нужно для валидации)
     */
    public $fileTypes='png,gif,jpg,jpeg';
    
    public $groupName='';
    public $sizes = array('thumb');
    public $originals='';
 
    /**
     * Шорткат для Yii::getPathOfAlias($this->savePathAlias).DIRECTORY_SEPARATOR.
     * Возвращает путь к директории, в которой будут сохраняться файлы.
     * @return string путь к директории, в которой сохраняем файлы
     */
    public function getSavePath(){
        
        return Yii::getPathOfAlias($this->savePathAlias).DIRECTORY_SEPARATOR;
    }
 
    public function attach($owner){
        parent::attach($owner);
 
        if(in_array($owner->scenario,$this->scenarios)){
            // добавляем валидатор файла
            foreach($this->attributesName as $key => $value){
                $fileValidator=CValidator::createValidator('file',$owner,$value,
                    array('types'=>$this->fileTypes,'allowEmpty'=>true));
                $owner->validatorList->add($fileValidator);
            }
        }
    }
 
  
    public function beforeSave($event){
        foreach($this->attributesName as $key => $value){
            if(in_array($this->owner->scenario,$this->scenarios) &&
                ($file=CUploadedFile::getInstance($this->owner,'image1'))){
                $this->deleteFile(); // старый файл удалим, потому что загружаем новый

                $this->owner->setAttribute($value,$file->name);
                //var_dump($this->getSavePath().$this->groupName.DIRECTORY_SEPARATOR.$this->originals.DIRECTORY_SEPARATOR.$file->name);exit();
                $file->saveAs($this->getSavePath().$this->groupName.DIRECTORY_SEPARATOR.$this->originals.DIRECTORY_SEPARATOR.$file->name);
                
            }
        }
        return true;
    }
 
    public function beforeDelete($event){
        $this->deleteFile(); // удалили модель? удаляем и файл, связанный с ней
    }
 
    public function deleteFile(){
         foreach($this->attributesName as $key => $value){
            $filePath=$this->savePath.$this->owner->getAttribute($value);
         }
        if(@is_file($filePath))
            @unlink($filePath);
    }
} 
lordius
Сообщения: 25
Зарегистрирован: 2013.01.15, 15:25

Re: Не работает загрузка файлов после добавления поля в табл

Сообщение lordius »

В общем откатался на старую версию, но все равно картинки не всегда загружаются, для одни моделей норм, для других нет, пока не знаю как лучше сделать, для бд обновление сделал выставлением вручную атрибутов модели.

Код: Выделить всё

$model->attributes=$_POST['Vips'];
                        //var_dump($model->attributes);exit();
                        $model->image1=$_POST['Vips']['image1'];
                        $model->image2=$_POST['Vips']['image2'];
                        $model->image3=$_POST['Vips']['image3'];
                        $model->image4=$_POST['Vips']['image4'];
                        $model->image5=$_POST['Vips']['image5']; 
но инстанс файла как был пустой так и остался, интересно почему.
($file=CUploadedFile::getInstance($this->owner,'image1'))
lordius
Сообщения: 25
Зарегистрирован: 2013.01.15, 15:25

Re: Не работает загрузка файлов после добавления поля в табл

Сообщение lordius »

В общем стыдно немного друзья, на картинках просто стоит опция 'htmlOptions'=>array(
'enctype'=>'multipart/form-data'), а на других формах не поставил. В общем в этом была проблема теперь пофиксил.
Закрыто