![]() |
![]() |
ВходЗдравствуйте, Гость ( Вход | Регистрация )
|
![]() |
![]() ![]()
Сообщение
#1
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
Допустим у меня есть первый класс:
КОД <?php class Primary { public $var='какая-то переменная'; public function __construct() { $db=array(тут данные для соединения с БД); $this->Secondary = new Secondary; $this->Secondary->Load($this->var); $this->Third = new Third; $this->Third->Method1($db); } } ?> Также есть второй класс: КОД <?php class Secondary { public function Load($var) { $dbname ='чему-то равно'; $var2 = $Primary->Third->Method2($dbname); } } ?> И Ещё есть третий класс: КОД <?php class Third { public function Method1() { $this->mysqli = new mysqli($db['host'], $db['user'], $db['password'], $db['name']); } public function Method2($dbname) { return $this->mysqli->select_db($dbname); } } ?> Каждый класс расположен в отдельном файле. Пишет ошибку, Fatal error: Call to a member function Method2() on a non-object in [...тут путь... к файлу, содержащему Secondary Class ]. Конкретно PHP не понравилась строка $var2 = $Primary->Third->Method2($dbname); в Secondary... У меня есть предчувствие, что вызываемый класс не может просто так обращаться к вызывающему его классу. Подскажите, пожалуйста, почему так происходит, в чём моя ошибка и как можно решить данную проблему. Сообщение отредактировал wizard993: May 11 2011, 21:17 |
|
|
![]() |
![]()
Сообщение
#2
|
|
Фэнат Stamina-ы ![]() Группа: Разработчики Сообщений: 2,470 Регистрация: 6.7.2007 Из: (-: Украина :-) Пользователь №: 268 Спасибо сказали: 992 Вставить ник ![]() |
Переменная $Primary не инициализирована. И не содержит в себе объект класса Primary. Необходимо создать объект:
$Primary=new Primary; |
Sunvas, Вас 1 раз(а) поблагодарили за это сообщение: wizard993 | |
|
|
![]()
Сообщение
#3
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
Sunvas, спасибо, что ответили.
Создал файл index.php КОД <?php require_once 'class_primary.php'; $Primary = new Primary; ?> В class_primary.php прописал автолоад остальных двух классов (secondary и third). Проблема всё та же... Если изменить код Secondary таким образом: КОД <?php class Secondary { public function Load($var) { $dbname ='чему-то равно'; $Primary = new Primary; $var2 = $Primary->Third->Method2($dbname); } } ?> или таким: КОД <?php class Secondary { public function Load($var) { $dbname ='чему-то равно'; $this->Primary = new Primary; $var2 = $this->Primary->Third->Method2($dbname); } } ?> То появляется другой разряд ошибок: Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 261904 bytes) in [и тут любой из предложенных классов на выбор] Ошибка выскакивает после 10-секундного зацикливания и думанья браузера. Цифры в ошибке всегда разные... И останавливается на произвольном участке кода. Сообщение отредактировал wizard993: May 11 2011, 21:18 |
|
|
![]()
Сообщение
#4
|
|
Живу на АС ![]() Группа: Пользователи Сообщений: 765 Регистрация: 10.6.2008 Из: Оренбург Пользователь №: 4,176 Спасибо сказали: 211 Вставить ник ![]() |
в этом случае класс Primary надо делать статическим.
и обращаться в нему через его статические методы. А так, как описано у тебя просто происходит переполнение памяти, так как первый класс вызывает конструктор второго а второй опять конструирует объект первого и опять и опять все повторяется. |
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение: wizard993 | |
|
|
![]()
Сообщение
#5
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
vitalik1972, спасибо, буду дальше думать...
Тогда ещё такой вопрос. Допустим, у меня много файлов с классами. Неужели необходимо в каждом прописывать что-то вроде $this->Primary = Primary::Primary(); Есть ли какое-нибудь решение такой ситуации? Если, что не так написал - простите, ещё только учусь (IMG:http://antislaed.net/style_emoticons/default/smile.gif) Сообщение отредактировал wizard993: May 11 2011, 23:09 |
|
|
![]()
Сообщение
#6
|
|
Живу на АС ![]() Группа: Пользователи Сообщений: 765 Регистрация: 10.6.2008 Из: Оренбург Пользователь №: 4,176 Спасибо сказали: 211 Вставить ник ![]() |
ЦИТАТА $this->Primary = Primary::Primary(); Это не надо писать. К статическому классу можно обращаться по его имени из любого места. Либо как вариант, пусть все твои классы происходят от одного класса родителя, в котором есть определение нужного тебе статического класса. Сообщение отредактировал vitalik1972: May 12 2011, 08:17 |
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение: wizard993 | |
|
|
![]()
Сообщение
#7
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
Это не надо писать. К статическому классу можно обращаться по его имени из любого места. vitalik1972, Немножко не понимаю. Из того, что я читал по PHP есть такие понятия, как статические члены класса и статические методы класса. К ним идёт обращение через оператор разрешения области видимости ( : : ) А как выглядит такое чудо, как статический класс? На php.net вроде не нашёл... Не могли бы показать на небольшом примере, что он из себя представляет и как к нему обращаться? P.S. пробежался по форумам. Я так понял статический класс - это класс, у которого все свойства и методы - статические? Поправьте, если не так. P.P.S тогда в связи с этим ещё вопрос. А можно ли в моём случае, не делать весь класс статическим, а создать какой-нибудь статический метод, который создаёт объект этого класса; и потом обращаться из других классов к нему посредством оператора разрешения области видимости. Вот ниже код того, что я хочу сказать (IMG:http://antislaed.net/style_emoticons/default/smile.gif) КОД <?php class Primary { public $var='какая-то переменная'; public $static_var; public function __construct() { $db=array(тут данные для соединения с БД); $this->Secondary = new Secondary; $this->Secondary->Load($this->var); $this->Third = new Third; $this->Third->Method1($db); } public static function static_method() { self::$static_var=new self(); return self::$static_var; } } ?> Обращаться к нему так: КОД <?php class Secondary { public function Load($var) { $dbname ='чему-то равно'; $this->Primary = Primary::static_method(); $var2 = $Primary->Third->Method2($dbname); } } ?> И изменил index.php следующим образом КОД <?php require_once 'class_primary.php'; require_once 'class_secondary.php'; require_once 'class_third.php'; $Primary = Primary::static_method(); ?> Ошибка та же, связана с памятью. И всё равно приходится в каждом классе, подключаемом из автолоада прописывать $this->Primary = Primary::static_method(); Либо как вариант, пусть все твои классы происходят от одного класса родителя, в котором есть определение нужного тебе статического класса. То есть, Вы имеете ввиду, что допустим, класс Primary родительский, а остальные наследуются от него? КОД class Secondary extends Primary { //... } Прикрепил файлы. Сообщение отредактировал wizard993: May 12 2011, 09:21
Прикрепленные файлы
![]() ![]() ![]() ![]() |
|
|
![]()
Сообщение
#8
|
|
Живу на АС ![]() Группа: Пользователи Сообщений: 765 Регистрация: 10.6.2008 Из: Оренбург Пользователь №: 4,176 Спасибо сказали: 211 Вставить ник ![]() |
ЦИТАТА То есть, Вы имеете ввиду, что допустим, класс Primary родительский, а остальные наследуются от него? Нет. Давай я лучше на примере KiVi CMS покажу как реализован статический класс и происходит обращение к нему: Итак, существует статический класс CApp (от слов Класс Приложение) сам он происходит от статического класса CBaseApp (зачем сделано так, здесь обсуждать не будем) Код файла index.php в корне сайта: КОД <?php define ( "MODULE_FILE", true ); require_once 'function/CApp.php'; CApp::init()->run(); ?> и теперь функция init в файле CApp.php КОД public static function init() { self::$app = new CApp (); return self::$app; } Все методы этого класса статические, поэтому все обращения к вызову класса приложения происходят через :: То есть, чтобы вызвать какую либо функцию данного класса или переменную обращаемся так: (например запрос к БД) $res = CApp::$db->sql_query("тут код запроса"); Скачай с оффсайта киви последний релиз и покопайся в коде, я уверен, что ты легко в нем разберешься. А проблемы с памятью потому, что как только ты делаешь new у тебя вызывается конструктор этого класса, который порождает второй и третий классы, которые порождают первый и так далее. Вот именно поэтому я использую функцию init для инициализации класса и вызываю этот метод сего 1 раз. Сообщение отредактировал vitalik1972: May 12 2011, 21:03 |
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение: wizard993 | |
|
|
![]()
Сообщение
#9
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
Ну KiVi скачал, ещё на выходных начал по-тихоньку разбираться. Заодно ещё рядом релиз AS 4.3.1 от Next и Eleanor CMS.
Я вообще почему задал этот вопрос. Скачал Элеанор, стал смотреть код... там в index.php следующие строки КОД require dirname(__file__).'/classes/mainclass.php'; $Mainclass=MainClass::getInstance(); То есть индекс обращается к статическому методу getInstance() класса Mainclass !!! НО если открыть файл classes\mainclass.php , то в структуре самого класса Mainclass можно увидеть не только статические методы, например, public function LoadService(). То есть класс Mainclass не является статическим, если я правильно понимаю... Далее, частично рассмотрим статическую функцию getInstance() КОД private static $Instance; public static function getInstance($init_other_classes=true,$classes=array()) { if(!isset(self::$Instance)) { static $process=false; if($process) return false; $process=true; self::$Instance=new self($init_other_classes,$classes); } return self::$Instance; } Если я опять же правильно понял, функция возвращает объект класса Mainclass, в том случае, если он не был создан. Обращение конкретно такого вида: $Mainclass=Mainclass::getInstance(); я заметил только в index.php. В других файлах иногда встречаются конструкции вида Mainclass::$Instance->name_of_some_object_or_method, но опять же не везде. Встречаются файлы, где какого-либо видимого создания объекта класса Mainclass вообще нету. То есть идут несколько строчек кода, никак не относящиеся к Mainclass, а потом сразу без "привета" идёт строка что-то вроде return $this->Mainclass->SCookie($c_name,$value); Вот мне и интересно как добиться такой реализации... vitalik1972, огромное спасибо за помощь и ответы, продолжаю думать (IMG:http://antislaed.net/style_emoticons/default/smile.gif) KiVi тоже параллельно разбираю. Сообщение отредактировал wizard993: May 12 2011, 23:06 |
|
|
![]()
Сообщение
#10
|
|
Живу на АС ![]() Группа: Пользователи Сообщений: 765 Регистрация: 10.6.2008 Из: Оренбург Пользователь №: 4,176 Спасибо сказали: 211 Вставить ник ![]() |
В элеаноре getInstace в киви Init, разницы никакой нет.
В элеаноре есть проверка на "дурака", то есть на повторный вызов КОД if(!isset(self::$Instance)) в киви ее нет, посчитал ненужной, да собственно так и продолжаю думать. Объясни смысл не полностью статического класса? В любом случае это объект, а статическая функция или нет я например не вижу разницы в данном контексте. Может быть санвас пояснит свой код? Давай подождем его комментариев... ЦИТАТА Встречаются файлы, где какого-либо видимого создания объекта класса Mainclass вообще нету. Я наконец-то понял, что ты имеешь в виду (IMG:http://antislaed.net/style_emoticons/default/smile.gif) Вобщем я могу сказать тебе так: если есть хотя бы одна статическая функция или переменная в классе - то он будет статическим. Статический - это говорит о том, что в памяти в процессе исполнения может быть всего лишь 1 объект данного класса. Надеюсь, что прояснил ситуацию Сообщение отредактировал vitalik1972: May 13 2011, 07:36 |
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение: wizard993 | |
|
|
![]()
Сообщение
#11
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
ЦИТАТА Статический - это говорит о том, что в памяти в процессе исполнения может быть всего лишь 1 объект данного класса. Надеюсь, что прояснил ситуацию Да, прояснил. А то про static довольно мало в книгах написано. Из литературы читал, что когда свойство или метод помечают ключевым словом static, то можно к ним обращаться без создания объекта класса и с помощью оператора :: . Ещё, знаю, что для всех объектов класса, статические свойства и методы являются общими. (То есть, если изменяются в одном объекте, то изменяются и в другом объекте). А есть ещё какие-нибудь принципиальные различия между статическими членами и обычными? И какие "+" и "-" есть в использовании? |
|
|
![]()
Сообщение
#12
|
|
Живу на АС ![]() Группа: Пользователи Сообщений: 765 Регистрация: 10.6.2008 Из: Оренбург Пользователь №: 4,176 Спасибо сказали: 211 Вставить ник ![]() |
Ну вот например смотри:
Ты создаешь какое-либо приложение. Класс приложения будет всего один, так почему бы его не сделать статическим? а вот классов блоков может быть несколько, соответственно они и должны быть динамическими. То же самое касается модулей и прочего. Тем более, что и обращение к статическому классу очень удобное через :: Например пишешь какой либо модуль или блок и вызываешь класс приложения через CApp:: Мне кажется что так очень наглядно все происходит, код легкий получается, опять таки из кода хорошо видно, что вызываются "стандартные" методы приложения. |
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение: wizard993 | |
|
|
![]()
Сообщение
#13
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
vitalik1972 Ещё раз спасибо за помощь (IMG:http://antislaed.net/style_emoticons/default/smile.gif) Попробовал сам написать - получилось, всё пашет.
Сообщение отредактировал wizard993: May 13 2011, 23:50 |
|
|
![]()
Сообщение
#14
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
Ну статика, это конечно хорошо...
но меня всё равно гложет мысль о том, как же Sunvas реализовал это чудо в Элеаноре. Возьмём начало файла classes\class_cache.php из Eleanor CMS (можно взять любой другой класс - это не важно) КОД class Cache extends BaseClass { public $langvars=array(), $Lib; public function Init() { $unique='elca_'; if(function_exists('apc_store') and file_exists($this->Mainclass->root_path.'classes/cache/class_cachemachine_apc.php')) $this->Mainclass->root_path.'classes/cache/class_cachemachine_apc.php' Вот что я не могу понять. Объект класса Mainclass не создаётся. Следовательно обращение к переменной root_path должно осуществляться через оператор :: Но, оно почему-то осуществляется так, КАК БУДТО СОЗДАН объект с именем Mainclass класса Mainclass. Где искать разгадку? Мне интуиция говорит, что рыть надо где-то в mainclass.php. Но, к сожалению, сколько не пытался, ничего похожего на реализацию этого чуда не нашёл. Народ, пожалуйста, объясните, каким образом так происходит? За счёт какой функции или чего-нибудь ещё? Сообщение отредактировал wizard993: May 16 2011, 20:38 |
|
|
![]()
Сообщение
#15
|
|
Живу на АС ![]() Группа: Пользователи Сообщений: 765 Регистрация: 10.6.2008 Из: Оренбург Пользователь №: 4,176 Спасибо сказали: 211 Вставить ник ![]() |
ЦИТАТА там в index.php следующие строки КОД require dirname(__file__).'/classes/mainclass.php'; $Mainclass=MainClass::getInstance(); ЦИТАТА private static $Instance; public static function getInstance($init_other_classes=true,$classes=array()) { if(!isset(self::$Instance)) { static $process=false; if($process) return false; $process=true; self::$Instance=new self($init_other_classes,$classes); } return self::$Instance; } а это что по твоему? вот создание самого себя (статического класса) self::$Instance=new self($init_other_classes,$classes); А после создания статического класса ты и обращаешься к нему через :: |
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение: wizard993 | |
|
|
![]()
Сообщение
#16
|
|
Продвинутый юзверь ![]() Группа: Пользователи Сообщений: 68 Регистрация: 29.1.2008 Из: Кубинка-8 Пользователь №: 2,152 Спасибо сказали: 10 Вставить ник ![]() |
vitalik1972 так вот этого я и не пойму...
ты же сам пишешь ЦИТАТА А после создания статического класса ты и обращаешься к нему через :: А у него через стрелочки... Сообщение отредактировал wizard993: May 16 2011, 22:49 |
|
|
![]()
Сообщение
#17
|
|
Я уже люблю АС ![]() Группа: Пользователи Сообщений: 196 Регистрация: 5.8.2008 Пользователь №: 4,945 Спасибо сказали: 39 Вставить ник ![]() |
Класс MainClass реализует шаблон проектирования Singleton (всегда создается не более одного объекта этого класса)
КОД $Mainclass = MainClass::getInstance(); возвращает объект класса (всегда один и тот же) - к нему можно обращаться как к любому другому объекту (->) статические методы по прежнему доступны через :: статические методы не наследуются, но их можно переопределить. вместо этого кода можно было бы использовать КОД $Mainclass = new MainClass(); но тогда нет гарантии, что не появится еще один объект ГлавныйКласс )) ЦИТАТА Вот что я не могу понять. Объект класса Mainclass не создаётся. Следовательно обращение к переменной root_path должно осуществляться через оператор :: Но, оно почему-то осуществляется так, КАК БУДТО СОЗДАН объект с именем Mainclass класса Mainclass. Этот объект может создаваться в родительском классе и использоваться в дочернем. Сообщение отредактировал patriot: May 22 2011, 17:40 |
patriot, Вас 1 раз(а) поблагодарили за это сообщение: wizard993 | |
|
|
![]() ![]() |
![]() |
Текстовая версия | Сейчас: 25 April 2025 - 19:49 |