Динамическое создание переменных экземпляра в классах PHP - PullRequest
0 голосов
/ 17 декабря 2009

Я не уверен, что это тривиальные вопросы, но в классе PHP:

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"

Это работает ?? Как бы мне заставить это работать? Ps. Я написал это быстро, поэтому, пожалуйста, не обращайте внимания на любые ошибки, которые я допустил при настройке класса или вызове методов!

EDIT Как насчет того, чтобы сделать эти переменные экземпляра, которые я создаю, закрытыми ??

РЕДАКТИРОВАТЬ 2 Спасибо всем за то, что ответили - все правы - я должен был просто проверить это сам, но на следующее утро у меня был экзамен, и во время учебы мне пришла в голову мысль, что я хотел проверить, работает ли это. Люди продолжают утверждать, что это плохой ООП - возможно, но он допускает некоторый элегантный код. Позвольте мне объяснить это немного и посмотреть, если вы все еще так думаете. Вот что я придумал:

//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...

}

Я мог бы просто поместить его в ассоциативный массив, но я никогда не смогу правильно назвать этот массив чем-то значимым (т. Е. $ User-> data ['name'] ... безобразно.) В любом случае вы должны знать, что в базе данных, поэтому я не совсем понимаю, в чем аргумент, что это сбивает с толку, тем более что вы можете просто изменять объекты дампа для отладки.

Ответы [ 5 ]

6 голосов
/ 17 декабря 2009

Почему бы вам просто не написать код и убедиться в этом?

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

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

и

var_dump($foo);

дает

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

но

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

выдаст исключение о том, что 'bar' неизвестен, а

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

вернет истину.

Теперь, вы должны выполнить это назначение? Ответ - нет. Это не хороший дизайн ООП. Помните, что ООП - это инкапсуляция. Итак, если bar описывает какое-то открытое свойство класса, сделайте его явным и объявите его в своем классе как public $bar. Если он должен быть закрытым, объявите его как private $bar. А еще лучше, вообще не использовать публичные свойства, делать их protected и предоставлять доступ к ним только через методы получения и установки. Это сделает интерфейс намного более понятным и понятным, так как передает, какое взаимодействие должно быть возможным с экземпляром объекта.

Назначение свойств «на лету» по всему коду делает обслуживание вашего кода кошмаром. Просто представьте, что где-то в жизни Фу кто-то делает это:

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

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

Теперь, взглянув на определение класса, приведенное выше, разработчик абсолютно не может понять, что теперь есть обезьяна, исправленная в Foo. Это затруднит отладку, особенно если такой код часто встречается и распределяется по нескольким файлам.

5 голосов
/ 17 декабря 2009

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

2 голосов
/ 17 декабря 2009

Если вы хотите создавать приватные переменные на лету, вы можете использовать магические функции php, чтобы эмулировать это, например,

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

Хотя эти динамически создаваемые переменные технически являются частными, они фактически доступны публично ... Я не могу представить себе цель для динамического создания частных переменных экземпляра. Я бы поставил под сомнение ваш дизайн.

2 голосов
/ 17 декабря 2009

да, это работает так, как вы надеетесь / ожидаете.

1 голос
/ 17 декабря 2009

Вы пробовали это?

Возможно, но вы можете получить строгие ошибки. Если вам нужно динамически создавать эти переменные, вы, вероятно, делаете что-то не так.

Вы должны либо изменить это на функцию:

function var($no) { .. }

или используйте __get (http://ca.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...