0 / 0 / 1
Регистрация: 11.10.2017
Сообщений: 27
1

(ООП) Область видимости полей, созданных динамически

29.10.2017, 13:46. Показов 973. Ответов 10
Метки нет (Все метки)

Есть у меня такой класс

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class AjaxCoreObject extends StdClass{
// всякие разные поля класса
 
// и есть в нем вот такая функция
function ArrayCount($arrayname) {
        // обработка строкового списка значений. создает аналог типа "массив" а так же его размер, как поля родительского объекта.
        
        $mids = explode(",", $this->$arrayname);
        $a = 0;
        $b = 0;
        $ename = 'exploded_'.$arrayname;
        unset($this->$ename);
        $ecount = 'count_'.$arrayname;
        while (isset($mids[$a])) { 
            $value = $mids[$a];
            echo $ename.'['.$b.']= '.$value; // вывод добавил для отладки, чтобы убедиться что значения заносятся в массив.
            if ((int)$value > 0) {
                $this->$ename[$b] = (int)$value;
                $b = $b + 1; // a & b в данном случае не одно и то же
            }
            $a = $a + 1;
        }
        if ((!isset($this->$ecount)) || ($this->$ecount != $a)) {
        $this->$ecount = $a;
        $this->OnChange();
        }
        // обращаться к массиву всегда с проверкой его существования (if $this->count_arrayname > 0)
        return $a;
    }
По идее эта функция должна обработать поле класса $this->$arrayname (которое является строкой), и строку оставить без изменений, но создать новые поля exploded_.$arrayname в виде массива, и count_.$arrayname в виде числа (размер массива).

И есть другой класс
PHP
1
2
3
include_once "ajaxcore.php";
class XGroup extends AjaxCoreObject{
public $participants = '1,2,14,20,21,24,27'; // перечисление значений в виде строки
логично, что public $exploded_participants и public $count_participants тут нету, они должны быть добавлены динамически уже после.
так же в классе XGroup есть большая длинная функция, в которой делается так:
PHP
1
2
$this->ArrayCount('participants');
$target = $this->exploded_participants[2]);
Но по итогам всего действа, после вызова самого последнего кусочка кода, я в логах сервера вижу
[29-Oct-2017 11:59:02 Europe/Moscow] PHP Notice: Undefined property: XGroup::$exploded_participants in E:\storage\programming\OpenServer\domains\frtp\cla sses\xgroup.php on line 256
Причем, отладочные echo-выводы в функции ArrayCount класса Ajaxcore, сообщают что массив успешно создан и заполнен значениями. а в классе XGroup, который является потомком Ajaxcore, этого массива не видно.
Как динамически создать новые поля класса, так чтобы потомки класса его видели?

Edit: только после создания темы, заметил что на форуме есть раздел PHP: ООП. Если модераторы перенесут тему туда, возражать не буду)
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.10.2017, 13:46
Ответы с готовыми решениями:

Обработка динамически созданных полей
Всем привет. Перейду сразу к делу. Есть форма в виде таблицы из 2 полей, по желанию пользователь...

Область видимости
Объясните с чем связана такая область видимости локальных переменных <?php $a = 5; function...

Область видимости
Есть страница index.php function send(){ include 'connect.php'; connect(); ...

Область видимости
Доброго времени суток. Есть скрипт регистрации (который уже наверно всем надоел :D), в нем я...

10
2192 / 1125 / 227
Регистрация: 16.03.2008
Сообщений: 5,298
Записей в блоге: 2
29.10.2017, 14:26 2
Хм... Что то мне кажется (я конечно не знаю деталей вашей задачи, но тем не менее), что создавать свойства класса это дурной тон. При чем даже не класса, а объекта... Т.е. по факту вы уже имеете объект какого то иного класса. Если использовать эти "новоиспеченные" свойства вне класса - то есть шанс однажды уронить проект, забыв о существовании свойства... Или выкинув "за ненадобностью" (а по факту забыв) незадекларированое в классе свойство.... А если это свойство пропадет из источника - обрушится проект? бррр.... Я бы руки пообрывал.

На мой личный взгляд правильнее было бы сделать приватное свойство типа массив (ассоциативный) и заносить в него все, что вам нужно. А для получения значений вне класса - сделать геттер. (а если нужно и задавать по отдельности - сеттер). В геттере проверять наличие и производить определенное действие (бросать исключение, возвращать специальное значение). Так ваш код будет прозрачным и понятным.

А так вы даже задокументировать не сможете. Т.е. я работаю с вашим кодом в нормальной ide. Вижу типа $myObhect->exploded_participants , подсказки не появляется, гляжу в описание класса- там нет такого.... ужас.

Добавлено через 4 минуты
Цитата Сообщение от Zander_driver Посмотреть сообщение
Как динамически создать новые поля класса, так чтобы потомки класса его видели?
О как.. Это еще хлеще. Ни как. Приведенным выше кодом, вы свойства не у класса создаете, а у объекта. Для нужного вам эффекта., делайте protected статическое свойство типа массив и далее как выше я сказал
0
Эксперт PHP
4841 / 3853 / 1599
Регистрация: 24.04.2014
Сообщений: 11,304
29.10.2017, 14:34 3
Zander_driver, рекомендую весь код выше удалить, почитать литературу по теме объектно ориентированное проектирование, и после этого вернуться к задаче
Цитата Сообщение от voral Посмотреть сообщение
Приведенным выше кодом, вы свойства не у класса создаете, а у объекта.
Думаю это и имелось ввиду, просто ТС не разделяет понятия класс и объект
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A {
    public function foo() {
        $this->a = 'it works';
    }
}
 
class B extends A {
    public function bar() {
        return $this->a;
    }
}
 
$b = new B();
$b->foo();
echo $b->bar();
https://ideone.com/5tF5fJ
0
0 / 0 / 1
Регистрация: 11.10.2017
Сообщений: 27
29.10.2017, 15:41  [ТС] 4
просто ТС не разделяет понятия класс и объект
Заблуждаетесь, очень даже разделяю.
Есть классы, они могут друг друга наследовать, а есть объекты, которые могут быть экземплярами класса.
В моем верхнем посте имелось в виду - как методами класса-родителя, создавать динамические поля видимые для методов класса-потомка.
Создавать у объекта конечно же, просто вопрос касается принадлежности методов (создающих и читающих) к разным классам.

Добавлено через 5 минут
Т.е. по факту вы уже имеете объект какого то иного класса.
Именно да. Отчасти понимаю, почему в php это считается дурным тоном, то самое "смотрю в описание класса, а там такого нету" - да)
Но, на Луа например я раньше многократно делал объекты классов, с динамически добавляемыми полями как переменных, так и методов. Эдакий объект, который "на лету" определяет, какие интерфейсы он (его класс? индивидуально созданный "для этого объекта" уже после его создания) будет реализовывать. Хотя мб в php это действительно лучше делать иначе, через массивы.

Добавлено через 21 минуту
Цитата Сообщение от voral Посмотреть сообщение
При чем даже не класса, а объекта...
Цитата Сообщение от Jewbacabra Посмотреть сообщение
ТС не разделяет понятия класс и объект
В то же время mysqli->query(бла-бла) с последующим result->fetch_object() создает объект с заранее неизвестными полями.
(Известными, если посмотреть структуру БД и запрос)
И класс-родитель у меня наследует от StdClass не случайно...

так что вопрос я все же повторю в более точной формулировке, дабы избежать обвинений в неразличении понятий класс/объект и прочих азов ООП.
Как методами класса-родителя, создать у конкретного объекта, поля (и методы), видимые для методов класса-потомка. Чтобы у данного объекта, методы класса-потомка (собственно класса, объект которого создавался конструктором), могли обращаться к новым динамически созданным полям и методам.
То что приведенная в первопосте задача, решается многими другими путями, это понятно. Как и понятно, что один из вариантов ответа на выделенный вопрос - это создать массив и туда все новосозданное пихать. Но это не всегда приемлемо, а вдруг я хочу динамически переопределять "родные" методы класса? у данного конкретного объекта, разумеется. Мы же динамически переопределяем.
Так что для саморазвития буду благодарен если кто-то даст ответ на вопрос, выделенный жирным.

Добавлено через 9 минут
Прокомментирую то что я хочу.

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class A {
   public function foo() {
      return 3;
   }
   public function set_foo($f) {
      $this->foo = $f; // не вызов функции, а ее присвоение (аргумент $f должен быть функцией)
   }
}
 
class B extends A {
   function transform_my($f) {
      $this->set_foo($f);
   }
}
 
function f () {
return 140;
}
 
$dog_a = new B();
$dog_b = new B();
$dog_b->transform_my($f); // передаем функцию. наверное это делается не совсем так) но смысл думаю понятен
 
$dog_a->foo(); // вернет 3
$dog_b->foo(); // вернет 140
0
Эксперт PHP
4841 / 3853 / 1599
Регистрация: 24.04.2014
Сообщений: 11,304
29.10.2017, 16:10 5
Цитата Сообщение от Zander_driver Посмотреть сообщение
И класс-родитель у меня наследует от StdClass не случайно...
зачем??? Оттуда же ничего не унаследуешь.
Цитата Сообщение от Zander_driver Посмотреть сообщение
Как методами класса-родителя, создать у конкретного объекта, поля (и методы), видимые для методов класса-потомка. Чтобы у данного объекта, методы класса-потомка (собственно класса, объект которого создавался конструктором), могли обращаться к новым динамически созданным полям и методам.
Я уже приводил пример (ООП) Область видимости полей, созданных динамически

В общем повторюсь
Цитата Сообщение от Jewbacabra Посмотреть сообщение
рекомендую весь код выше удалить, почитать литературу по теме объектно ориентированное проектирование, и после этого вернуться к задаче
0
0 / 0 / 1
Регистрация: 11.10.2017
Сообщений: 27
29.10.2017, 17:28  [ТС] 6
Цитата Сообщение от Jewbacabra Посмотреть сообщение
Оттуда же ничего не унаследуешь.
т.е. способность иметь динамически создаваемые поля есть у любого класса? окей. я не был уверен что в php это так.
Цитата Сообщение от Jewbacabra Посмотреть сообщение
Я уже приводил пример
Который наводит на мысли, что вы не понимаете о чем речь, к сожалению. В противном случае поясните мне, почему в моем вышеприведенном коде, экземпляр класса XGroup (его методы), не видят поле exploded_participants, (отсутствующее в описании обоих классов), динамически созданное методом класса AjaxCoreObject.
объект один и тот же. для создания нового поля обращаемся к методу класса-родителя. потом в методе собственно этого класса, к которому принадлежит объект, пытаемся обратиться к этому полю, а оказывается что "его нет". Причина?
0
Эксперт PHP
4841 / 3853 / 1599
Регистрация: 24.04.2014
Сообщений: 11,304
29.10.2017, 18:00 7
Цитата Сообщение от Zander_driver Посмотреть сообщение
Причина?
Значит в коде есть логическая ошибка.
0
0 / 0 / 1
Регистрация: 11.10.2017
Сообщений: 27
29.10.2017, 18:21  [ТС] 8
Порылся в проблеме самостоятельно, получилось следующее.

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?php
ini_set('display_errors','On'); #включаем отображение ошибок если выключено
error_reporting(E_ALL | E_STRICT); #устанавливаем режим отображения - все ошибки и советы
 
class AAA {
    public $a = 1;
    public function get_x($value_name) {
        return $this->$value_name;
    }
    public function add_v($vname, $vval) {
        $this->$vname = $vval;
    }
    public function add_construct_v($vname, $vval) {
        $vxx = 't'.$vname;
        $this->$vxx = $vval;
    }
    public function add_array_a($aname, $aval) {
        $this->$aname[0] = $aval;
    }
    public function add_array_b($aname, $aval) {
        if (!isset($this->$aname)) {
            $this->$aname = array(null);
        };
        $this->$aname[0] = $aval;
    }
    
    public function ftest() {
        return 5;
    }
}
 
class BBB extends AAA {
    public function get_xx($value_name) {
        return $this->$value_name;
    }
}
 
$xB = new BBB();
$xB->add_v('a', 100);
$xB->add_v('b', 101);
$xB->add_construct_v('c', 102);
$xB->add_array_a('xx',11);
$xB->add_array_b('yy',12);
echo '<html>test: <br>'."\n";
echo 'наследник а: '.$xB->get_xx('a').'<br>'."\n";
echo 'наследник b: '.$xB->get_xx('b').'<br>'."\n";
echo 'наследник tc: '.$xB->get_xx('tc').'<br>'."\n";
echo 'родитель а: '.$xB->get_x('a').'<br>'."\n";
echo 'родитель b: '.$xB->get_x('b').'<br>'."\n";
echo 'родитель tc: '.$xB->get_x('tc').'<br>'."\n";
echo 'прямое обращение a: '.$xB->a.'<br>'."\n";
echo 'прямое обращение b: '.$xB->b.'<br>'."\n";
echo 'прямое обращение tc: '.$xB->tc.'<br>'."\n";
echo 'тип поля xx: '.gettype($xB->xx).'<br>'."\n";
echo 'тип поля yy: '.gettype($xB->yy).'<br>'."\n";
echo 'прямое обращение array xx: '.$xB->xx[0].'<br>'."\n";
echo 'прямое обращение array yy: '.$xB->yy[0].'<br>'."\n";
echo '</html>';
 
?>
Результат:
test:
наследник а: 100
наследник b: 101
наследник tc: 102
родитель а: 100
родитель b: 101
родитель tc: 102
прямое обращение a: 100
прямое обращение b: 101
прямое обращение tc: 102

Notice: Undefined property: BBB::$xx in E:\storage\programming\OpenServer\domains\dynclass modify\test.php on line 54
тип поля xx: NULL
тип поля yy: array

Notice: Undefined property: BBB::$xx in E:\storage\programming\OpenServer\domains\dynclass modify\test.php on line 56
прямое обращение array xx:
прямое обращение array yy:
Собственно, с простыми строко-числовыми значениями все прекрасно работает. С массивами творятся странности.
1) если явно не создать его как массив, то его и нету, тип NULL (это в принципе логично, но почему-то умалчивается всеми справочниками, везде утверждается что конструкция вида $a[что-то] = $b при изначальном отсутствии переменной $a, создает массив. Ага щаз.)
2) даже несмотря на то, что массив создан. (тип yy - array) - его значения не доступны.
Вот она собственно и проблема. И не надо мне показывать как просто это делается. Почему не делается в динамически создаваемом массиве?
0
Эксперт PHP
4841 / 3853 / 1599
Регистрация: 24.04.2014
Сообщений: 11,304
29.10.2017, 20:06 9
Лучший ответ Сообщение было отмечено Zander_driver как решение

Решение

Цитата Сообщение от Zander_driver Посмотреть сообщение
везде утверждается что конструкция вида $a[что-то] = $b при изначальном отсутствии переменной $a, создает массив. Ага щаз.
так и есть http://sandbox.onlinephpfuncti... 05aed20ab3
PHP
1
2
3
$obj = new stdClass();
$obj->foo['a'] = 42;
var_dump($obj->foo);
Цитата Сообщение от Zander_driver Посмотреть сообщение
И не надо мне показывать как просто это делается. Почему не делается в динамически создаваемом массиве?
Извини, но мне лень разбираться в твоем коде. Если это работает в простых примерах, значит это работает. Если у тебя не работает - значит идет обращение к свойству прежде чем оно создано

Добавлено через 15 минут
Цитата Сообщение от Zander_driver Посмотреть сообщение
$this->$aname[0] = $aval;
Такие конструкции будут по-разному работать в php 5 и 7.
В 5 скобки будут расставлены таким образом $this->{$aname[0]} = $aval;, в 7 $this->{$aname}[0] = $aval;
В 7 версии этот код будет работать, в 5 нет http://sandbox.onlinephpfuncti... e7dfee5427
0
0 / 0 / 1
Регистрация: 11.10.2017
Сообщений: 27
29.10.2017, 21:00  [ТС] 10
Спасибо. Значит php5 устарел, т.к. поведение "не создавать массив а ругаться, при вызове $this->$несуществующая_переменная[0] = $x;" - логически не верно.
0
Эксперт PHP
4841 / 3853 / 1599
Регистрация: 24.04.2014
Сообщений: 11,304
29.10.2017, 21:17 11
Цитата Сообщение от Zander_driver Посмотреть сообщение
огически не верно.
верно, просто приоритет операторов другой
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.10.2017, 21:17
Помогаю со студенческими работами здесь

Область видимости
&lt;?php if(isset($_POST)){ $count = 0; $m = array(); getVideo(1); getVideo(2);

ПОлучить данные методом Post из динамически созданных input'ов
Вопрос в следующем: Моя задача была написать с помощью яваскрипта скрипт который динамически...

Как передать значения на сервер из динамически созданных <select>
Создаю динамически в таблице элемент select вот таким вот кодом function deleteRow(index){ var...

Область видимости переменных
Добрый день форумчане! Вопрос так сказать новичка.Есть глобальные переменные и локальные.Если...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru