Class redeclared даже при использовании include_once

God

Новичок
if (!class_exists('MainClass'))
include('mainclass.php'); - здесь class_exists вернёт false
include('yourclass.php'); - а вот здесь уже true
 

whirlwind

TDD infected, paranoid
>условие if (!class_exists('MainClass')) сработает только ОДИН раз и вернет false, какой смысл в этом условии?

А в этом и смысл, что класс, который внутри блока, будет объявлен только в том случае, если он еще до этого не был декларирован. Это более надежный аналог include_once, когда нас не обязывают использовать include_once и мы можем подключать один и тот же файл сколько нам угодно даже посредством include не получая при этом ошибок, связанных с попыткой переопределить уже объявленный класс.

>Я понимаю разницу.
>Если я верно уловил суть, God хочет создать ОДИН объект

Нет, он не хочет создать объект, он хочет объявить класс. Объект у нас создается посредством оператора new, а декларация класса выполняется посредством ключевого слова class. Так вот God хочет что бы class для определенного класса выполнялась только один раз, а не каждый раз при подключении файла.
 

CCCP_MOCKBA

Новичок
mainclass.php
PHP:
class MainClass
{
   ....
}
yuorclass.php
PHP:
require_once('mainclass.php');
class YourClass extends MainClass
{
   ....
}
file.php
PHP:
require_once('mainclass.php');
require_once('yourclass.php');
$obj1 = new YourClass();
$obj2 = new MainClass();
Для инклуда существуют функции require_once() и/или autoload() и ошибок "Class redeclared" не возникает
 

eugef

Новичок
Выдержка из справки по PHP 4.3:
Include и require идентичны во всём, кроме обработки облома. include() выводит Warning!, а require() выдаёт Fatal Error. Иначе говоря, используйте require(), если вы хотите, чтобы отсутствие файла останавливало процессинг страницы. include() не работает таким образом, скрипт продолжит выполнение.
Аналгично и для функций с суфиксом _once.

Перед include_once я делаю проверку на существование файла и выполняю include_once только если файл существовал. Поэтому при замене с include на require никаких изменений я не замечу? Или разница есть еще в чем-то?

Проблема в том, что ошибка "Class redeclared" происходит не всегда - загружая одну и ту же страницу она может раз на 10 выдать такую ошибку а может и нет, кто-нибудь с этим сталкивался?

Поэтому я буду действовать так:
1. Поверяю class_exists - объявлен класс или нет
2. Если объявлен - создаю экземпляр класса
3. Если класс не объявлен и файл с определнием класса существует - то делаю ему include_once и создаю экземпляр класса.

Повторю, что подключение всех класов у меня происходит всегда в одной функции.
 

McSimm

Новичок
Поэтому я буду действовать так:
Не хочу навязывать свое мнение, однако я до последнего искал бы причину ошибки. Тем более такой загадочной, люблю я загадки (когда не deadline конечно :) )

А версия PHP у вас какая? (не заметил если уже упоминалась)
 

God

Новичок
2. Если объявлен - создаю экземпляр класса
3. Если класс не объявлен и файл с определнием класса существует - то делаю ему include_once и создаю экземпляр класса.
Опять же затачиваешься под свою какую-то нынешнюю ситуацию. Предположи, что в будущем тебе придётся создавать несколько экземпляров класса, да ещё в разных подключаемых файлах. Вот тогда и пригодится защита использованием class_exists при объявлении класса.
Мда, если б чаще пользовали C, C++, то и тред бы не раздулся. Там всё это уже делается на автомате:
PHP:
#ifndef YorClassH
#define YorClassH
class YorClass
{
    ...
}
#endif
 

eugef

Новичок
McSimm
Не хочу навязывать свое мнение, однако я до последнего искал бы причину ошибки
Я бы тоже искал бы причину! Но заказчик поджимает со сроками - поэтому легче пока причину устранить, а потом на досуге, если время будет, то и отловить :) Вся беда в том что локально эта ошибка ниразу не появмлась!

Вот инфа о сервере на котором вылетает ошибка:
PHP:
PHP Version 4.4.2
FreeBSD 4.11-STABLE 
Apache/1.3.34
-~{}~ 18.04.06 11:06:

God
Мда, если б чаще пользовали C, C++, то и тред бы не раздулся. Там всё это уже делается на автомате
Сам я на С++ много писал но в PHP другой способ программирования, и нет в нем директив препроцессору - потому и существуют разные функции типа include_once - чтоб только раз файл подключать.

А вот почему он один и тот же файл 2 раза подключает - вот это уже загадка!
 

McSimm

Новичок
отлаживать надо. т.е. например, оставить include_once() поставить проверку на объявленый класс, но в секцию else{} добавить запись в лог.
для начала строку, передаваемую include_once(), массив get_included_files, realpath() от пути к файлу....

ситуация с добавлением виртуальных хостов наводит на подозрения о проблемах с символическими ссылками, но это гадание. PHP 4 нормально должен отслеживать их в include_once()
 

eugef

Новичок
McSimm
отлаживать надо
Ок, спасибо, воспользуюсь твоим алгоритмом!

ситуация с добавлением виртуальных хостов наводит на подозрения о проблемах с символическими ссылками
Да я тоже так подразумеваю что в этом глюк.
 

God

Новичок
и нет в нем директив препроцессору
Раз нет директив, то достаточно заменить их на class_exists и не париться теперь на отслеживание, где поимел include без _once, и поиск каких-то плавающих глюков
 

McSimm

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

tony2001

TeaM PHPClub
>Include и require идентичны во всём, кроме обработки облома.

так и написано "облома"?
это где такой мануал?
 

God

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

McSimm

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

-~{}~ 18.04.06 15:32:

и не париться теперь на отслеживание, где поимел include без _once, и поиск каких-то плавающих глюков
 

eugef

Новичок
tony2001
>Include и require идентичны во всём, кроме обработки облома.
так и написано "облома"?
это где такой мануал?
Мануал с сайта http://script-info.net

McSimm
сейчас как раз автору темы усиленно советуют забить на непонятую проблему, т.к. ее легко можно избежать
Полностью с тобой согласен.

В общем остается вопрос - как может быть такое, что файл иногда подключается дважды, если везде (10 раз проверил) для подключения используется одна функция, которая подключает файл через include_once???

Есть мнение, что это возникает из-за того, что один файл подключается с разных виртуальных хостов.
 

tony2001

TeaM PHPClub
>Мануал с сайта http://script-info.net
красота..
мануал пятилетней давности и машинный перевод Пирогова примерно того же времени.
и всё это под соусом "мега-сайт про все языки".

особенно мне нравится этот "великий русский языка":
Обработка возвращает: можно выполнить оператор return() внутри подключённого файла, чтобы прервать обработку этого файла и возвратиться в скрипт, вызвавший его. Также можно возвращать значения из подключённых файлов. Вы можете принять значение вызова include как обычно.
Как хорошо, что я могу принять значение.
А то я уже переживать начал..

Поскольку include() и require() являются специальными конструкциями языка, вы обязаны заключить их в блок операторов, если это внутри условного блока.
Заключить куда-что-это-внутри?

к сожалению, таких сайтов (особенно почему-то в Рунете) очень много.
но я не знаю НИ ОДНОГО сайта, который бы обновлял документацию (а она меняется и пополняется ежедневно).

и главное - есть php.net, у него есть куча зеркал.
зачем ходить на какую-то поделку очередного студента и читать мануал ТАМ ?
 

eugef

Новичок
tony2001
и главное - есть php.net, у него есть куча зеркал.
зачем ходить на какую-то поделку очередного студента и читать мануал ТАМ ?
В том то и дело, что этот мануал есть в offline версии (скачал архив и смотри без инета) - поэтому и использую.

Offtopic: (можно и веточку создать по теме)
Подскажите другой offline справочник по PHP - буду очень благодарен.

А по-сути практически никто ничего толкового про разницу между require и include не сказал (сугубо имхо).
 

tony2001

TeaM PHPClub
>В том то и дело, что этот мануал есть в offline версии (скачал архив и смотри без инета) - поэтому и использую.
http://ru.php.net/download-docs.php

>А по-сути практически никто ничего толкового про разницу между require и include не сказал (сугубо имхо).
IMNSHO после мануала добавить нечего.
Там ВСЁ написано.
 
Сверху