Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > call to a member function XX on a non-object in...


Автор: SergV 21.8.2014, 16:54
Делаю шаблон для сайта, решил его сделать на отдельных макетах и блоках, так как сложный, и запнулся с ошибкой.

Ситуация следующая, имеется файл индексный, в котором в самом начале подключаю файл с настройками, а в нём подключаю файл с классом, и этот клас инициализирую в файле настроек.

Дальше всё просто, в индексном файле вызываю функцию подключение макета - $tpl->loadLayout('xxx'), и в подключенном макете вызываю функцию подключения блока(в) - $tpl->loadBlock('xxx'). Так вот, в индексном файле всё норм, вызываются функции без проблем, а в подключенном файле макета функция выдаёт ошибку, но при статическом вызове TPL::$tpl->loadBlock('xxx'), всё работает нормально.

Пытался разобраться сам, но чего то не пойму, почему не передаётся объект в другой файл, который подключил... 
Я уже давно с пыхом не работал, а с классами и вообще подавно, и нагуглить чёт не вышло, английского не знаю, а на русском всё не по теме. Мож кто подскажет где проблема, чего не так делаю?

ПС. Пых 5.4, локальный сервер OpenServer. Класс стандартный, с "парой" публичных функций, думаю смысла нет приводить, так как там не чего особо нет, кроме пары строк в каждой, да и всё работает в общем то, кроме файла макета...

Автор: baldina 21.8.2014, 17:06
очевидно, что файл с классом подключился, а переменная-объект в нужном месте в нужное время отсутствует.
без исходников о деталях можно только гадать

Добавлено через 1 минуту и 26 секунд
Цитата(SergV @  21.8.2014,  16:54 Найти цитируемый пост)
в индексном файле вызываю функцию подключение макета - $tpl->loadLayout('xxx')

а $tpl где родится? а в подключенном файле макета она доступна?

Автор: SergV 21.8.2014, 17:23
Имеется основной файл index.php шаблона...
Код

<?php defined('_JEXEC') or die;  
include_once (file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'incl' . DIRECTORY_SEPARATOR . 'config.php')) 
    ? __DIR__ .DIRECTORY_SEPARATOR .'incl' . DIRECTORY_SEPARATOR . 'config.php' 
    : trigger_error('Import not found object: ', E_USER_ERROR);
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->language; ?>" lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>" >
...
</head>
<body>
...
<?php $tpl->loadLayout('default'); ?>
...
</body>

В нём инклюдится файл настроек, в котором константы и т.д., и инклюд класса.
Код

<?php defined('_JEXEC') or die('Restricted access');

class TPL
{
...
public function loadLayout($layout = false, $view = false) {
...  Обработка входящих данных    
include JPATH_THEMES.DS.TPL.DS.'layouts'.DS.$layout.'.php';
}

public function loadBlock($block = false, $layout = false) {
... Обработка входящих данных        
include JPATH_THEMES.DS.TPL.DS.'layouts'.DS.'blocks'.DS.$block.'.php';
}

Там же в config.php и инициализация класса - $tpl = new TPL;

Вызов идёт из index.php - $tpl->loadLayout('layout-name')
В "layout-name" хтмл вёрстка и вызов блока - $tpl->loadBlock('block-name'), где оствшаяся хтмл вёрстка. Вот тут и выходит ошибка вызова функции, но если вызывать как TPL::$tpl->loadBlock('xxx'), то всё норм.

Суть в том, что до переноса в класс, в config.php были просто две функции, и они вызывались без проблем, а в классе такая вот байда вышла... :(

Автор: baldina 21.8.2014, 17:46
Цитата(SergV @  21.8.2014,  17:23 Найти цитируемый пост)
public function loadLayout($layout = false, $view = false) {
...  Обработка входящих данных    
include JPATH_THEMES.DS.TPL.DS.'layouts'.DS.$layout.'.php';
}

$tpl недоступен отсюда. его надо передать в параметрах или, если он глобальный, 

Код

public function loadLayout($layout = false, $view = false) {
global $tpl;
include JPATH_THEMES.DS.TPL.DS.'layouts'.DS.$layout.'.php';
}


Добавлено через 38 секунд
однако он будет доступен и так, только не через $tpl а через $this

Добавлено через 10 минут и 33 секунды
т.е.
Код

$this->loadBlock('xxx');

Автор: SergV 21.8.2014, 18:02
Спасибо, чёт ступил, не попробовал через $this вызывать, думал не прокатит, тепрь работает.   smile 

А попутный вопрос, можно как то так через $tpl делать, но не использовать global $tpl, так как вроде по старой памяти, глобалки не советуют из за проблем с защищённостью или чего там ещё?

ПС. Интересно вообще, как функция в $this попала, если я класс инитиализировал как $tpl..., и не где не переопределял, и клас не наследуется не от какого другого.  smile  smile 

ПС2. Приколы, $this работает только для вызова из файла блоков в макете, а в индексном файле выдаёт туже ошибку.  Мда..., хочется вызывать одинаково, а то там одно, тут другое.

Автор: baldina 21.8.2014, 19:02
SergV
Цитата(SergV @  21.8.2014,  18:02 Найти цитируемый пост)
можно как то так через $tpl делать, но не использовать global $tpl

передать в качестве параметра.
но... не надо через $tpl, логика следующая:
контроллер создает $tpl - экземпляр TPL и работает с ним. $tpl - шаблон с исполняемым кодом, то есть view.
код в partial temlates, подключаемых через loadLayout() и loadBlock() - суть часть кода view, поэтому ему логично обращаться к объекту шаблона (типа TPL), а значит view, как к себе, через $this

Добавлено через 2 минуты и 22 секунды
Цитата(SergV @  21.8.2014,  18:02 Найти цитируемый пост)
$this работает только для вызова из файла блоков в макете, а в индексном файле выдаёт туже ошибку

ну естественно. блоки становятся частью кода функции-члена, а индексный файл - внешняя создающая и вызывающая среда.
индексный файл - controller, блоки - часть view. view целиком представлен в индексном файле как $tpl

Автор: ksnk 22.8.2014, 07:32
Если я правильно понял, TPL - классический синглтон класс. Нужно и работать с ним как с синглтоном.

Код

class TPL{
    private static $instance;  // экземпляра объекта
    private function __construct(){ /* ... @return Singleton */ }  // Защищаем от создания через new Singleton
    private function __clone()    { /* ... @return Singleton */ }  // Защищаем от создания через клонирование
    private function __wakeup()   { /* ... @return Singleton */ }  // Защищаем от создания через unserialize
    public static function getTpl() {    // Возвращает единственный экземпляр класса. @return Singleton
        if ( empty(self::$instance) ) {
            self::$instance = new self();
        }
        return self::$instance;
    }
 // то что было раньше  
 }
 


в нужных местах писать $tpl=TPL::getTpl() или TPL::getTpl()->do_something();

Автор: Aliance 22.8.2014, 07:57
ksnk, лучше наверное такой синглтон пометить как final, либо заменить self на static ;)

Автор: ksnk 22.8.2014, 09:21
Aliance, Если разработчики php будут и дальше толкать язык в сторону Java - то нет, на static заменять не стоит  smile final - да, для дополнительного лоска - можно добавить. 

Текст стырен откуда-то, вероятно с википедии, так что мопед не мой я на нем только катаюсь...   smile 

Автор: SergV 22.8.2014, 09:49
baldina, сказать честно, понял через слово, совсем уже забыл что к чему в пхп, занимаясь 3д дизайном. smile
Так или иначе, нашёл шаблон один, где подобная иеархия с подключением, правдо там всё идет через плагин(класс в плагине сидит), но в шаблоне везде вызов на подключение идёт как я писал... Попробую там подсмотреть что и как делается, и вытянуть что надо из плагина в шаблон.

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

В общем придётся пока делать обходным путём, вызывая блоки через $this, и постепенно разбираться с найденным шаблоном и его плагином... Не вышло по быстрому сделать нормально, думал тряхну стариной, раз раз и на матрац, а $тут-> smile  smile 

ПС. Глючит меня с утра, в найденом шаблоне точно так же, вызов макета через объявление класса и т.д., а подключение блоков через $this...

В общем вопрос снимается, всем спасибо за ответы.

Автор: baldina 22.8.2014, 09:54
Цитата(ksnk @  22.8.2014,  07:32 Найти цитируемый пост)
TPL - классический синглтон класс

синглтон - потенциально проблемное место для расширения. поэтому в отсутствие достаточных доводов TPL лучше синглотоном не считать

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)