我需要在PHP中使用光标fetch方法获取每个数据集行。但在现代,我还想利用PDO的优势。在我的例子中,它与经典的小组改变相结合:
我有以下表格:
create table profile
(
id int not null auto_increment,
email char(50) not null,
password char(100) not null,
name char(100) not null,
surname char(50) not null,
street char(50) not null,
homeno char(5) not null,
group_id int not null,
primary key(id)
);
create table usergroups
(
id int auto_increment not null,
name char(30) not null,
primary key(id)
);
create table actions
(
id int not null auto_increment,
name char(50) not null,
primary key(id)
);
create table group_rights
(
id int auto_increment not null,
action_id int not null,
group_id int not null,
allowed int(1) not null,
primary key(id)
);
所以,在第3范式中。
我的PHP代码看起来像这样(目前它有效,但我认为我应该利用以更好的方式使用PDO):
class AuthModel extends BaseModel
{
public function __construct()
{
parent::__construct();
}
public function load()
{
$sSQL = <<<SQL
select `usergroups`.`name` as `group`, `actions`.`name` as `action`, `profile`.`name` as `user`, `allowed`
from profile
inner join usergroups on usergroups.id = profile.group_id
inner join group_rights on usergroups.id = group_rights.group_id
inner join actions on group_rights.action_id = actions.id
order by profile.group_id;
SQL;
$arRightList = array();
$pdo = $this->_db->getPdo();
$stmt = $pdo->prepare($sSQL, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$stmt->execute();
$arRow = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT);
$auth = new AuthList();
if ($arRow)
{
$sGroup = $arRow['group'];
$sGroupNew = $sGroup;
$arActRights = array();
$arActUsers = array();
}
while ($arRow)
{
while ($sGroup === $sGroupNew && $arRow)
{
if ($arRow['allowed'] == 0)
{
$arActRights[$arRow['action']] = AuthList::ACTION_DENY;
}
else
{
$arActRights[$arRow['action']] = AuthList::ACTION_ACCEPT;
}
$arActUsers[] = $arRow['user'];
$sGroupNew = $arRow['group'];
$arRow = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT);
}
$auth->addGroup($sGroup, $arActRights);
foreach ($arActUsers as $sActUser)
{
$auth->setPrimaryUserGroup($sGroup, $sActUser);
}
$arActRights = array();
$arActUsers = array();
$sGroup = $sGroupNew;
}
return $auth;
}
}
...和AuthList类完成:
class AuthList
{
const USER_ALREADY_SET = -1;
const USER_GROUP_CHANGED = 0;
const USER_SUCCESSFULLY_ADDED = 1;
const ACTION_ALREADY_ALLOWED = -1;
const ACTION_SUCCESSFULLY_ALLOWED = 0;
const ACTION_ALREADY_DENIED = -1;
const ACTION_SUCESSFULLY_DENIED = 0;
const GROUP_ALREADY_EXISTS = -1;
const GROUP_SUCCESSFULLY_ADDED = 0;
const ACTION_ACCEPT = 'OK';
const ACTION_DENY = 'NOK';
const LIST_KEY_NAME = 'list';
protected $_rights;
protected $_list;
protected $_groups;
public function __construct()
{
$this->_list = array();
$this->_groups = array();
}
public function addAction ($sAction)
{
if (is_callable($sAction))
{
$this->_list[] = $sAction->__toString();
}
else
{
$this->_list[] = $sAction;
}
}
public function addGroup ($sGroupName, $rights = array())
{
$iRetCode = -2;
if (in_array($sGroupName, $this->_groups))
{
$iRetCode = self::GROUP_ALREADY_EXISTS;
}
else
{
if (empty($rights))
{
$this->_groups[$sGroupName] = array();
}
else
{
$this->_groups[$sGroupName][self::LIST_KEY_NAME] = $rights;
}
$iRetCode = self::GROUP_SUCCESSFULLY_ADDED;
}
return $iRetCode;
}
public function setPrimaryUserGroup ($sGroupName, $sUser)
{
$iRetCode = -2;
foreach ($this->_groups as $sKeyGroupName => $users)
{
if (in_array($sUser, $users) && $sGroupName === $sKeyGroupName)
{
// User already are in the requested group, finish working
$iRetCode = self::USER_ALREADY_SET;
break;
}
elseif (in_array($sUser, $users) && $sGroupName !== $sKeyGroupName)
{
for ($iUserPos = 0; $iUserPos < count($users); $iUserPos++)
{
if ($users[$iUserPos] === $sUser)
{
$iUserNo = $iUserPos;
break;
}
}
unset($users[$iUserNo]);
$this->_groups[$sGroupName][] = $sUser;
$iRetCode = self::USER_GROUP_CHANGED;
break;
}
else
{
$this->_groups[$sGroupName][] = $sUser;
$iRetCode = self::USER_SUCCESSFULLY_ADDED;
break;
}
}
return $iRetCode;
}
public function allowAction ($sGroupName, $sActionName)
{
$iRetCode = -2;
if ($this->_groups[$sGroupName][self::LIST_KEY_NAME][$sActionName] === self::ACTION_ACCEPT)
{
$iRetCode = self::ACTION_ALREADY_ALLOWED;
}
else
{
$this->_groups[$sGroupName][self::LIST_KEY_NAME][$sActionName] = self::ACTION_ACCEPT;
$iRetCode = self::ACTION_SUCCESSFULLY_ALLOWED;
}
return $iRetCode;
}
public function denyAction ($sGroupName, $sActionName)
{
$iRetCode = -2;
if ($this->_groups[$sGroupName][self::LIST_KEY_NAME][$sActionName] === self::ACTION_DENY)
{
$iRetCode = self::ACTION_ALREADY_DENIED;
}
else
{
$this->_groups[$sGroupName][self::LIST_KEY_NAME][$sActionName] = self::ACTION_DENY;
$iRetCode = self::ACTION_SUCESSFULLY_DENIED;
}
return $iRetCode;
}
public function isAllowed ($sUserName, $sActionName)
{
$rw = false;
foreach ($this->_groups as $users)
{
if (in_array($sUserName, $users))
{
if (array_key_exists($sActionName, $users[self::LIST_KEY_NAME]))
{
$rw = $users[self::LIST_KEY_NAME][$sActionName] === self::ACTION_ACCEPT;
}
break;
}
}
return $rw;
}
public function dump()
{
var_dump($this->_groups);
}
}
我使用数据库连接类作为单例模式。所以,
$this->_db
只是对包含PDO类对象的单例的引用。致电
$authmdl = new AuthModel();
$authlist = $authmdl->load();
你会得到ACL。