Question

I come from a .NET world. Now entering these frigid php waters.

I found an example that got me a little confused. Of course, I am trying to apply OOP fundamentals to this php code but it doesn't make sense.

This is the class i am talking about.

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

Alright, it's obvious to me that in the method findByIdentity($id) all it's doing is creating a static new instance of User. This is the first thing that caught me off guard.

In .net you cannot create an instance of a static class.

Now, moving on. in that line

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

the second thing that intrigues me is the following.

Since all you have in that array is a key/value collection....

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

how does php determine that it has to create an User object? Reflection? Which leads me to the next question.... looking at the class that it inherits from, Object, in the constructor, there's in one parameter which is an array (one of the elements of the array above).

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

BUT, this class in its constructor, is calling Yii::configure($this, $config) and in this method, the way I see it, Yii is adding to $this (the Object instance I am assuming, not the User one) the parameters that belong to User.

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

Seems to me like it's adding parameters dynamically to Object which will be accessed by User via the matching parameters.

Makes sense?

From my .net standpoint, $this in Object refers to Object instance itself, not to the User instance inheriting from it (like my friend says). I told him that's a violation of basic OOP principles and it's simply impossible.

Anyone that could make me understand about this?

Thank you.

Was it helpful?

Solution

For anyone interested, here is a good answer with a lengthy explanation.

http://forums.phpfreaks.com/topic/286702-php-inheritance-dynamic-properties-and-new-static-constructor/

Enjoy!

OTHER TIPS

There's no such thing as a static class in PHP, you can have static methods and static members in it. But every class can be instantiated. You can throw an Exception in the constructor though.

Now... on the static keyword. In the context you're using it, it's calling the late statically bound class' constructor. Here's some code that will help you.

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

class Other extends Something {

}

When you call getInstance from the context of Other, what getInstance does is call the constructor for the class Other

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

Also, since you're inheriting from the yii\base\Object class, and you're not defining a constructor in User, the constructor that is called is the one in yii\base\Object


Now to the second part of your question

From my .net standpoint, $this in Object refers to Object instance itself, not to the User instance inheriting from it (like my friend says). I told him that's a violation of basic OOP principles and it's simply impossible.

$this referes to the actual object, whatever the class the object was instantiated from. You can do that in .NET as well, though you'd need to cast your object. But for the sake of PHP where there's no strong typing, the object presents itself as is and you can make use of it as is.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top