如果我想访问公共方法,我可以轻松做到。但是如果我想访问方法内的属性,我应该做什么,是否推荐?
我可以在 php 中做这样的事情吗?
class Auth {
public function check($user = false){
$project = false; //make it somehow public
if($user == 'user1'){
$this->project = 1;
}
}
}
比其他地方
$auth = new Auth();
$auth->check('user1')->project;
只是为了让大家知道这是可能的,这是来自
的
Zend framework
代码
Zend-Authentication
if ($result->isValid()) {
$this->getStorage()->write($result->getIdentity());
}
我相信你的问题基本上是关于流畅的接口或方法链接与魔术方法
__get
尝试运行此:
<?php
class Auth {
public function check($user = false){
$project = false; //make it somehow public
if($user == 'user1'){
$this->project = 1;
}
}
}
$auth = new Auth();
$auth->check('user1')->project;
结果:
注意:第 13 行尝试获取 /in/Hi5Rc 中非对象的属性
因为
$auth->check('user1')
返回 NULL(或 void),并且 NULL 没有 project
属性。
我们需要的第一件事是让
$auth->check('user1')
返回一些有用的东西。鉴于 $project
是布尔值,而 $this->project
是整数,因此最有意义的是返回 $project
并获取值。
<?php
class Auth {
public function check($user = false){
$project = false; //make it somehow public
if($user == 'user1'){
$this->project = 1;
}
return $project;
}
}
$auth = new Auth();
print_r($auth->check('user1'));
结果是:
布尔(假)
但这并不能解决您关于如何流畅访问非公共字段或参数的问题。
您似乎误以为这些项目正在使用$project
类中的
方法作用域变量(如
check()
)并使它们可访问。他们不是。
甚至在您的 Zend-Authentication 示例中也没有。
$storage
本身是受保护的,但它具有公共(流畅)getters/setters。
因此,
$this->getStorage()
返回 new Storage\Session()
的实例,它具有公共 write()
。
因此
$this->getStorage()->write()
有效。
因此,让我们对示例类进行一些修改以进行演示。
<?php
class Project{
/**
* @var string
*/
private $name;
/**
* @var bool
*/
private $active;
/**
* @var string
*/
private $description;
public function __construct($name = 'Default', $active = false, $description = '')
{
$this->name = $name;
$this->active = $active;
$this->description = $description;
}
/**
* @param string $name
*
* @return Project
*/
public function setName(string $name): Project
{
$this->name = $name;
return $this;
}
/**
* @param bool $active
*
* @return Project
*/
public function setActive(bool $active): Project
{
$this->active = $active;
return $this;
}
/**
* @param string $description
*
* @return Project
*/
public function setDescription(string $description): Project
{
$this->description = $description;
return $this;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return bool
*/
public function isActive(): bool
{
return $this->active;
}
/**
* @return string
*/
public function getDescription(): string
{
return $this->description;
}
public function toArray(){
return [
'name' => $this->name,
'active' => $this->active,
'description' => $this->description
];
}
public function toJson(){
return json_encode($this->toArray());
}
public function __toString()
{
return $this->toJson();
}
}
class Auth {
/**
* @var Project
*/
private $project;
public function __construct($project = Null)
{
$this->project = is_null($project)? new Project() : $project;
}
public function check($user = false){
if($user == 'user1'){
$this->project->setName("Project: $user")->setActive(true)->setDescription("This project belongs to $user");
}
return $this;
}
/**
* @param Project $project
*
* @return Auth
*/
public function setProject(Project $project): Auth
{
$this->project = $project;
return $this;
}
/**
* @return Project
*/
public function getProject(): Project
{
return $this->project;
}
}
$auth = new Auth();
echo $auth->check('user1')->getProject();
现在的结果是:
{"name":"项目:user1","active":true,"description":"该项目 属于用户1”}
但是,您希望像访问公共字段一样访问 private 字段,而不使用定义的 getter/setter。因此,让我们对
Auth
类进行更多更改。
class Auth {
/**
* @var Project[]
*/
private $private_project;
public function __construct($project = Null)
{
$this->private_project = is_null($project)? new Project() : $project;
}
public function check($user = false){
if($user == 'user1'){
$this->private_project->setName("Project: $user")->setActive(true)->setDescription("This project belongs to $user");
}
return $this;
}
public function __get($name)
{
if ($name === 'project'){
return $this->private_project;
}
}
}
现在您可以按照您的要求流畅地访问该字段了:
$auth = new Auth();
echo $auth->check('baduser')->project;
echo "\n";
echo $auth->check('user1')->project;
结果:
{"名称":"默认","活动":false,"描述":""}
{"name":"项目:user1","active":true,"description":"该项目属于user1"}
__get()
函数来动态访问模型字段。 Laravel 还充分利用了 __call()
魔法方法来提高流畅度。
我希望这有助于澄清一些问题。
class Auth
{
protected $project;
public function __constructor($project = false)
{
$this->project = $project;
}
public function check($user = false)
{
if($user == 'user1')
{
$this->project = 1;
}
return $this;
}
public function project()
{
return $this->project;
}
}
然后您可以执行以下操作:
$auth = new Auth();
$auth->check('user1')->project(); // returns 1
或者如果您愿意,您还可以在构造函数中为
$project
设置另一个默认值
$auth = new Auth($other_default_value);
$auth->check('user2')->project(); // returns $other_default_value
yield
呢?
class Auth
{
public function check($user = false)
{
$project = false; // make it somehow public
if($user === 'user1'){
(yield 'project' => $project); // making it public
}
return $this;
}
}
稍后你可以发现它如下:
$array = iterator_to_array($auth->check($user));
// array(1) { ["project"] => bool(false) }
但是要使用此功能,您将无法使用方法链接,因为无论如何您都需要检索生成器,因此最好修改方法来发现
$project
。
<?php
class Auth
{
public $project;
public function check($user = false)
{
$this->project = false;//make it somehow public
if ($user == 'user1') {
$this->project = 1;
}
return $this;
}
}
$auth = new Auth();
var_dump($auth->check('user1')->project);
这将返回 1。函数中定义的局部变量只能在函数内部访问,不能在外部访问,因此您需要全局定义它们
$project
是您的情况下的局部变量,在 check
方法的范围内可见。您可以将其定义为成员:
class Auth {
public $project = false;
public function check($user = false){
if($user == 'user1'){
$this-project = 1;
}
}
}
但是,建议创建成员
public
并通过getter访问它,这将检查它是否已初始化,如果没有,则初始化它:
class Auth {
private $project = false;
public getProject($user = false) {
if ($this->project === false) {
check($user);
}
return $this->project;
}
public function check($user = false){
if($user == 'user1'){
$this-project = 1;
}
}
}
您需要将其添加为类变量:
class Auth {
public $project = false;
public function check($user = false) {
if($user == 'user1'){
$this->project = 1;
}
}
}
该房产的可用方式如下:
$auth = new Auth ();
$auth->check ('user1');
echo $auth->project; // 1