在 PHP 中是否有类似于“friend”或“internal”的等效功能?如果没有,是否有任何模式可以遵循以实现此行为?
编辑: 抱歉,但标准的 PHP 并不是我要找的。我正在寻找类似于 ringmaster 所做的东西。
我有一些类在后端执行 C 风格的系统调用,而且调用次数已经变得非常繁琐。在对象 A 中有一些函数,它们将对象 B 作为参数,并必须调用对象 B 中的一个方法并将自身作为参数传递。如果最终用户调用了 B 中的方法,则系统将崩溃。
PHP不支持任何类似于“friend”的声明。使用PHP5的__get和__set方法并检查仅允许的友好类的回溯,可以模拟它,尽管实现代码有点笨拙。
PHP网站上关于这个主题有一些样例代码和讨论:sample code
class HasFriends
{
private $__friends = array('MyFriend', 'OtherFriend');
public function __get($key)
{
$trace = debug_backtrace();
if(isset($trace[1]['class']) && in_array($trace[1]['class'], $this->__friends)) {
return $this->$key;
}
// normal __get() code here
trigger_error('Cannot access private property ' . __CLASS__ . '::$' . $key, E_USER_ERROR);
}
public function __set($key, $value)
{
$trace = debug_backtrace();
if(isset($trace[1]['class']) && in_array($trace[1]['class'], $this->__friends)) {
return $this->$key = $value;
}
// normal __set() code here
trigger_error('Cannot access private property ' . __CLASS__ . '::$' . $key, E_USER_ERROR);
}
}
(tsteiner 在 nerdclub dot net 上证明的代码,在 bugs.php.net 上)
使用php >=5.3.3中的握手和闭包,也可以提升权限,即有选择地泄漏数据。
基本上,交互过程如下:类A具有一个公共方法,该方法接受一个类B对象,并调用B->grantAccess(或您接口定义的任何内容),传递一个闭包。 闭包use($that,$anythingelseyouneed)
其中$that=$this,并且您需要确定哪些属性允许被访问。闭包只有一个参数-要返回的属性;如果它是在$that上的属性并且一切都很好,则闭包返回该属性。否则,它将返回'',或抛出异常,或者可能是默认值。
类B->grantAccess接受可调用对象并存储它,在其他方法中使用它来挑选闭包允许泄漏的私有属性。 将类B的默认构造函数设置为private。使用带有类A参数的静态工厂方法构建B,以确保握手发生。
要参考代码,请单击此处:https://gist.github.com/mcamiano/00592fb400e5043d8acd
<?php
class FooWithFriend {
private function guardOnlyFriend(): void
{
if (( is_a($this, BarFriendOfFoo::class) ) === false ) {
throw new Exception('Only class BarFriendOfFoo he can create me');
}
}
protected function __construct()
{
$this->guardOnlyFriend();
echo 'Hello friend - ';
}
}
final class BarFriendOfFoo extends FooWithFriend {
public function __construct()
{
parent::__construct();
}
}
final class Bar2FriendOfFoo extends FooWithFriend {
public function __construct()
{
parent::__construct();
}
}
$bar = new BarFriendOfFoo();
$bar = new Bar2FriendOfFoo();
$dummy = new FooWithFriend();
现在的PHP有一个类友谊
选项:
class Person
{
friend HumanResourceReport;
protected $id;
protected $firstName;
protected $lastName;
public function __construct($id, $firstName, $lastName)
{
$this->id = $id;
$this->firstName = $firstName;
$this->lastName = $lastName;
}
public function makeReport()
{
return new HumanResourceReport($this);
}
}
class HumanResourceReport
{
private $person;
public function __construct(Person $person)
{
$this->person = $person;
}
public function getFullName()
{
// HumanResourceReport would not have access to protected
// members of Person if not explicitly listed as a friend.
return $this->person->firstName . ' ' . $this->person->lastName;
}
public function getReportIdentifier()
{
return "HR_REPORT_ID_{$this->person->id}";
}
}
更多细节请查看这里:PHP RFC:类友谊
private function foo($arg1, $arg2) { /*function stuff goes here */ }
protected function foo($arg1, $arg2)
我相信在PHP5中,默认情况下函数是公共的,这意味着您不必使用以下语法,但这是可选的:
public function foo($arg1, $arg2) { /*function stuff goes here */ }
在使用公共函数之前,您仍需实例化对象。因此,我将非常详细地向您介绍,在不实例化对象的情况下使用类中的函数,请确保使用以下语法:
static function foo($arg1, $arg2) { /*function stuff goes here */ }
这将允许您仅通过引用类来使用函数,如下所示:
MyClass::foo($a1, $a2);
$myObject = new MyClass();
$myObject->foo($a1, $a2);