方法中的php类方法

If I want to access the public method, I can do that easily. But if I want to access the property within method, what should I do, and is it recommended??

Can I do something like this in php?

class Auth {
   public function check($user = false){
    $project = false; //make it somehow public
     if($user == 'user1'){
       $this->project = 1;
     }
   }
}

and than in some other place

$auth = new Auth();
$auth->check('user1')->project;

Just so you people know its possible here is the Zend framework code from

Zend-Authentication

 if ($result->isValid()) {
            $this->getStorage()->write($result->getIdentity());
        }

You will need to add it as a class variable:

class Auth {
   public $project = false;

   public function check($user = false) {
     if($user == 'user1'){
       $this->project = 1;
     }
   }
}

The property is then available as follows:

$auth = new Auth ();
$auth->check ('user1');
echo $auth->project; // 1
<?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);

This will return you 1. The local variables defined in function are only accessbile inside the function not outside hence you need to define them globally

$project is a local variable in your case, visible within the scope of the check method. You could define it as a member:

class Auth {
   public $project = false;
   public function check($user = false){
     if($user == 'user1'){
       $this-project = 1;
     }
   }
}

However, it is recommendable to make the member public and reach it via a getter, which will check whether it was initialized and if not, initialize it:

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;
     }
   }
}

If you don't want to create extra class properties and "preserve method chaining", what about 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;
   }
}

Later on you can discover it as follows:

$array = iterator_to_array($auth->check($user));
// array(1) { ["project"] => bool(false) }

But for this to use you won't be able to use method chaining, bec. you need to retrieve generator anyway, so better to revise approach for discovering the $project.

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;
   }
}

then you can do the following:

$auth = new Auth();
$auth->check('user1')->project(); // returns 1

or if you want you can also set another default value for the $projectin the constructor

$auth = new Auth($other_default_value);
$auth->check('user2')->project();  // returns $other_default_value

I believe your question is basically regarding Fluent Interfaces or Method Chaining in conjunction with the magic method __get

Attempting to run this:

<?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;

Results in:

Notice: Trying to get property of non-object in /in/Hi5Rc on line 13

because $auth->check('user1') returns NULL (or void) and NULL doesn't have a project property.

The first thing we require is for $auth->check('user1') to return something useful. Given that $project is a boolean and $this->project is an integer, it makes the most sense to just return $project and get the value.

<?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'));

which results in :

bool(false)

But that doesn't address your question about how to fluently access a nonpublic field or parameter.

It appears that you are operating under the misconception that these projects are taking method scoped variables like $project in your check() class and making them accessible. They are not.

Not even in your example of the Zend-Authentication.

The field $storage itself is protected, but it has public (fluent) getters/setters.

So, $this->getStorage() returns an instance of new Storage\Session() which has a public write().

Thus $this->getStorage()->write() works.

So lets take your example class and modify it a bit to demonstrate.

<?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();

now results in:

{"name":"Project: user1","active":true,"description":"This project belongs to user1"}

However, you wanted to access the private field as if it were a public field without using a defined getter/setter. So lets make some more changes to the Auth class.

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;
        }
    }

}

Now you can fluently access the field as you requested:

$auth = new Auth();
echo $auth->check('baduser')->project;
echo  "
";
echo $auth->check('user1')->project;

results in:

{"name":"Default","active":false,"description":""}

{"name":"Project: user1","active":true,"description":"This project belongs to user1"}

Laravel's Eloquent models make great use of the __get()function for accessing model fields dynamically. Laravel also makes great use of the __call() magic method for fluency.

I hope that helps bring some clarity.