قسمت دوم
در قسمت قبل ACO و ARO شرح داده شد. امیدوارم مفهوم این دو برای شما روشن شده باشد.
ساخت ARO
دو مدل User و Group را به عنوان ARO در نظر می گیریم. User کاربران سیستم هستند و Group هم گروه های کاربری.
فرض کنید در یک سیستم فروشگاه کاربری به نام ali وجود دارد. علی یک مدیر ارشد است و قادر می باشد تمام امور مربوط به فروشگاه را انجام دهد. احمد در این سیستم تنها می تواند کالاها را اضافه و یا ویرایش کند اما حق حذف کالا را ندارد. در صورتی که کاربران شبیه به علی و احمد زیاد باشند می توانیم با گروه بندی این کاربران ، مجوز های دسترسی را فقط روی گروه تنظیم کنیم. مثلاً در این سیستم می توانیم یک گروه Admin و یک گروه Operator داشته باشیم که به ترتیب علی و احمد عضو آنها هستند. هر کاربری که در گروه Admin قرار بگیرد تمام مجوز های این گروه را خواهد داشت. این فروشگاه کاربر دیگری به نام جواد دارد که او می تواند تمام کارهای یک مدیر ارشد را همچون علی انجام دهد اما او قادر نیست کاربران سیستم را حذف و یا اضافه کند. ما با قرار دادن جواد در گروه Admin تمام مجوز ها را به او می دهیم و با منع کردن دسترسی او به کنترلر users از انجام کلیه امور مربوط به کاربران جلوگیری می کنیم. توجه کنید اگر خواسته باشیم لیست کاربران را به جواد نشان دهیم باید مجوز اکشنی همچون index را به جواد بدهیم.
شاید تاکنون متوجه ساختار درختی ARO و ACO شده باشید. در ادامه بیشتر این موضوع را درک می کنید.
اکنون جداول users و groups را می سازیم:
کد:
--
-- Table structure for table `groups`
--
CREATE TABLE `groups` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(100) character set utf8 collate utf8_persian_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(255) character set utf8 collate utf8_persian_ci NOT NULL,
`password` char(40) NOT NULL,
`name` varchar(255) character set utf8 collate utf8_persian_ci NOT NULL,
`lastname` varchar(255) character set utf8 collate utf8_persian_ci NOT NULL,
`group_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
--
-- Constraints for table `users`
--
ALTER TABLE `users`
ADD CONSTRAINT `users_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
و همچنین مدلها
کد PHP:
<?php
class User extends AppModel
{
var $name = 'User';
var $belongsTo = array(
'Group' => array(
'className' => 'Group',
'foreignKey' => 'group_id'
)
);
var $actsAs = array('Acl' => 'requester');
function parentNode() {
if (!$this->id && empty($this->data)) {
return null;
}
$data = $this->data;
if (empty($this->data)) {
$data = $this->read();
}
if (!$data['User']['group_id']) {
return null;
} else {
return array('Group' => array('id' => $data['User']['group_id']));
}
}
}
?>
کد PHP:
<?php
class Group extends AppModel {
var $name = 'Group';
var $hasMany = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'group_id',
'dependent' => false
)
);
var $actsAs = array('Acl' => 'requester');
function parentNode() {
return null;
}
}
?>
به متغییر actsAs و همچنین تابع parentNode در هر دو مدل توجه کنید.
'Acl' => 'requester' نشان می دهد هر دو مدل از نوع ARO هستند.
دقت کنید در کیک یک کامپوننت Acl و یک رفتار(behaviors) Acl وجود دارد که متفاوت، اما به هم مربوطند. وقتی یک مدل دارای رفتار Acl باشد به یک تابع به نام parentNode نیاز دارد. زمانی که یک کاربر و یا یک گروه کاربری اضافه می شود معادل آن نیز باید در جدول aros اضافه شود. درصورت حذف نیز رکورد معادل در جدول aros باید حذف شود. این کار مشکل به نظر می رسد اما اگر تابع parentNode به درستی طراحی شود این عمل به طور خودکار توسط رفتار Acl انجام می شود.
همانطور که قبلاً نیز اشاره شد جداول aros و acos دارای ساختار درخت گونه هستند. در این مثال جدول aros حداکثر عمق 2 را می تواند داشته باشد. Group ها همیشه پدر و User ها همیشه فرزند یک گروه هستند بنابراین parent_id مربوط به Group در جدول aros باید حتماً NULL باشد. اگر به تابع parentNode در مدل Group نگاه بیندازید ، متوجه خواهید شد که چرا همیشه خروجی NULL دارد. پس وظیفه تابع parentNode تولید گره پدر می باشد.
گره پدر برای مدل User همان گره
گروه خودش است.
درصورتی که مدل Group نیز ساختار درختی داشته باشد ، عمق مذکور تا بی نهایت می تواند ادامه داشته باشد یعنی گروها می توانند خود فرزند گروه دیگری باشند و تابع parentNode هم باید تغییر کند.
کد PHP:
function parentNode() {
if (!$this->id && empty($this->data)) {
return null;
}
$data = $this->data;
if (empty($this->data)) {
$data = $this->read();
}
if (!$data['Group']['parent_id']) {
return null;
} else {
return array('Group' => array('id' => $data['Group']['parent_id']));
}
}
ادامه دارد...