php - tutorial - Yii: no se pueden eliminar las cosas del panel de administración
yii vs laravel (2)
Soy un yiibie y estoy teniendo un problema que cualquier evento que estoy tratando de eliminar no se borra y me da un error que es
Error 500: <h1>CDbException</h1>
<p>CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`response_system`.`user_join_event`, CONSTRAINT `fk_user_join_event_event1` FOREIGN KEY (`event_id`) REFERENCES `event` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION). The SQL statement executed was: DELETE FROM `event` WHERE `event`.`id`=18 (C:/wamp/apps/yii/db/CDbCommand.php:357)</p><pre>#0 C:/wamp/apps/yii/db/ar/CActiveRecord.php(1745): CDbCommand->execute().
Puedo actualizar fácilmente el evento como si pudiera actualizar la imagen, pero no puedo eliminarla. Este es mi EventController
class EventController extends RController
{
/**
* @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/admin'';
/**
* @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
''rights'',
);
}
/**
* 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(''*''),
),
array(''allow'', // allow authenticated user to perform ''create'' and ''update'' actions
''actions''=>array(''create'',''update''),
''users''=>array(''@''),
),
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),
));
}
public function actionAllevent()
{
$allmodels=Event::model()->findAll(array(''order''=>''id DESC''));
$this->layout=''main'';
$this->render(''allevent'' ,array(''allmodels''=>$allmodels));
}
/**
* Creates a new model.
* If creation is successful, the browser will be redirected to the ''view'' page.
*/
public function actionCreate()
{
$model=new Event;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST[''Event'']))
{
$rnd = rand(0,9999); // generate random number between 0-9999
$model->attributes=$_POST[''Event''];
$uploadedFile=CUploadedFile::getInstance($model,''image'');
$fileName = "{$rnd}-{$uploadedFile}"; // random number + file name
$model->image = $fileName;
if($model->save())
{
$uploadedFile->saveAs(Yii::app()->basePath.''/../img/''.$fileName); // image will uplode to rootDirectory/event/
$this->redirect(array(''admin''));
}
$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[''Event'']))
{
$_POST[''Event''][''image''] = $model->image;
$model->attributes=$_POST[''Event''];
$uploadedFile=CUploadedFile::getInstance($model,''image'');
if($model->save())
{
if(!empty($uploadedFile)) // check if uploaded file is set or not
{
$uploadedFile->saveAs(Yii::app()->basePath.''/../img/''.$model->image);
}
$this->redirect(array(''admin''));
}
$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)
{
if(Yii::app()->request->isPostRequest)
{
// we only allow deletion via POST request
$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''));
}
else
throw new CHttpException(400,''Invalid request. Please do not repeat this request again.'');
}
/**
* Lists all models.
*/
public function actionIndex()
{
$dataProvider=new CActiveDataProvider(''Event'');
$this->render(''index'',array(
''dataProvider''=>$dataProvider,
));
}
/**
* Manages all models.
*/
public function actionAdmin()
{
$model=new Event(''search'');
$model->unsetAttributes(); // clear any default values
if(isset($_GET[''Event'']))
$model->attributes=$_GET[''Event''];
$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 Event the loaded model
* @throws CHttpException
*/
public function loadModel($id)
{
$model=Event::model()->findByPk($id);
if($model===null)
throw new CHttpException(404,''The requested page does not exist.'');
return $model;
}
/**
* Performs the AJAX validation.
* @param Event $model the model to be validated
*/
protected function performAjaxValidation($model)
{
if(isset($_POST[''ajax'']) && $_POST[''ajax'']===''event-form'')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
}
Y este es mi Event model
<?php
/**
* This is the model class for table "event".
*
* The followings are the available columns in table ''event'':
* @property integer $id
* @property string $image
*
* The followings are the available model relations:
* @property UserJoinEvent[] $userJoinEvents
*/
class Event extends CActiveRecord
{
/**
* Returns the static model of the specified AR class.
* @param string $className active record class name.
* @return Event the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* @return string the associated database table name
*/
public function tableName()
{
return ''event'';
}
/**
* @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(''image'', ''required''),
array(''image'', ''length'', ''max''=>45),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array(''id, image'', ''safe'', ''on''=>''search''),
// this will allow empty field when page is update (remember here i create scenario update)
array(''image'', ''file'',''types''=>''jpg, gif, png, mp4'', ''allowEmpty''=>true, ''safe''=>false, ''on''=>''insert,update''),
array(''image'', ''length'', ''max''=>255, ''on''=>''insert,update''),
);
}
/**
* @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(
''userJoinEvents'' => array(self::HAS_MANY, ''UserJoinEvent'', ''event_event_id''),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
''id'' => ''ID'',
''image'' => ''Image'',
);
}
/**
* 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(''id'',$this->id);
$criteria->compare(''image'',$this->image,true);
return new CActiveDataProvider($this, array(
''criteria''=>$criteria,
));
}
}
Y este es mi view file(_form.php)
<?php
/* @var $this EventController */
/* @var $model Event */
/* @var $form BSActiveForm */
?>
<?php $form=$this->beginWidget(''bootstrap.widgets.BsActiveForm'', array(
''id''=>''event-form'',
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
''enableAjaxValidation''=>false,
//form options array...
''htmlOptions'' => array(
''enctype'' => ''multipart/form-data'',
),
));
?>
<p class="help-block">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
<?php //echo $form->textFieldControlGroup($model,''image'',array(''maxlength''=>45)); ?>
<!--this is for data path entry-->
<div class="row">
<?php echo $form->labelEx($model,''image''); ?>
<?php echo CHtml::activeFileField($model, ''image''); ?> <!--by this we can upload image-->
<?php echo $form->error($model,''image''); ?>
</div>
<?php if($model->isNewRecord!=''1'') ?>
<div class="row">
<?php echo CHtml::image(Yii::app()->request->baseUrl.''/img/''.$model->image,"",array("width"=>200)); ?> <!--Image shown here if page is update page-->
</div>
<br>
<?php echo BsHtml::submitButton(''Submit'', array(''color'' => BsHtml::BUTTON_COLOR_PRIMARY)); ?>
<?php $this->endWidget(); ?>
Esta es la estructura de la tabla userjoinevent
Tabla de estructura para la tabla user_join_event
--
CREATE TABLE IF NOT EXISTS `user_join_event` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`event_id` int(11) NOT NULL,
`date_created` varchar(45) DEFAULT NULL,
`date_modified` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_user_join_event_user1_idx` (`user_id`),
KEY `fk_user_join_event_event1_idx` (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=91 ;
Y esta es la restricción para la mesa
ALTER TABLE `user_join_event`
ADD CONSTRAINT `fk_user_join_event_event1` FOREIGN KEY (`event_id`) REFERENCES `event` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
ADD CONSTRAINT `fk_user_join_event_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
Y este es el modelo de UserJoinEvent
<?php
/**
* This is the model class for table "user_join_event".
*
* The followings are the available columns in table ''user_join_event'':
* @property integer $id
* @property integer $user_id
* @property integer $event_id
* @property string $date_created
* @property string $date_modified
*
* The followings are the available model relations:
* @property Event $event
* @property User $user
*/
class UserJoinEvent extends CActiveRecord
{
/**
* Returns the static model of the specified AR class.
* @param string $className active record class name.
* @return UserJoinEvent the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* @return string the associated database table name
*/
public function tableName()
{
return ''user_join_event'';
}
/**
* @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(''user_id, event_id'', ''required''),
array(''user_id, event_id'', ''numerical'', ''integerOnly''=>true),
array(''date_created, date_modified'', ''length'', ''max''=>45),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array(''id, user_id, event_id, date_created, date_modified'', ''safe'', ''on''=>''search''),
array(''date_modified'',''default'', ''value''=>new CDbExpression(''NOW()''),//automatically add the current date in mysql feild
''setOnEmpty''=>false,''on''=>''update''),
array(''date_created,date_modified'',''default'', ''value''=>new CDbExpression(''NOW()''),''setOnEmpty''=>false,''on''=>''insert''),
);
}
/**
* @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(
''event'' => array(self::BELONGS_TO, ''Event'', ''event_id''),
''user'' => array(self::BELONGS_TO, ''User'', ''user_id''),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
''id'' => ''ID'',
''user_id'' => ''User'',
''event_id'' => ''Event'',
''date_created'' => ''Date Created'',
''date_modified'' => ''Date Modified'',
);
}
/**
* 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(''id'',$this->id);
$criteria->compare(''user_id'',$this->user_id);
$criteria->compare(''event_id'',$this->event_id);
$criteria->compare(''date_created'',$this->date_created,true);
$criteria->compare(''date_modified'',$this->date_modified,true);
return new CActiveDataProvider($this, array(
''criteria''=>$criteria,
));
}
}
Por favor, ayúdenme con esto, gracias.
Bueno, el problema está relacionado con el hecho de que tienes el enlace Event a User Event en la tabla user_join_event. luego, cuando intentas eliminar un Evento, el DB genera un error porque en la forma en que una fila de user_join_event permanece sin referencia. Esto implica que antes de eliminar el evento es obligatorio eliminar el hijo redireccionado. (Sugiero que hagas una copia de la tabla antes de ejecutar el código)
public function actionDelete($id)
{
if(Yii::app()->request->isPostRequest)
{
// we only allow deletion via POST request
$modelUserEvents = UserJoinEvent::model()->findAllByAttributes( array(''event_id''=>$id));
if isset($modelUserEvents){
foreach($modelUserEvents as $child){
$child->delete();
}
}
$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''));
}
else
throw new CHttpException(400,''Invalid request. Please do not repeat this request again.'');
}
tiene relación con la tabla UserJoinEvent, y el error causa de las restricciones, por lo tanto, elimine las filas de la tabla UserJoinEvent (tabla principal)