是的,ACL 是多余的
ACL 是一个非常强大和灵活的系统——但它不是免费的,它带来了复杂性。除非您有一个绝对需要细粒度权限的用例(您描述的两个规则不适合此) - 不要使用 ACL。
限制预订他添加的用户
这条规则很容易实现——例如添加到相关的查找调用中:
$results = $BookModelInstance->find('all', array(
'conditions' => array(
'created_by' => AuthComponent::user('id')
)
));
限制他购买的用户的书籍
这条规则也很容易实现,稍微复杂一点:
$BookModelInstance->bindModel(array(
'hasOne' => array( // Yes, hasOne not hasMany
'MyPurchase' => array(
'className' => 'Purchase',
'foriegnKey' => 'user_id'
)
)
));
$results = $BookModelInstance->find('all', array(
'recursive' => 0, // to join hasOne+belongsTo associations into the query
'conditions' => array(
'MyPurchase.user_id' = AuthComponent::user('id'),
)
));
bindModel 调用等效于SELECT .. FROM books LEFT JOIN book_users
.. find 调用中的条件将因此将结果限制为有用户购买图书记录的图书。
把它们放在一起
自动应用这两个规则的简单实现是:
model Book extends AppModel {
public $actsAs = array('Containable');
public $restrictToUser = true;
public function beforeSave($options = array()) {
if (!$this->id) {
// Store who created this book
$this->data[$this->alias]['created_by'] = AuthComponent::user('id');
}
return true;
}
public function beforeFind($queryData) {
if (!$this->restrictToUser) {
// we don't want to apply user-level restrictions
return true;
}
$userId = AuthComponent::user('id');
if (!$userId) {
// we want to restrict to the current user - there isn't one.
return false;
}
// define the association to the purchase table
$this->bindModel(array(
'hasOne' => array(
'MyPurchase' => array(
'className' => 'Purchase',
'foriegnKey' => 'user_id'
)
)
));
//ensure the purchase table is included in the current query
$queryData['contain']['MyPurchase'] = array();
// restrict to rows created by the current user, OR purchased by the current user
$queryData['conditions']['OR'] = array(
$this->alias '.created_by' => $userId,
'MyPurchase.user_id' => $userId
);
return $queryData;
}
}
这需要在 books 表中存在一个字段created_by
(或等效字段),并使用可包含来确保该purchases
表(或等效字段)包含在所有相关查询中。