The Active Record Cannot Be Deleted Because It Is New

Здравствуйте.

Проблема следующая. В контроллере, в actionDelete при удаление записи через $this->loadModel($id)->delete(); которая, кстати, генерируется по умолчанию в контроллере через gii, выдается ошибка "The active record cannot be deleted because it is new".

При том при всем, в контроллере userController, созданным по учебнику с идентичным по сути кодом, все удаляется.

Я новичек в Yii и очень прошу помощи.

А покжите код контроллера и модели.

Контроллер:


<?php


class ImagesController 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';


	/**

	 * @return array action filters

	 */

	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',  // allow all users to perform 'index' and 'view' actions

				'actions'=>array('index','view'),

				'users'=>array('admin'),

			),

			array('allow', // allow authenticated user to perform 'create' and 'update' actions

				'actions'=>array('create','update'),

				'users'=>array('admin'),

			),

			array('allow', // allow admin user to perform 'admin' and 'delete' actions

				'actions'=>array('admin','delete'),

				'users'=>array('admin'),

			),

			array('deny',  // deny all users

				'users'=>array('*'),

			),

		);

	}


	/**

	 * 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 Images;

		

    if(isset($_POST['Images'])) {

      $model->id_image=CUploadedFile::getInstance($model, 'filesrc');

      $model->attributes=$_POST['Images'];

      $model->filename = !$model->filename || $model->filename == "" ? $model->id_image->name : $model->filename;

      

      $newImageFullPath = $model->getImagePath();

      $newPreviewFullPath = $model->getPreviewPath();

			

      $model->filesrc = $newImageFullPath;

      $model->previewsrc = $newPreviewFullPath;

      

      if($model->save()) {

          $model->id_image->saveAs($newImageFullPath);

          $resizeImage = Yii::app()->image->load($newImageFullPath);

					$resizeImage->resize($model->imageMaxWidth, $model->imageMaxHeight);

					$resizeImage->save();

					copy($model->getRootPath().$newImageFullPath, $model->getRootPath().$newPreviewFullPath);

					$resizePreview = Yii::app()->image->load($newPreviewFullPath);

					$resizePreview->resize($model->previewMaxWidth, $model->previewMaxHeight);

					$resizePreview->save();

					$this->redirect(array('view','id'=>$model->id));

      }

    }

    $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['Images']))

		{

			$model->attributes=$_POST['Images'];

			if($model->save())

				$this->redirect(array('view','id'=>$model->id));

		}


		$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();

		$Image = Images::model()->findByPk($id);

		$Image->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'));

	}

	

	/*protected function afterDelete()

	{

    parent::afterDelete();

    $model = new Images;

		$item = $this->loadModel($id);

		$item->delete();

		$rootPath =$model->getRootPath(); 

		$attribs = $item->attributes;

		$filesToDelete = array($attribs['filesrc'], $attribs['previewsrc']);

		foreach($filesToDelete as $file) {

			$file = $rootPath.$file;

			var_dump($file);

			//unset($file);

		}

	}*/


	/**

	 * Lists all models.

	 */

	public function actionIndex()

	{

		$dataProvider=new CActiveDataProvider('Images');

		$this->render('index',array(

			'dataProvider'=>$dataProvider,

		));

	}


	/**

	 * Manages all models.

	 */

	public function actionAdmin()

	{

		$model=new Images('search');

		$model->unsetAttributes();  // clear any default values

		if(isset($_GET['Images']))

			$model->attributes=$_GET['Images'];


		$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 $id the ID of the model to be loaded

	 * @return Images the loaded model

	 * @throws CHttpException

	 */

	public function loadModel($id)

	{

		$model=Images::model()->findByPk($id);

		if($model===null)

			throw new CHttpException(404,'The requested page does not exist.');

		return $model;

	}


	/**

	 * Performs the AJAX validation.

	 * @param Images $model the model to be validated

	 */

	protected function performAjaxValidation($model)

	{

		if(isset($_POST['ajax']) && $_POST['ajax']==='images-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}

}



Модель:


<?php


class Images extends ImagesBase

{

	

	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'tbl_images';

	}


	/**

	 * @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('filesrc', 'required'),

			array('filename', 'length', 'max'=>255),

			array('filesrc', 'file', 'types'=>'jpg, gif, png', 'maxSize'=>1048576),

		);

	}


	/**

	 * @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(

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'id' => 'ID',

			'filename'=>'File Name',

			'filesrc'=>'Image',

			'previewsrc' => 'Image preview',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 *

	 * Typical usecase:

	 * - Initialize the model fields with values from filter form.

	 * - Execute this method to get CActiveDataProvider instance which will filter

	 * models according to data in model fields.

	 * - Pass data provider to CGridView, CListView or any similar widget.

	 *

	 * @return CActiveDataProvider the data provider that can return the models

	 * based on the search/filter conditions.

	 */

	public function search()

	{

		// @todo Please modify the following code to remove attributes that should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);

		$criteria->compare('filename',$this->filename,true);

		$criteria->compare('filesrc',$this->filesrc,true);

		$criteria->compare('previewsrc',$this->previewsrc,true);


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}


	/**

	 * Returns the static model of the specified AR class.

	 * Please note that you should have this exact method in all your CActiveRecord descendants!

	 * @param string $className active record class name.

	 * @return Images the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}

}



ImagesBase.php (дополнительный файл к моделе):


<?php


class ImagesBase extends CActiveRecord

{

	

	/*

		There are base variables

		and functions 

		for images model working

	*/

	public $id_image;

	public $uniqName;

	public $fileExt;

	public $imgfolder = "images/upload/";

	public $previewSubFolder = "preview/";

	public $projPath = "/testdrive/";

	public $imageMaxWidth = 640;

	public $imageMaxHeight = 480;

	public $previewMaxWidth = 120;

	public $previewMaxHeight = 90;

	

	function __construct() {

		$this->uniqName = $this->getUniqName();

		if($id_image) {

			$this->fileExt = $this->getFileExt();

		}

		

		parent::__construct();

	}

	

	public function getRootPath() {

		return $_SERVER['DOCUMENT_ROOT'].$this->projPath;

	}

	

	public function getFileExt($filename=null) {

		preg_match('/([^\.])+$/', $filename === null ? $this->id_image->name : $filename, $match);

		return $match[0];

	}

	

	public function getUniqName() {

		return rand( 545, 1514554 ).md5(strtotime(date("now")));

	}

	

	function getImagePath() {

    return $this->imgfolder.$this->uniqName.".".$this->getFileExt();

	}

	

	function getPreviewPath() {

		return $this->imgfolder.$this->previewSubFolder.$this->uniqName.".".$this->getFileExt();

	}


}

Похоже, что Вы поломали конструктор модели.

Попробуйте одно из двух:

– ЛИБО используйте afterConstruct() вместо переопределения __construct (это рекомендованный способ)

Только не забудьте тоже вызвать parent::afterConstruct

– ЛИБО исправьте


public function __construct()

на


public function __construct($scenario='insert')

и, соответственно, не забудьте передать в парент


parent::__construct($scenario);

Иначе при populateRecord вызовется конструктор с непустым значением scenario и сработает setIsNewRecord(true).

Спасибо большое. Воспользовался первым вариантом (рекомендованный способ) и все получилось!