Наследование Php, динамические свойства и новый статический() конструктор

Я родом из мира .NET. Теперь войдите в эти фригидные воды php.

Я нашел пример, который немного озадачил меня. Конечно, я пытаюсь применить основы ООП к этому PHP-коду, но это не имеет смысла.

Это класс, о котором я говорю.

<?php

namespace app\models;

class User extends \yii\base\Object implements \yii\web\IdentityInterface
{
    public $id;
    public $username;
    public $password;
    public $authKey;

    private static $users = [
        '100' => [
            'id' => '100',
            'username' => 'admin',
            'password' => 'admin',
            'authKey' => 'test100key',
        ],
        '101' => [
            'id' => '101',
            'username' => 'demo',
            'password' => 'demo',
            'authKey' => 'test101key',
        ],
    ];

    public static function findIdentity($id)
    {
        return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
    }

    public static function findByUsername($username)
    {
        foreach (self::$users as $user) {
            if (strcasecmp($user['username'], $username) === 0) {
                return new static($user);
            }
        }
        return null;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getAuthKey()
    {
        return $this->authKey;
    }

    public function validateAuthKey($authKey)
    {
        return $this->authKey === $authKey;
    }

    public function validatePassword($password)
    {
        return $this->password === $password;
    }
}

Хорошо, мне очевидно, что в методе findByIdentity ($ id) все, что он делает, создает статический новый экземпляр пользователя. Это первое, что меня насторожило.

В .net вы не можете создать экземпляр статического класса.

Теперь двигаемся дальше. в этой строке

return isset(self::$users[$id])? new static(self::$users[$id]) : null;

второе, что меня интригует, следующее.

Так как все, что у вас есть в этом массиве, это коллекция ключей/значений....

private static $users = [
        '100' => [
            'id' => '100',
            'username' => 'admin',
            'password' => 'admin',
            'authKey' => 'test100key',
        ],
        '101' => [
            'id' => '101',
            'username' => 'demo',
            'password' => 'demo',
            'authKey' => 'test101key',
        ],
    ];

как php определяет, что он должен создать объект User? Отражение? Это приводит меня к следующему вопросу.... глядя на класс, который он наследует, Object, в конструкторе, там в одном параметр, который является массивом (одним из элементов массива выше).

public function __construct($config = [])
{
    if (!empty($config)) {
        Yii::configure($this, $config);
    }
    $this->init();
}

НО, этот класс в своем конструкторе вызывает Yii:: configure ($ this, $config) и в этом методе, как я его вижу, Yii добавляет к $this (экземпляр объекта, который я предполагаю, а не Пользователь), параметры, которые принадлежат Пользователю.

public static function configure($object, $properties)
{
    foreach ($properties as $name => $value) {
        $object->$name = $value;
    }
    return $object;
}

Мне кажется, что он динамически добавляет параметры в Object, который будет доступен пользователю через соответствующие параметры.

Имеет смысл?

С моей точки зрения .net $this в Object ссылается на экземпляр объекта, а не на экземпляр пользователя, наследующий его (как говорит мой друг). Я сказал ему, что нарушение основных принципов ООП и это просто невозможно.

Кто-нибудь, кто мог бы мне понять об этом?

Спасибо.

Ответ 2

В PHP нет такой вещи, как статический класс, в ней могут быть статические методы и статические члены. Но каждый класс может быть создан. Однако вы можете использовать исключение в конструкторе.

Теперь... по ключевому слову static. В контексте, который вы используете, он вызывает конструктор позднего статически связанного класса. Вот код, который поможет вам.

class Something {
    public static function getInstance() {
        return new static();
    }
}

class Other extends Something {

}

Когда вы вызываете getInstance из контекста Other, то, что getInstance делает, вызывает конструктор для класса Other

// this will print `Other`
echo get_class(Other::getInstance());

Кроме того, поскольку вы наследуете от класса yii\base\Object и не определяете конструктор в User, вызываемый конструктор является тем, который находится в yii\base\Object


Теперь во вторую часть вашего вопроса

С точки зрения my.net, $this в Object ссылается на экземпляр объекта непосредственно, а не на экземпляр пользователя, наследующий его (как говорит мой друг). Я сказал ему, что нарушение основных принципов ООП и это просто невозможно.

$это относится к фактическому объекту, независимо от класса, из которого был создан объект. Вы можете сделать это и в .NET, хотя вам нужно будет отбросить ваш объект. Но для PHP, где нет сильной типизации, объект представляет себя как есть, и вы можете использовать его как есть.