我正在用cakePHP构建一个应用程序,我很新。我现在要做的就是这个。让我用几句话来解释:我有两个模型,项目和类型。一个项目可以有许多类型。所以Typology表有一个外键 - item_id - 引用item。现在我想阻止用户删除项目,如果仍有类型参考此项目。
我的物品型号是这样的:
<?php
App::uses('AppModel', 'Model');
/**
* Item Model
*
* @property ItemLocation $ItemLocation
* @property ItemCharacteristic $ItemCharacteristic
* @property FirstSeller $FirstSeller
* @property SecondSeller $SecondSeller
* @property User $User
* @property Contact $Contact
* @property ItemPicture $ItemPicture
* @property Typology $Typology
*/
class Item extends AppModel {
public $name = 'Item';
/**
* Primary key field
*
* @var string
*/
public $primaryKey = 'id';
/**
* Display field
*
* @var string
*/
public $displayField = 'title';
/**
* Validation rules
*
* @var array
*/
public $validate = array(
'id' => array(
'blank' => array(
'rule' => 'blank',
'on' => 'create',
),
),
'title' => array(
'words' => array(
'rule' => array('custom', '/[0-9A-Za-z\._-]/'),
'message' => 'The Item name can only contain letters, numbers and spaces.',
),
'maxLength' => array(
'rule' => array('maxLength', 100),
'message' => 'The Item name must not be longer than 100 characters.',
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'The Item name must not be empty.',
),
'isUnique' => array(
'rule' => 'isUnique',
'message' => 'This Item name already exists.',
),
),
'user_id' => array(
'numeric' => array(
'rule' => array('numeric'),
//'message' => 'Your custom message here',
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Not Empty',
),
),
'created' => array(
'datetime' => array(
'rule' => array('datetime'),
//'message' => 'Your custom message here',
),
),
);
/**
* belongsTo associations
*
* @var array
*/
public $belongsTo = array(
'ItemUser' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
/**
* hasMany associations
*
* @var array
*/
public $hasMany = array(
'ItemTypologies' => array(
'className' => 'Typology',
'foreignKey' => 'item_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
类型学模型是这样的:
<?php
App::uses('AppModel', 'Model');
/**
* Typology Model
*
* @property Item $Item
* @property TypologyCategory $TypologyCategory
* @property TypologyCondition $TypologyCondition
* @property User $User
* @property TypologyPicture $TypologyPicture
*/
class Typology extends AppModel {
public $name = 'Typology';
/**
* Primary key field
*
* @var string
*/
public $primaryKey = 'id';
/**
* Display field
*
* @var string
*/
public $displayField = 'title';
/**
* Validation rules
*
* @var array
*/
public $validate = array(
'id' => array(
'blank' => array(
'rule' => 'blank',
'on' => 'create',
),
),
'item_id' => array(
'numeric' => array(
'rule' => array('numeric'),
'message' => 'Chose Which Object This Typology Belongs To',
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Can Not be Empty',
),
),
'title' => array(
'words' => array(
'rule' => array('custom', '/[0-9A-Za-z\._-]/'),
'message' => 'The Typology name can only contain letters, numbers and spaces.',
),
'maxLength' => array(
'rule' => array('maxlength', 50),
'message' => 'The Typology name must not be longer than 50 characters.',
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Typology Title Can not be Empty',
),
'isUnique' => array(
'rule' => 'isUnique',
'message' => 'Typology Name Should be Unique',
),
),
'description' => array(
'words' => array(
'rule' => array('custom', '/[0-9A-Za-z\._-]/'),
'message' => 'The Typology name can only contain letters, numbers and spaces.',
),
'maxLength' => array(
'rule' => array('maxlength', 350),
'message' => 'The Typology name must not be longer than 350 characters.',
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Description can not be Empty',
),
),
'user_id' => array(
'numeric' => array(
'rule' => array('numeric'),
'message' => 'Chose the user who created this typology',
),
'notEmpty' => array(
'rule' => array('notEmpty'),
//'message' => 'Your custom message here',
),
),
'created' => array(
'datetime' => array(
'rule' => array('datetime'),
//'message' => 'Your custom message here',
),
),
);
/**
* belongsTo associations
*
* @var array
*/
public $belongsTo = array(
'TypologyItem' => array(
'className' => 'Item',
'foreignKey' => 'item_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'TypologyUser' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
现在我所看到和写的是这个,如果有人有任何想法,我真的很感激它:
// using app/Model/Item.php
// In the following example, do not let an Item to be deleted if it
// still contains Typologies Attached to it.
// A call of $this->Typology->delete($id) from TypologiesController.php has set
// $this->id .
// Assuming 'ItemTypologies hasMany Typology', we can access $this->Typoogy
// in the model.
public function beforeDelete($cascade = true) {
$count = $this->Typology->find('count', array('conditions' => array('item_id' => $this->Typology->id)));
if ($count == 0) {
return true;
} else {
return false;
}
}
当我尝试删除具有typologes的项目或者没有显示此错误的项目时!
Fatal Error
Error: Call to a member function find() on a non-object
File: C:\wamp\www\project\app\Model\Item.php
Line: 449
我该如何解决它?
答案 0 :(得分:0)
我会说你希望你的数据库通过确保这些外键约束在db中来防止删除其他类型引用的项。那么你的UI不应该让人们选择删除类型学所引用的项目,但是你可能想让他们选择从项目中删除类型。
我不知道你提出的是什么类型的用户界面,但是(在我的头脑中,未经检查的代码为任何拼写错误/错误道歉),说你有一个索引操作/项目视图,你可能有这个你的ItemsController.php索引动作:
$items = $this->Item->find('all')
$this->set('items', $items);
然后在你的Views / Items / index.ctp中你可能有:
<?php foreach ($items as $item): ?>
<h1><?php echo $item['Item']['name'];?>
<?php
if(!isset($item['Typology'])||count($item['Typology'])==0){
//ie this items has no Typologies
//Create delete button/link for this item
}
elseif(isset($item['Typology'])&&count($item['Typology'])>0){
//we have some typologies for this item
foreach ($item['Typology'] as $typology){
//info about the typology and possible delete button/link
}
}
?>
<?php endforeach; ?>
HTH
在控制器中添加更多细节 - 扩展@savedario的答案
如果您的模型设置了正确的外键约束,那么
$this->Item->delete()
如果有任何违反这些限制的行为,将失败,因为@savedario说,你可以用
测试成功if ($this->Item->delete())
或者你可以更进一步,正如@savedario所说明的那样,但我认为在这里做得更优雅和一般:http://joshuapaling.com/post/catching-integrity-constraint-violations-when-deleting-records并且如果有链接记录则抛出异常,然后你可以在下面测试(从joshuapaling的博客复制):
try {
if ($this->MyModel->delete()) {
$this->Session->setFlash('Record deleted', 'default', array(), 'good');
} else {
$this->Session->setFlash('Record was not deleted. Unknown error.', 'default', array(), 'bad');
}
} catch (Exception $e) {
$this->Session->setFlash("Delete failed. {$e->getMessage()}", 'default', array(), 'bad');
}
答案 1 :(得分:0)
逻辑类似于theotherdy已解释的内容。
在您的控制器代码中,delete()方法如下:
public function delete($id = null) {
$this->request->onlyAllow('post', 'delete');
$options = array('conditions' => array('Item.' . $this->Field->primaryKey => $id));
$item = $this->Item->find('first', $options);
if (!$item) {
throw new NotFoundException(__('Invalid item'));
}
if (isset($item['Typology']) && count($item['Typology'])) {
$this->setFlash(__("Item '%s' is being used by %s Typologies.<br />Cannot delete.", $item['Item']['title'], count($item['Tipology'])));
} else {
$this->Item->id = $id;
if ($this->Item->delete()) {
$this->setFlash(__('Item deleted'));
} else {
$this->setFlash(__('Item was not deleted'));
}
}
$this->redirect(array('action' => 'index'));
}