开发者

Dynamically creating instance variables in PHP classes

I'm not sure if this is a trivial questions but in a PHP class:

MyClass:

class MyClass {
   public $var1;
   public $var2;

    constructor() { ... }

    public method1 () {

    // Dynamically create an instance variable
         $this->var3 = "test"; // Public....?


    }
}

Main:

$test = new MyClass();
$test->method1();
echo $test->var3; // Would return "test"

Does this work?? How would I get this to work? Ps. I wrote this quickly so please disregard any errors I made with setting up the class or calling methods!

EDIT What about making these instance variables that I create private??

EDIT 2 Thanks all for responding - Everyone is right - I should have just tested it out myself, but I had an exam the next morning and had this thought while studying th开发者_如何学Cat I wanted to check to see if it worked. People keep suggesting that its bad OOP - maybe but it does allow for some elegant code. Let me explain it a bit and see if you still think so. Here's what I came up with:

//PHP User Model: 

class User {
    constructor() { ... }

    public static find($uid) {
         $db->connect(); // Connect to the database

         $sql = "SELECT STATEMENT ...WHERE id=$uid LIMIT 1;";
         $result = $db->query($sql); // Returns an associative array

         $user = new User();

         foreach ($result as $key=>$value)
            $user->$$key = $value; //Creates a public variable of the key and sets it to value

         $db->disconnect();
    }
}

//PHP Controller:

function findUser($id) {

    $User = User::find($id);

    echo $User->name;
    echo $User->phone;
    //etc...

}

I could have just put it in an associative array but I can never correctly name that array something meaningful (ie. $user->data['name'] ... ugly.) Either way you have to know what is in the database so I do not really understand what the argument is that its confusing, especially since you can just var dump objects for debugging.


Why dont you just write the code and see for yourself?

<?php
class Foo
{
    public function __construct()
    {
        $this->bar = 'baz';
    }
}

$foo = new Foo;
echo $foo->bar; // outputs 'baz'

and

var_dump($foo);

gives

object(Foo)#1 (1) {
    ["bar"] => string(3) "baz"
}

but

$r = new ReflectionObject($foo);
$p = $r->getProperty('bar');
var_dump($p->isPublic());

will throw an Exception about 'bar' being unknown, while

$r = new ReflectionObject($foo);
$p = $r->getProperties();
var_dump($p[0]->isPublic());

will return true.

Now, should you do this type of assignment? Answer is no. This is not good OOP design. Remember, OOP is about encapsulation. So, if bar is describing some public property of the class, make it explicit and declare it in your class as public $bar. If it is supposed to be private declare it as private $bar. Better yet, dont use public properties at all and make them protected and provide access to them only through getters and setters. That will make the interface much more clearer and cleaner as it conveys what interaction is supposed to be possible with an object instance.

Assigning properties on the fly here and there across your code, will make maintaining your code a nightmare. Just imagine somewhere along the lifecylce of Foo someone does this:

$foo = new Foo;
$foo->monkey = 'ugh';

echo $foo->monkey; // outputs 'ugh'

Now, from looking at the class definition above, there is absolutely no way, a developer can see there is now a monkey patched into Foo. This will make debugging a pain, especially if code like this is frequent and distributed across multiple files.


Yes that will indeed work. Auto-created instance variables are given public visibility.


yes that works as you'd hope/expect.


I you wanted to make private variables on the fly you could use php magic functions to emulate this, e.g

MyClass

<?php
class MyClass {
    public $var1;
    public $var2;
    private $data = array();

    public function __get($key) {
        // for clarity you could throw an exception if isset($this->data[$key]) 
        // returns false as it is entirely possible for null to be a valid return value
        return isset($this->data[$key]) ? return $this->data[$key] : null;
    }

    public function __set($key, $value) {
        $this->data[$key] = $value;
    }
}
?>

Main

<?php
$test = new MyClass();
$test->myVar = 'myVar is technically private, i suppose';
echo $this->myVar; // 'myVar is technically private
?>

Although these dynamically created variables are technically private, they are infact publicly accessible... i cannot image the purpose for wanting to dynamically create private instance variables. I would question your design.


Did you try it?

It is possible but you might get strict errors. If you dynamically need to create these variables, you are probably doing something wrong.

You should either change this into a function:

function var($no) { .. }

or use __get (http://ca.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜