这里最简单的方法和“技巧”实际上是:
将您的规则和防护设置为与示例配置中所示相同的数组格式。因此,从数据库读取记录后,无论原始数据库数据是什么格式,都应对其进行处理以匹配与配置中相同的保护格式。 (我的回答详细介绍了如何使用 Doctrine ORM 做到这一点,但也应该让您了解其他数据库引擎。只需用您最喜欢的数据库引擎替换“数据库读取”操作即可)
将已经采用 BjyAuthorize 期望的正确格式的规则(因为您这样做了)注入到BjyAuthorize\Guard\Controller
, 从内部YOUR_MODULE_NAME\Factory\DoctrineControllerGuardAdapterFactory
,您将编写。 Bjy 的控制器将把这些规则视为来自配置*,并且不会怀疑有任何差异。
退一步享受吧!
这是您需要在自己的模块中编写的构造:
namespace YOUR_MODULE_NAME\Factory;
/**
* See "How and where exactly to register the factory" in ZF2 config
* below in my answer.
*/
class [Custom]ControllerGuardAdapterFactory
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
/**
* Retrieve your rules from favorive DB engine (or anything)
*
* (You may use $serviceLocator to get config for you DB engine)
* (You may use $serviceLocator to get your DB engine)
* (You may use $serviceLocator to get ORM Entity for your DB engine)
* (Or you may hack your DB connection and retrieval in some other way)
*
* Hell, you may read them from a text file using PHP's file() method
* and not use $serviceLocator at all
*
* You may hardcode the rules yourself right here for all that matters
*/
$rules = ... //array(...);
/**
* Inject them into Bjy's Controller
*
* Rules must be in the same format as in Bjy config, or it will puke.
* See how ['guards'][\BjyAuthorize\Guard\Controller::class] is constructed
* in Bjy configuration for an example
*/
return new \BjyAuthorize\Guard\Controller($rules, $serviceLocator);
}
}
现在观察并观察这可以变得多么令人头脑麻木的复杂! (仿照Bjy自己的机制)
这主要是 ZF2、OO 和 Bjy“配置地狱”,伙计们,除此之外没有什么特别的。欢迎来到 ZF2 和 Bjy 以及 ORM 配置地狱。不客气。
详细解答——如何实施?
写一个adapter工厂,从数据库读取规则,然后将它们注入到BjyAuthorize 的 Controller Guard https://github.com/bjyoungblood/BjyAuthorize/blob/1.4.0/src/BjyAuthorize/Guard/Controller.php。效果与读取规则的效果相同['guards'][\BjyAuthorize\Guard\Controller::class]
What?
The way BjyAuthorize 的 Controller Guard https://github.com/bjyoungblood/BjyAuthorize/blob/1.4.0/src/BjyAuthorize/Guard/Controller.php有效的方法是它采用某种格式的规则(为['guards']['BjyAuthorize\Guard\Controller']
),然后它使用规则来填充 ACL。它还根据规则为您计算资源并将其加载到 ACL 中。如果没有,您将必须编写自己的资源提供程序来执行此操作。
所以任务就变成了:
- 从数据库加载规则并将规则转换为 BjyAuthorize 期望的格式。这可以在您自己的规则提供程序中完成,很像这个 https://github.com/bjyoungblood/BjyAuthorize/blob/1.4.0/src/BjyAuthorize/Provider/Role/ObjectRepositoryProvider.php.
- 您可以使用工厂从 module.config.php 文件加载特定的数据库和存储类配置数组。我把我的放在下面
['guards']['YOUR_MODULE_NAME_controller_guard_adapter']
.
'guards' => array(
'YOUR_MODULE_NAME_controller_guard_adapter' => array(
'object_manager' => 'doctrine.entity_manager.orm_default',
'rule_entity_class' => 'YOUR_MODULE_NAME\Entity\ObjectRepositoryProvider'
)
)
- (续)我将其置于保护之下,而不是rule_providers,因为我们在这里处理的不是纯粹的规则提供者。它是一个防护提供程序,或者“从 ObjectRepositoryProvider 中获取规则并将其注入控制器防护的适配器”。这个工厂应该看起来像这样 https://github.com/bjyoungblood/BjyAuthorize/blob/1.4.0/src/BjyAuthorize/Service/ObjectRepositoryRoleProviderFactory.php,只不过您将加载规则,而不是角色。然后,您将把规则注入到控制器中,如下一步所示。
- 将规则注入到控制器中,就像这里所做的一样 https://github.com/bjyoungblood/BjyAuthorize/blob/1.4.0/src/BjyAuthorize/Service/ControllerGuardServiceFactory.php#L31
示例实施细节(来自评论中的问答)
更多关于“将规则注入控制器”的最后一点。基本上有两个步骤:1)确保您已经(或将)以某种方式生成规则(这是困难的一步)。 2)将这些规则注入控制器(这是更简单的步骤)。实际的注入是这样完成的
$rules = __MAGIC__; //get rules out of somewhere, somehow.
return new Controller($rules, $serviceLocator); //$rules injection point
请参阅下面的代码块以了解我自己的实现,其中块中的最后一行是我在上面给出的行。
namespace YOUR_MODULE_NAME\Factory;
use BjyAuthorize\Exception\InvalidArgumentException;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use YOUR_MODULE_NAME\Provider\Rule\DoctrineRuleProvider; //this one's your own
use BjyAuthorize\Guard\Controller;
class DoctrineControllerGuardAdapterFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
//just setting up our config, move along move along...
$config = $serviceLocator->get('Config');
$config = $config['bjyauthorize'];
//making sure we have proper entries in our config...
//move along "nothing to see" here....
if (! isset($config['guards']['YOUR_MODULE_NAME_controller_guard_adapter'])) {
throw new InvalidArgumentException(
'Config for "YOUR_MODULE_NAME_controller_guard_adapter" not set'
);
}
//yep all is well we load our own module config here
$providerConfig = $config['guards']['YOUR_MODULE_NAME_controller_guard_adapter'];
//more specific checks on config
if (! isset($providerConfig['rule_entity_class'])) {
throw new InvalidArgumentException('rule_entity_class not set in the YOUR_MODULE_NAME guards config.');
}
if (! isset($providerConfig['object_manager'])) {
throw new InvalidArgumentException('object_manager not set in the YOUR_MODULE_NAME guards config.');
}
/* @var $objectManager \Doctrine\Common\Persistence\ObjectManager */
$objectManager = $serviceLocator->get($providerConfig['object_manager']);
//orp -- object repository provider
//here we get our class that preps the object repository for us
$orp=new DoctrineRuleProvider($objectManager->getRepository($providerConfig['rule_entity_class']));
//here we pull the rules out of that object we've created above
//rules are in the same format BjyAuthorize expects
$rules=$orp->getRules();
//here pass our rules to BjyAuthorize's own Guard Controller.
//It will not know the difference if we got the rules from Config or from Doctrine or elsewhere,
//as long as $rules are in the form it expects.
return new Controller($rules, $serviceLocator);
}
}
教义规则提供者
namespace YOUR_MODULE_NAME\Provider\Rule;
use Doctrine\Common\Persistence\ObjectRepository;
use BjyAuthorize\Provider\Rule\ProviderInterface;
/**
* Guard provider based on a {@see \Doctrine\Common\Persistence\ObjectRepository}
*/
class DoctrineRuleProvider implements ProviderInterface
{
/**
* @var \Doctrine\Common\Persistence\ObjectRepository
*/
protected $objectRepository;
/**
* @param \Doctrine\Common\Persistence\ObjectRepository $objectRepository
*/
public function __construct(ObjectRepository $objectRepository)
{
$this->objectRepository = $objectRepository;
}
/**
* Here we read rules from DB and put them into an a form that BjyAuthorize's Controller.php understands
*/
public function getRules()
{
//read from object store a set of (role, controller, action)
$result = $this->objectRepository->findAll();
//transform to object BjyAuthorize will understand
$rules = array();
foreach ($result as $key => $rule)
{
$role=$rule->getRole();
$controller=$rule->getController();
$action=$rule->getAction();
if ($action==='all') //action is ommitted
{
$rules[$controller]['roles'][] = $role;
$rules[$controller]['controller'] = array($controller);
}
else
{
$rules[$controller.':'.$action]['roles'][]=$role;
$rules[$controller.':'.$action]['controller']=array($controller);
$rules[$controller.':'.$action]['action']=array($action);
}
}
return array_values($rules);
}
}
问:工厂具体如何以及在哪里注册DoctrineControllerGuardAdapterFactory
答:试试这个路径:module\YOUR_MODULE_NAME\config\module.config.php
并有
'service_manager' => array(
'factories' => array(
'YOUR_MODULE_NAME_controller_guard_adapter' => \YOUR_MODULE_NAME\Factory\DoctrineControllerGuardAdapterFactory::class
)
)
- Note:
YOUR_MODULE_NAME
。左边的东西=>
标志是“关键”,可以是任何你想要的东西。 Bjy 中的约定是它与实际的类名和路径相似。还有右边的东西=>
是您想要使用此键调用的类的实际完全限定命名空间。