Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Проблема с передачей свойства потомку

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: Не передаётся свойство через от родителя к потомку
Neonion
Отправлено: 08 Октября, 2017 - 20:54:21
Post Id



Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Нояб. 2009  
Откуда: Киев, Украина


Помог: 0 раз(а)




В общем суть в том, что есть класс Application и в нём есть свойство $view_folder, которое передаётся потомку только если оно static. А вот если я в родителе его объявлю просто как
protected $view_folder, то его видимость пропадает как в потомке, так и в вызове функции render() родителя(хотя казалось бы, функция класса родителя и там это свойство само по себе должно быть видимо). Но оно становится NULL. При этом после окончания создания класса потомка и вызова его функции это свойство опять становится видимым Однако
К методу родителя спокойно обращаюсь.

Как только объявил его как static, то всё заработало.
Почему так? Не могу понять. Извиняюсь за сумбурность объяснения, но вот так оно у меня в голове сейчас.
Ниже привожу код класса родителя Application и класса потомка Profile.

Application.php
PHP:
скопировать код в буфер обмена
  1.  
  2. class Application
  3. {
  4.     public $controller;
  5.     public $action;
  6.     static protected $view_folder;
  7.  
  8.     public function start()
  9.     {
  10.         $uri = self::getRoute();
  11.         $router = new Router($uri);
  12.         $router->registerClass(array($this, 'autoload'));
  13.  
  14.         $this->construct($router);
  15.  
  16.         return true;
  17.     }
  18.    
  19.     private static function getRoute(){
  20.         return $_SERVER['REQUEST_URI'];
  21.     }
  22.  
  23.     private function construct($router)
  24.     {
  25.         if (!isset($router->routing['function'])) {
  26.             $router->routing['function'] = 'index';
  27.         }
  28.        
  29.         $class = $router->routing['class'];
  30.         $function = $router->routing['function'];
  31.         self::$view_folder = $class;
  32.         $controller = new $class($class);
  33.         $controller->$function();
  34.  
  35. /* ЗДЕСЬ СВОЙСТВО ОПЯТЬ ВИДИМОЕ, А В САМОМ КЛАССЕ - НЕТ(если оно не static) */
  36.  
  37.         return true;
  38.     }
  39.    
  40.  
  41. /* ЭТА ФУНКЦИЯ ВЫЗЫВАЕТСЯ ИЗ ПОТОМКА И СВОЙСТВО ЗДЕСЬ НЕ ВИДНО(если оно не static) */
  42.     protected function render($view, $params = null)
  43.     {
  44.         echo "<br>Called from child class<br>";
  45.         echo self::$view_folder . "<br>";
  46.         echo $view;
  47.         var_dump($params);
  48.     }
  49.  
  50. }
  51.  


Profile.php
PHP:
скопировать код в буфер обмена
  1.  
  2. <?PHP
  3.  
  4. class Profile extends Application {
  5.  
  6.     public function index()
  7.     {
  8.         echo "Index action in profile controller <br>";
  9.         echo parent::$view_folders;
  10.  
  11. /* ВЫЗОВ МЕТОДА ИЗ РОДИТЕЛЯ, ГДЕ Я ХОЧУ ИМЕТЬ ВИДИМЫМ СВОЙСТВО $view_folder, НО ПОЧЕМУ ТОЛЬКО STATIC ? */
  12.         $this->render('index', [
  13.             "param1" => "first",
  14.             "param2" => "second",
  15.         ]);
  16.     }
  17.    
  18. }
  19.  


Спасибо всем, кто дочитал Улыбка
 
 Top
andrewkard
Отправлено: 09 Октября, 2017 - 09:23:51
Post Id


Участник


Покинул форум
Сообщений всего: 1372
Дата рег-ции: Нояб. 2014  


Помог: 30 раз(а)




А Вы уверены что при вызове метода рендер вызовется метод start() родителя?
логичнее было бы в конструкторе его вызвать, правда не видно всей архитектуры

PHP:
скопировать код в буфер обмена
  1.  
  2. class Application{
  3.  
  4. __construct(){
  5. $this->start();
  6. }
  7. }
  8.  


или перенести начинку start() в конструктор
 
 Top
Neonion
Отправлено: 09 Октября, 2017 - 14:20:44
Post Id



Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Нояб. 2009  
Откуда: Киев, Украина


Помог: 0 раз(а)




А зачем мне метод start() на этапе компиляции? Profile - это такой себе контроллер, который вызывает метод render из родителя Application и с помощью этого метода рендерит страничку(сам метод и класс Render я еще не написал, но суть пока не в этом).

Для понимания всей архитектуры приведу её полный пример здесь.
Она простая как газета Правда Улыбка

Index.php
PHP:
скопировать код в буфер обмена
  1.  
  2. <?
  3. /* Подключаем нужные либы для старта и запускаем Aplication через метод start().
  4. Я первый раз подобное пишу, возможно лучше было бы и конструктор просто сделать.
  5. */
  6. require_once (__DIR__ . '/base/Application.php');
  7. require_once (__DIR__ . '/base/Router.php');
  8.  
  9. $app = new Application();
  10. $app->start();
  11.  


Далее Application.php вычисляет куда мы обратились и передаёт строку в Router.
Хрен его знает как правильно, но написал как смог) Думаю потом у меня будет лучше получаться.

Router.php

PHP:
скопировать код в буфер обмена
  1.  
  2. class Router {
  3.  
  4.     public $routing = [
  5.         "class" => '',
  6.         "function" => '',
  7.     ];
  8.  
  9.     public function __construct($uri)
  10.     {
  11.         $uri = explode('/', $uri);
  12.         array_shift($uri);
  13.         $uri_elements = count($uri);
  14.  
  15.         for ($i = $uri_elements; $i != 0; $i--) {
  16.             if (!isset($uri[$i]) || empty($uri[$i])) {
  17.                 unset($uri[$i]);
  18.             }
  19.         }
  20.  
  21.         $this->mapper($uri);
  22.         $this->registerClass();
  23.     }
  24.  
  25.     protected function mapper($uri)
  26.     {
  27.         $uri_count = count($uri);
  28.  
  29.         if ($uri_count == 1) {
  30.             $this->routing = [
  31.                 "class" => ucfirst($uri[0]),
  32.             ];
  33.  
  34.         } elseif ($uri_count == 2) {
  35.             $this->routing = [
  36.                 "class" => ucfirst($uri[0]),
  37.                 "function" => $uri[1],
  38.             ];
  39.         }
  40.  
  41.         return true;
  42.     }
  43.  
  44.     public function registerClass()
  45.     {
  46.         spl_autoload_register(array($this, 'autoload'));
  47.     }
  48.  
  49.     public function autoload()
  50.     {
  51.         $path = realpath(dirname(__FILE__).'/../') . '/controllers/' . $this->routing['class'] . '.php';
  52.  
  53.         if (require_once $path) {
  54.             return true;
  55.         } else {
  56.             return false;
  57.         }
  58.  
  59.     }
  60.  
  61. }
  62.  


Роутер же возвращает controller и action к которым следует далее обратиться.
И вот к примеру обращаясь к engine.com/profile/index мы получим controller "profile" и action "index". В котроллере происходят определенные действия и в итоге надо сделать рендер всего этого дела.

Profile.php

PHP:
скопировать код в буфер обмена
  1.  
  2. class Profile extends Application {
  3.  
  4.  
  5.  
  6.     public function index()
  7.     {
  8.         $model = "first";
  9.         $form  = "second";
  10.  
  11.         $this->render('index', [
  12.             "param1" => $model,
  13.             "param2" => $form,
  14.         ]);
  15.     }
  16.  
  17.     public function settings()
  18.     {
  19.         $model = "first";
  20.         $form  = "second";
  21.  
  22.         $this->render('settings', [
  23.             "param1" => $model,
  24.             "param2" => $form,
  25.         ]);
  26.     }
  27.  
  28. }
  29.  


Т.е. зная что контроллер у нас profile, то и вьюху будем искать в папке views/profile. Достаточно распространённый подход, как например в фреймворке Yii.

Так вот, я не могу понять, почему в Application.php если я использую свойство $view_folder не статически, то видимость его ограничена методом start()? Т.е. если оно не статическое, то я не могу написать в контроллере Profle $this->view_folder и получить результат. И в методе render(), который описан в классе Application(а вызывается из контроллера) я тоже не могу получить значение - $this->view_folder выдаёт NULL.

Структура папок в приложении имеет такой вид:


Пишу весь этот велосипед исключительно для себя и чтобы понять как работает та или иная фича.
Спасибо за помощь)

(Отредактировано автором: 09 Октября, 2017 - 14:23:17)

 
 Top
andrewkard
Отправлено: 09 Октября, 2017 - 14:37:08
Post Id


Участник


Покинул форум
Сообщений всего: 1372
Дата рег-ции: Нояб. 2014  


Помог: 30 раз(а)




PHP:
скопировать код в буфер обмена
  1.  
  2. $controller = new $class($class);
  3.  

Вы создаете новые экземпляр потомка и его родителя, по этому Вам нужно сделать
PHP:
скопировать код в буфер обмена
  1.  
  2. $controller->start();
  3. $controller->$function();
  4.  

либо перенести содержимое старт в конструктор класса,
поправьте если не прав.
 
 Top
Neonion
Отправлено: 09 Октября, 2017 - 14:40:23
Post Id



Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Нояб. 2009  
Откуда: Киев, Украина


Помог: 0 раз(а)




А, т.е. когда я создаю класс контроллера Profile который наследует Application, то я одновременно создаю и новый экземпляр класса Application?
 
 Top
andrewkard
Отправлено: 09 Октября, 2017 - 14:55:05
Post Id


Участник


Покинул форум
Сообщений всего: 1372
Дата рег-ции: Нояб. 2014  


Помог: 30 раз(а)




Neonion пишет:
то я одновременно создаю и новый экземпляр класса Application?

все же не совсем так, что там на самом деле происходит в памяти, нужно копать,
по крайней мере в память грузятся публичные или защищенные свойства и методы родителей, поскольку к ним имеем доступ.
И в данном случае похоже что свойство view == NULL
 
 Top
Neonion
Отправлено: 09 Октября, 2017 - 14:58:19
Post Id



Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Нояб. 2009  
Откуда: Киев, Украина


Помог: 0 раз(а)




Ну да, вот собственно и ответ похоже) Спасибо)

А как сам код выглядит, похоже на говнокодище или вполне сносно?))
 
 Top
andrewkard
Отправлено: 09 Октября, 2017 - 15:07:33
Post Id


Участник


Покинул форум
Сообщений всего: 1372
Дата рег-ции: Нояб. 2014  


Помог: 30 раз(а)




Neonion пишет:
А как сам код выглядит, похоже на говнокодище или вполне сносно?))

смущает только что класс Profile наследуется от Application, а не от какого то общего контроллера для контроллеров действия
 
 Top
Neonion
Отправлено: 09 Октября, 2017 - 15:15:23
Post Id



Новичок


Покинул форум
Сообщений всего: 5
Дата рег-ции: Нояб. 2009  
Откуда: Киев, Украина


Помог: 0 раз(а)




Ок, понял. Подумаю еще раз над архитектурой...
Еще раз спасибо!
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Объектно-ориентированное программирование »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB