Cakephp 2.3 如果其他对象引用某个对象,则拒绝删除该对象

Cakephp 2.3 如果其他对象引用某个对象,则拒绝删除该对象,cakephp-2.3,cakephp-model,Cakephp 2.3,Cakephp Model,我正在用cakePHP构建一个应用程序,我对它很陌生。我现在想做的就是这样。让我用几句话来解释:我有两个模型,项目和类型。一个项目可以有多种类型。所以类型表有一个外键-item_id-它引用item。现在,如果仍然存在引用该项的类型,我想阻止用户删除该项 我的项目模型如下: <?php App::uses('AppModel', 'Model'); /** * Item Model * * @property ItemLocation $ItemLocation * @proper

我正在用cakePHP构建一个应用程序,我对它很陌生。我现在想做的就是这样。让我用几句话来解释:我有两个模型,项目和类型。一个项目可以有多种类型。所以类型表有一个外键-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' => ''
        )
    );
当我试图删除一个有排版的条目或一个没有排版的条目时,它会显示这个错误

Fatal Error

Error: Call to a member function find() on a non-object
File: C:\wamp\www\project\app\Model\Item.php
Line: 449

我怎样才能解决它

我想说的是,您希望您的数据库通过确保那些外键约束在数据库中来防止删除其他类型所引用的项。那么您的UI不应该给人们提供删除类型所引用的项目的选项,但是您可能确实希望给他们提供从项目中删除类型的选项

我不知道您建议的是什么类型的UI,但是(在我的脑海中,未经检查的代码,因此对任何输入错误/错误表示歉意),如果您有一个项目的索引操作/视图,那么您的ItemsController.php索引操作中可能有以下内容:

$items = $this->Item->find('all')
$this->set('items', $items);
然后在视图/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; ?>
如果有任何违反这些约束的情况,则将失败,因此,正如@savedario所说的,您可以使用

if ($this->Item->delete())
或者你可以更进一步,如@savedario所示,但我认为在这里做得更优雅、更一般:如果存在链接记录,则抛出一个异常,然后可以在以下内容中进行测试(复制自joshuapaling的博客):


逻辑与前面解释的相似

在控制器代码中,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'));
}
公共函数删除($id=null){
$this->request->onlyllow('post','delete');
$options=array('conditions'=>array('Item'.$this->Field->primaryKey=>$id));
$item=$this->item->find('first',$options);
如果(!$项目){
抛出新的NotFoundException(uuu('Invalid item'));
}
if(设置($item['Typology'])和计数($item['Typology'])){
$this->setFlash(uuu(“项目'%s'正被%s类型使用。
无法删除”),$Item['Item']['title'],count($Item['Tipology']); }否则{ $this->Item->id=$id; 如果($this->Item->delete()){ $this->setFlash(uuu('Item deleted'); }否则{ $this->setFlash(uuu('项目未被删除'); } } $this->redirect(数组('action'=>'index')); }
用户界面还没有完全构建好,但我正在尝试先构建逻辑。我明白你的意思,但重点是用户仍然可以通过URL访问删除操作,我也不希望这样,这就是为什么我问是否有一种方法或查询可以首先计算foregin键引用的所有类型,如果有超过1的类型,则拒绝删除或返回false,否则允许删除,返回true.Thanx很多@savedario,你的代码真的帮助了我。我得到了我想要的东西。
$this->Item->delete()
if ($this->Item->delete())
 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');
}
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'));
}