Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP how to use magic method with static class? [duplicate]

Tags:

php

class

static

I'm trying to convert array to object. I want to use magic methods - __get and __set with static properties.

My code:

class UserData {
    private static  $id, $name, $login;

    public function __get($var)
    {
        return self::$var;
    }
    public function __set($var, $val)
    {
        self::{$var} = $val;
    }
}

And setting:

foreach($userArray as $key => $val) 
    {
        DaneBilingowe::${$key} = $val;
    }

Error: Fatal error: Cannot access private property UserData::$id

Is it possible to use magic method with static property?

like image 711
webrama.pl Avatar asked Mar 15 '13 07:03

webrama.pl


2 Answers

In short, no.

__get() and __set() are instance methods. They are essentially the functions that make up the stdClass(), which is an instance.

If you must set static content in this manner you can give the class a stdClass parameter and a singleton structure that would allow you to magically set and get data.

For example:

class UserData {
    protected static $_instance;
    protected $_data = array();

    public static function get_instance() {
        static $initialized = FALSE;

        if ( ! $initialized) {
            self::$_instance = new UserData;
            $initialized = TRUE;
        }

        return self::$_instance;
    }

    public function __get($var) {
        $self = self::get_instance();

        return isset($self->_data[$var]) ? $self->_data[$var] : NULL;
    }

    public function __set($var, $val) {
        $self = self::get_instance();

        $self->_data[$var] = $val;
    }
}

Then you could go:

 $UserData =& UserData::get_instance();
 $UserData->var = 'val';

 echo $UserData->var; // prints 'val'

I don't recommend using Singletons in PHP, however, because they are pointless. You can read some reasons why in the post Best practice on PHP singleton classes.

Either use a static class or an instance class.

Magic getters and setters are shortcuts. You can implement the same behavior with normal setters and getters. The example below provides the same functionality, but the intent is a lot more clear:

class UserData {
    protected $id, $name, $login;

    public static function set_name($name) {
        self::$name = $name;
    }

    public static function set_login($login) {
        self::$login = $login;
    }

    public static function get_id() {
        return self::$id;
    }

    public static function get_name() {
        return self::$name;
    }

    public static function get_login() {
        return self::login;
    }
}

Notice how in the above code $id is not writable. It is only readable. $name and $login are readable and writable. It is easier and less buggy to control reading and writing using normal setters and getters. Magic methods are just that, magic, and usually magic is not concrete and is less understandable in code.

The final point I want to make is, why would UserData be static? Unless you only have 1 user in the entirety of your code it doesn't make sense to have it static. Perhaps I am not getting the whole picture, but something with an id and name should be instantiated so that you can have multiple instances. Otherwise, why have the id because the class itself is unique.

like image 83
None Avatar answered Oct 14 '22 07:10

None


If you really want to use magic methods on static properties, you can but you will need an instance. Though it does not look reasonable, being a programmer itself is not reasonable at all :)

Also user defined classes and objects are not dynamic in php. You can not add variables to them that easily... So you can use the pattern below:

class UserData {
    private static  $id, $name, $login, $arr = [];

    public function __get($var){
        return (array_key_exists(self::$arr, $var)? self::$arr[$var]:null;
    }

    public function __set($var, $val){
        self::$arr[$var] = $val;
    }
}

And setting: Well what is DaneBilingowe? I do not now here... But:

$inst = new UserData();

foreach($userArray as $key => $val){
    $inst->$key = $val;
}

will work.

But beware, It will work only on class (static) memory. Also since there is no appropriate filtering for setting names, weird things can happen. (That means you should add them)

like image 32
Volkan Avatar answered Oct 14 '22 05:10

Volkan