AntiSlaed CMS
Вход
Логин: Пароль:Забыли пароль?
Запомнить вас на этом компьютере?
Войти скрытым?

Здравствуйте, Гость ( Вход | Регистрация )

> Внимание!

Адрес нашего форума изменился, теперь мы доступны по адресу antislaed.net. Обновите ссылки и закладки, он больше не изменится.


 
Ответить в данную темуНачать новую тему
> Взаимодействие классов в PHP, Вызванный класс обращается к вызывающему
wizard993
сообщение May 11 2011, 16:41
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
Sunvas
сообщение May 11 2011, 20:26
Сообщение #2


Фэнат Stamina-ы
Иконка группы

Группа: Разработчики
Сообщений: 2,470
Регистрация:
6.7.2007
Из: (-: Украина :-)
Пользователь №: 268
Спасибо сказали: 992

Вставить ник




Переменная $Primary не инициализирована. И не содержит в себе объект класса Primary. Необходимо создать объект:

$Primary=new Primary;
Sunvas, Вас 1 раз(а) поблагодарили за это сообщение:
wizard993
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
wizard993
сообщение May 11 2011, 21:11
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
vitalik1972
сообщение May 11 2011, 22:44
Сообщение #4


Живу на АС
Иконка группы

Группа: Пользователи

Сообщений: 765
Регистрация:
10.6.2008
Из: Оренбург
Пользователь №: 4,176
Спасибо сказали: 211

Вставить ник




в этом случае класс Primary надо делать статическим.
и обращаться в нему через его статические методы. А так, как описано у тебя просто происходит переполнение памяти, так как первый класс вызывает конструктор второго а второй опять конструирует объект первого и опять и опять все повторяется.
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение:
wizard993
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
wizard993
сообщение May 11 2011, 22:59
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
vitalik1972
сообщение May 12 2011, 08:15
Сообщение #6


Живу на АС
Иконка группы

Группа: Пользователи

Сообщений: 765
Регистрация:
10.6.2008
Из: Оренбург
Пользователь №: 4,176
Спасибо сказали: 211

Вставить ник




ЦИТАТА
$this->Primary = Primary::Primary();


Это не надо писать. К статическому классу можно обращаться по его имени из любого места.

Либо как вариант, пусть все твои классы происходят от одного класса родителя, в котором есть определение нужного тебе статического класса.

Сообщение отредактировал vitalik1972: May 12 2011, 08:17
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение:
wizard993
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
wizard993
сообщение May 12 2011, 08:28
Сообщение #7


Продвинутый юзверь
Иконка группы

Группа: Пользователи

Сообщений: 68
Регистрация:
29.1.2008
Из: Кубинка-8
Пользователь №: 2,152
Спасибо сказали: 10

Вставить ник




ЦИТАТА(vitalik1972 @ May 12 2011, 08:15 ) *
Это не надо писать. К статическому классу можно обращаться по его имени из любого места.


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();

ЦИТАТА(vitalik1972 @ May 12 2011, 08:15 ) *
Либо как вариант, пусть все твои классы происходят от одного класса родителя, в котором есть определение нужного тебе статического класса.


То есть, Вы имеете ввиду, что допустим, класс Primary родительский, а остальные наследуются от него?
КОД
class Secondary extends Primary
{
  //...
}


Прикрепил файлы.

Сообщение отредактировал wizard993: May 12 2011, 09:21
Прикрепленные файлы
Прикрепленный файл  class_primary.php ( 428 б ) Кол-во загрузок: 0
Прикрепленный файл  class_secondary.php ( 209 б ) Кол-во загрузок: 0
Прикрепленный файл  class_third.php ( 262 б ) Кол-во загрузок: 0
Прикрепленный файл  index.php ( 154 б ) Кол-во загрузок: 0
 
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
vitalik1972
сообщение May 12 2011, 20:56
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
wizard993
сообщение May 12 2011, 21:30
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
vitalik1972
сообщение May 13 2011, 07:32
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
wizard993
сообщение May 13 2011, 07:52
Сообщение #11


Продвинутый юзверь
Иконка группы

Группа: Пользователи

Сообщений: 68
Регистрация:
29.1.2008
Из: Кубинка-8
Пользователь №: 2,152
Спасибо сказали: 10

Вставить ник




ЦИТАТА
Статический - это говорит о том, что в памяти в процессе исполнения может быть всего лишь 1 объект данного класса.
Надеюсь, что прояснил ситуацию

Да, прояснил. А то про static довольно мало в книгах написано.

Из литературы читал, что когда свойство или метод помечают ключевым словом static, то можно к ним обращаться без создания объекта класса и с помощью оператора :: . Ещё, знаю, что для всех объектов класса, статические свойства и методы являются общими. (То есть, если изменяются в одном объекте, то изменяются и в другом объекте). А есть ещё какие-нибудь принципиальные различия между статическими членами и обычными? И какие "+" и "-" есть в использовании?
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
vitalik1972
сообщение May 13 2011, 11:39
Сообщение #12


Живу на АС
Иконка группы

Группа: Пользователи

Сообщений: 765
Регистрация:
10.6.2008
Из: Оренбург
Пользователь №: 4,176
Спасибо сказали: 211

Вставить ник




Ну вот например смотри:
Ты создаешь какое-либо приложение. Класс приложения будет всего один, так почему бы его не сделать статическим?
а вот классов блоков может быть несколько, соответственно они и должны быть динамическими.
То же самое касается модулей и прочего.
Тем более, что и обращение к статическому классу очень удобное через ::

Например пишешь какой либо модуль или блок и вызываешь класс приложения через CApp::
Мне кажется что так очень наглядно все происходит, код легкий получается, опять таки из кода хорошо видно, что вызываются "стандартные" методы приложения.
vitalik1972, Вас 1 раз(а) поблагодарили за это сообщение:
wizard993
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
wizard993
сообщение May 13 2011, 21:10
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
wizard993
сообщение May 16 2011, 20:38
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
vitalik1972
сообщение May 16 2011, 22: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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
wizard993
сообщение May 16 2011, 22:49
Сообщение #16


Продвинутый юзверь
Иконка группы

Группа: Пользователи

Сообщений: 68
Регистрация:
29.1.2008
Из: Кубинка-8
Пользователь №: 2,152
Спасибо сказали: 10

Вставить ник




vitalik1972 так вот этого я и не пойму...
ты же сам пишешь
ЦИТАТА
А после создания статического класса ты и обращаешься к нему через ::

А у него через стрелочки...

Сообщение отредактировал wizard993: May 16 2011, 22:49
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение
patriot
сообщение May 22 2011, 17:35
Сообщение #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
Перейти в начало страницы
 
     Выделите текст перед нажатием цитаты
+Цитировать сообщение

Ответить в данную темуНачать новую тему

2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
 

RSS Текстовая версия Сейчас: 17 May 2024 - 07:39
Хостинг предоставлен NetLevel.Ru   Eleanor CMS