Контроль доступа к классам в PHP

Мне нужно организовать какой-то контроль доступа к объектным методам, когда он используется в разных контекстах (API в моей системе). Вот пример кода:

class A { public function doA(){} public function doB(){} } class APIAClient { public function getA() { return new A(); } } class APIBClient { public function getA() { return new A(); } } 

В объекте APIAClient A должны иметь оба метода doA () и doB (), но в APIBClient не должен иметь метод doB ().

На данный момент я реализовал APIBClientAProxy (который возвращается APIBCleint-> getA ())

  class APIBClientAProxy { private $a = new A; public function doA() { $this->a->doA() } } 

Но может быть, есть лучшая модель для решения моей проблемы, без использования дополнительного прокси-объекта для каждого контекста (например, API). Я думаю о магическом методе __call со списком разрешенных методов в определенном контексте, но магические вызовы трудно документировать и документация – это большая точка в моем приложении (API должен быть хорошо документирован)

Благодаря!

Вместо наследования вы можете использовать композицию через черты (введенные в PHP 5.4).

Сначала определите черты

 trait A { public function doA() { // do something here } } trait B { public function doB() { // do something here } } 

затем используйте эти черты в объявлении класса

 class APIAClient { use A, B } class APIBClient { use A } 

Вы можете использовать наследование здесь, например:

 class A { public function doA() { // do something here } } class B extends A { public function doB() { // do something here } } class APIAClient { public function getObj() { return new B(); } } class APIBClient { public function getObj() { return new A(); } } 

Таким образом, когда вы вызываете getObj() на APIAClient, он возвращает экземпляр B который имеет как doA() и doB() . Однако, когда вы вызываете его на APIBClient , вы возвращаете экземпляр A который имеет только doA() .

Вы не можете изменить класс в зависимости от того, когда и как создаются экземпляры (ну, не совсем).
Вы можете использовать хакерское обходное решение (но я бы рекомендовал против него)

 class A { private $_canDoB = null; public function __construct($doB = true) { $this->_canDoB = !!$doB;//force bool } public function doB() { if ($this->_canDoB === false) { throw new LogicError('You can\'t doB'); } } } 

Поэтому, если вы передадите значение фальши в конструктор A (в вашем APIBClient ), doB ошибку. Однако я бы рекомендовал использовать наследование:

 class AB { public function doA() { //both B and B share this method } } class B {//nothing atm } class A { public function doB() } 

И APIAClient ваш APIAClient вернет new A() , тогда как APIBClient возвращает новый экземпляр класса B
При использовании типа-намека вы можете просто проверить экземпляры AB :

 public function doSomething(AB $instance) { if ($instance instanceof A) { return $instance->doB(); } return $instance->doA(); } 

Или, не полагаясь на тип-намеки и проверку типов, вы всегда можете использовать одну из многих функций, таких как method_exists