Garrett
Garrett

Reputation: 11725

CakePHP Making Child Models for different types of Comments

I have a Comment Model that I am using to store comments for both Goals and Notes.

The current implementation has a GoalComment Model and a NoteComment Model, each of which extends Comment, and the Comment's beforeFind does the following:

$queryData['conditions'][$this->name . '.' . $this->__type_field] = $this->name;

which basically sets the type field of the Comment Model to either GoalComment or NoteComment, depending on which of those classes is performing a find.

This implementation has worked up until now, where I want to delete comments. Below is the Model association for Comments in Goals:

var $hasMany = array(
    'Comment' => array(
        'className' => 'GoalComment',
        'foreignKey' => 'object_id'
    )
);

And in my beforeDelete, where I want to remove all comments associated with the goal, I have:

$this->Comment->deleteAll(array('object_id' => $this->id));

But I get the following SQL error:

SQL Error: 1054: Unknown column 'GoalComment.type' in 'where clause' [CORE\cake\libs\model\datasources\dbo_source.php, line 525]
Query: SELECT `Comment`.`id` FROM `comments` AS `Comment` LEFT JOIN `users` AS `Poster` ON (`Comment`.`poster_id` = `Poster`.`id`)
LEFT JOIN `goals` AS `Goal` ON (`Comment`.`object_id` = `Goal`.`id`)  
WHERE `object_id` = 52 AND `GoalComment`.`type` = 'GoalComment'

This is happening because of the beforeFind action I described before, which adds the GoalComment.type = 'GoalComment'. This has made me rethink the whole approach to the situation.

So my question is how should this relationship be re-implemented? My best idea is to scrap the beforeFind in Comment and simply remake the $hasMany relationship to be:

var $hasMany = array(
    'Comment' => array(
        'className' => 'Comment',
        'foreignKey' => 'object_id',
        'conditions' => array('Comment.type = "GoalComment"')
    )
);

This would extract all of the thinking from the Comment Model, and it just seems more natural to me.

Do you have an idea for a better implementation, or should I go with the one above? Thanks!

Upvotes: 3

Views: 726

Answers (1)

Dave
Dave

Reputation: 29131

I think you're correct in realizing that you've been over-thinking the associations.

The "normal" way for this type of relationship is to simply use the fields model and foreign_key in your comments table.

//Comment model
public $belongsTo = array(
    'Goal' => array(
        'className' => 'Goal',
        'foreignKey' => 'foreign_key',
        'conditions' => array('Comment.model' => 'Goal')
    ,
    'Note' => array(
        'className' => 'Note',
        'foreignKey' => 'foreign_key',
        'conditions' => array('Comment.model' => 'Note')
    )
);

//Goal model
public $hasMany = array(
    'Comment' => array(
        'className' => 'Comment',
        'foreignKey' => 'foreign_key',
        'conditions' => array('Comment.model' => 'Goal')
    )
);

//Note model
public $hasMany = array(
    'Comment' => array(
        'className' => 'Comment',
        'foreignKey' => 'foreign_key',
        'conditions' => array('Comment.model' => 'Note')
    )
);

Upvotes: 4

Related Questions