Метод класса php внутри метода

Если я хочу получить доступ к публичному методу, я могу сделать это легко. Но если я хочу получить доступ к свойству внутри метода, что мне делать, и рекомендуется ли это?

Могу ли я сделать что-то подобное в 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());
        }

6 ответов

Я полагаю, что ваш вопрос в основном касается плавных интерфейсов или объединения методов в сочетании с магическим методом. __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;

Результаты в:

Примечание: попытка получить свойство необъекта в /in/Hi5Rc в строке 13

так как $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'));

что приводит к:

BOOL (ложь)

Но это не решает ваш вопрос о том, как получить свободный доступ к непубличному полю или параметру.

Похоже, что вы работаете под неправильным представлением о том, что эти проекты используют такие переменные, как $project в вашем check() класс и сделать их доступными. Они не.

Даже в вашем примере с Zend-аутентификацией.

Поле $storage сам по себе защищен, но у него есть публичные (беглые) методы получения / установки.

Так, $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": "Project: user1", "active": true, "description": "Этот проект принадлежит user1"}

Однако вы хотели получить доступ к закрытому полю, как если бы оно было открытым, без использования определенного метода получения / установки. Итак, давайте внесем еще некоторые изменения в 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;

результаты в:

{ "Имя": "По умолчанию", "активный": ложь, "Описание": ""}

{"name": "Project: user1", "active": true, "description": "Этот проект принадлежит user1"}

Eloquent модели Laravel широко используют __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. Локальные переменные, определенные в функции, являются только accessbile внутри функции, а не снаружи, поэтому вам нужно определить их глобально

Вам нужно будет добавить его как переменную класса:

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

$project является локальной переменной в вашем случае, видимой в рамках check метод. Вы можете определить это как член:

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

Тем не менее, рекомендуется сделать член public и получить его через геттер, который проверит, инициализирован ли он, и, если нет, инициализирует его:

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;
     }
   }
}
Другие вопросы по тегам