SoftDeleteBehavior

Anyone try to implement a SofDeletebehavior in Yii… i try the following implementation…

class SoftDeleteActiveRecordbehavior extends CActiveRecordbehavior {





	/**


	 * @see CActiveRecordbehavior::beforeDelete()


	 */


	public function beforeDelete () {


		$model = $this->getOwner();


		$model->setAttribute('deleted', true);


		$model->setAttribute('deleted_at', date('Y-m-d h:i:s'));


		$model->save();


		return false;


	}


}

there is a way to prevent default delete implementation in this method?

Nice!  I know some people prefer soft deletions.

It should prevent the default delete, unless you have beforeDelete() defined in the model and forget to call the parent implementation of beforeDelete().  It may be a bug otherwise…

Quote

Nice!  I know some people prefer soft deletions.

It should prevent the default delete, unless you have beforeDelete() defined in the model and forget to call the parent implementation of beforeDelete().  It may be a bug otherwise…

There is a way to override the beforeDelete() of model in the behavior?

something like



class SoftDeleteActiveRecordbehavior extends CActiveRecordbehavior {





	/**


	 * @see CActiveRecordbehavior::beforeDelete()


	 */


	public function beforeDelete () {


		$model = $this->getOwner();


                $model->getOwner()->beforeDelete = $this->foo;


	}


        


        public function foo(){





        }


}


No, what you did at first was fine, except I just noticed that Yii does not support canceling a delete from a behavior's beforeDelete().  This should be implanted IMHO. I'll create a ticket

Is there a way to run a method in a CModelbehavior before the execution of a find method in the model with this behavior?

Something like a beforeFind callback?

I want to do this to add merge some conditions to a query when a SoftDeletebehavior is attached to one model, to find only the records marked with the delete column equal to true

Bump.

I submitted an RFE here: http://code.google.c…s/detail?id=417

Quote

Bump.

I submitted an RFE here: http://code.google.c…s/detail?id=417

Humm… ok! Thanks!

I like your idea, but can’t get it working the way I want. I want to implement it the same way that AutoTimestampBehaviour does in the Skeleton App.

When I include the code you originally gave by putting the following in my model


public function behaviors(){

		return array(

			'SoftDeleteActiveRecordBehavior' => array(

				'class' => 'SoftDeleteActiveRecordBehavior',

			),

			'AutoTimestampBehavior' => array(

				'class' => 'AutoTimestampBehavior',

			)

		);

	}

it doen’t work - the record is deleted. The code is being loaded however - if I put some rubbish into the file SoftDeleteActiveRecordBehavior.php it does come up with an error as intended.

However if I put the code


public function beforeDelete () {

      $model = $this->getOwner();

      $model->setAttribute('deleted', true);

      $model->save();

      return false;

   }

directly in my model.php file it does work - ie my deleted field is set, and the record isn’t deleted.

What am I doing wrong? I’d like to implement the former rather than the latter.

are you using 1.07

according to this

http://code.google.com/p/yii/issues/detail?id=406&can=1&q=beforedelete

you would need 1.07 to make this work

here is my idea about logical delete:

http://www.yiiframework.com/forum/index.php?/topic/2335-ar-ext-for-logs-in-db-save-of-many-many-and-extra/

I hope is useful,

Paul

Would you mind posting that again with the attachments uploaded again?

It seems like the board messed up all attachments when it was updated

Yes, I’m using 1.07, (otherwise even the add in to the model.php wouldn’t work).

Re up the files.

If you find any bugs or have a better idea please give me feedback

Regards,

Paul

Hi,

I am trying to implement my version of SoftDeleteBehavoir. The main idea was to use beforeDelete to set "deleted" flag and use beforeFind to prevent "deleted" record from finding.

The code looks like:




class ARUndeletableBehavior extends CActiveRecordBehavior

{

    public function beforeFind($event)

    {

        $criteria = new CDbCriteria;

        $criteria->condition = "deleted = 0";

        $this->owner->dbCriteria->mergeWith($criteria);

    }


    public function beforeDelete($event)

    {

        $this->owner->deleted = true;

        $this->owner->save();


        //prevent real deletion

        $event->isValid = false;

    }

}



The problem is that beforeFind invoked for regular ActiveRecords, but does not invoked for objects constructed using "with" statement. For example following code works ("deleted" records not returned and ARUndeletableBehavior::beforeFind is invoked):




$comment = Comment::model()->findbyPk($id);



But this does not ("deleted" records are returned and ARUndeletableBehavior::beforeFind is not invoked):




$commentList = Comment::model()->with('author')->findAll();



So now I am able only to mark records as deleted, but can not automatically hide these records using behavior.

Hi,

my suggestion:

<?php

class SoftDeleteBehavior extends CActiveRecordBehavior

{

      public &#036;status='status';


      public &#036;valueDeleted = 'deletado';





public function beforeDelete(&#036;event)


{


    &#036;this-&gt;Owner-&gt;{&#036;this-&gt;status} = &#036;this-&gt;valueDeleted;


    &#036;this-&gt;Owner-&gt;save();





    //prevent real deletion


    &#036;event-&gt;isValid = false;


}





public function deleteds() {


                &#036;this-&gt;Owner-&gt;getDbCriteria()-&gt;mergeWith(array(


                    'condition'=&gt;&#036;this-&gt;status.&quot;='&#036;this-&gt;valueDeleted'&quot;


                ));


                return &#036;this-&gt;Owner;


      }

public function notdeleteds() {

                &#036;this-&gt;Owner-&gt;getDbCriteria()-&gt;mergeWith(array(


                                    'condition'=&gt;&#036;this-&gt;status.&quot;&lt;&gt;'&#036;this-&gt;valueDeleted'&quot;


                ));


                return &#036;this-&gt;Owner;


      }

}

?>

I recall reading that with() is implemented in CActiveFinder, so you might be able to override its behavior to censor the result set. I haven’t tried it though, so I don’t know how practical that would be. Good luck! In fact I hope you addressed this long ago.

Ivo

Thanks for reply, Ivo. It seems CActiveFinder does not have behaviors. There are many ways to workaround this problem. In my case I added defaultScope() methods to my models to filter soft deleted records. Actually CActiveFinder is a good abstraction layer designed to be transparent and invisible, but here we have a case when this abstraction fails to be transparent.

P.S. I just checked CActiveFinder code again and there is a good chance that this problem is solved in Yii 1.1, because in Yii 1.0.9 there was no beforeFind() method call in CActiveFinder, but it is in Yii 1.1 RC.

hi,

Can you also explain which file to edit ?

OR

Which file I should add this code ?

class SoftDeleteBehavior extends CActiveRecordBehavior

{

}

protected/controller/TableNameController.php

or

protected/models/TableName.php

or

protected/views/TableName/_form.php

protected/views/TableName/_search.php

protected/views/TableName/_view.php

protected/views/TableName/admin.php

protected/views/TableName/create.php

protected/views/TableName/index.php

protected/views/TableName/update.php

protected/views/TableName/view.php

I put mine in protected/components/behaviors/SoftDeleteBehaviour.php then in the model include


public function behaviors(){

		return array(

            'SoftDeleteBehavior' => array(

            'class' => 'application.components.behaviors.SoftDeleteBehavior',			)

		);

	}