Выцепить назойливый NOTICE

whirlwind

TDD infected, paranoid
Выцепить назойливый NOTICE

Повесил хендлер ошибок. Стало доставать следующее сообщение.

[client 127.0.0.1] NOTICE PHP in E:\\project\\cmf\\support\\mlog.class.php at 260 say: Redefining already defined constructor for class MLog


260 - естессно function __construct. Не фатально, но неприятно. Не могу найти где проглючил. Во всех файлах-классах есть такая оберточка, для примера

PHP:
if ( !class_exists('classname') ){
   include('baseclass.php')
   class classname extends baseclass{


   }
}
Т.е. файлы инклюдятся один раз. Временно закомментил конструкторы вверх по иерархии, все равно где то редефайнит. Как бы его выцепить?
 

whirlwind

TDD infected, paranoid
В том то и фишка, что нет. Два наследника и две записи в логе.

-~{}~ 22.11.05 10:46:

Очередное подверждение, что код в конструкторах - это вред. Нашел где протупил

PHP:
        public function __construct(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            //if ( !$this->_isInitialized() ){
            //    $this->_initSingleton();
            //}
            return;
        }
 

whirlwind

TDD infected, paranoid
Хм... думал из-за this трабла... нифига, оказываецца.
Есть такой кусок в конструкторе
PHP:
self::$somevar = ML_ALL;
где $somevar некий статический атрибут класса, а ML_ALL - константа, объявленная в этом же файле. Так вот если закомментировать данное присвоение, то сообщения о редефайне пропадают. Нутром чую, что дело каким-то образом связано с обработкой дефайна. Кто нить может ткнуть в связанный RTFW/M?

-~{}~ 22.11.05 11:46:

> вместо оберточки используй
Не, не катит. Есть разница между "подключить один раз" и "не подключится более одного раза". Фича MSVC.
 

si

Administrator
whirlwind
думаю что require_once это то что вам надо, подумайте над этим.
 

whirlwind

TDD infected, paranoid
Убрал обертки, поставил по всей иерархии require_once -нотайс выводится один раз. Ради эксперимента отменил все once на обычные варианты - нотайс выводится один раз. Так же для эксперимента сделал несколько инклудов одного и того же класса подряд (без оберток с обычным include) - нотайс выводится один раз! Комментирую присвоение атрибуту константного значения - нотайс не выводится. Что бы не было левых вопросов и ответов, дословно

объявление константы в начале файла класса
PHP:
if ( !defined('ML_ALL'))    define('ML_ALL',ML_ERROR|ML_WARNING|ML_NOTICE,true);
вариант без нотайса
PHP:
        public function __construct(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END

            if ( !self::$mlog_init ){
                ini_set('track_errors',1);
                ini_set('log_errors',true);
                ini_set('html_errors',false);

                self::$mlog_debug = false;
            //    self::$mlog_log_mask = ML_ALL;
                self::$mlog_init = true;
            }
            return;
        }
вариант с нотайсом
PHP:
        public function __construct(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END

            if ( !self::$mlog_init ){
                ini_set('track_errors',1);
                ini_set('log_errors',true);
                ini_set('html_errors',false);

                self::$mlog_debug = false;
                self::$mlog_log_mask = ML_ALL;
                self::$mlog_init = true;
            }
            return;
        }
При чем тут вообще include_once? Разницу между фактическим и косвеным редефайном чувствуете?
 

si

Administrator
whirlwind
странные вы вещи говорите, похоже не совсем понимаете для чего надо использовать require_once

у вас такое работает ?
PHP:
<?php
class  Foo {}
class Foo {}
?>
да и какая версия PHP у вас


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

whirlwind

TDD infected, paranoid
5.0.4

такое конечно же не работает, но такое

PHP:
<?php

include('support/mlog.class.php');
include('support/mlog.class.php');
include('support/mlog.class.php');

?>
работает. При том, что MLog без обертки.
 

whirlwind

TDD infected, paranoid
PHP:
if ( !defined('ML_ERROR'))  define('ML_ERROR'   ,E_USER_ERROR   ,true);
if ( !defined('ML_WARNING'))define('ML_WARNING' ,E_USER_WARNING ,true);
if ( !defined('ML_NOTICE')) define('ML_NOTICE'  ,E_USER_NOTICE  ,true);
if ( !defined('ML_ALL'))    define('ML_ALL',ML_ERROR|ML_WARNING|ML_NOTICE,true);

if ( !class_exists('MLog') ){

    if ( !defined('DEBUG_Mlog') ) define('DEBUG_MLog',false,true);
    if ( !defined('DEBUG_MLog_ls') ) define('DEBUG_MLog_ls',"<br>\n",true);

    class MLog {
        private static $mlog_init;
        private static $mlog_log_mask;
        private static $mlog_debug;
    
        public function setDebug($flag){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return $this->_setDebug($flag);
        }
    
        public function getDebug(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return $this->_getDebug();
        }
    
        public function isDebug(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return $this->_getDebug();
        }
    
        public function setLogMask($mask){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return $this->_setLogMask($mask);
        }
    
        public function getLogMask(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return $this->_getLogMask();
        }
    
        public function setLogFile($filename=null){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            ini_set('error_log',$filename);
            return true;
        }
    
        public function mlog(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            $argc = func_num_args();
            
            if ( $argc == 0 ){
                return false;
            }
            $argv = func_get_args();
            $type = ML_NOTICE;
            if ( $argc > 1 ){
                if ( $argv[1] && ($argv[1] == ML_ERROR || $argv[1] == ML_WARNING
                   || $argv[1] == ML_NOTICE) )
                {
                    $type = $argv[1];
                }
                array_splice($argv,1,1);
            }
    
            if ( $type & self::$mlog_log_mask ){
                $msg = call_user_func_array('sprintf',$argv);
                error_log($this->_formatMessage($msg,$type));
                if ( $this->isDebug() ){
                    echo $this->_formatMessage($msg,$type,true);
                }
            }

            return true;
        }
    
    // private or hidden methods
    
        protected function _formatMessage($msg,$level,$for_echo=false){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            $p = 'UNKNOWN';
            switch ($level){
                case ML_ERROR:
                    $p = 'ERROR';
                    break;
                case ML_WARNING:
                    $p = 'WARNING';
                    break;
                case ML_NOTICE:
                    $p = 'NOTICE';
                    break;
                default:
            }
    
            if ($for_echo){
                return "<b>$p</b>: $msg<br>\n";
            }
            /*
            $stack = debug_backtrace();
            $id = '';
            return "$p $id $msg";
            */
            return "$p $msg";
        }
    
        private function _setDebug($flag){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            ini_set('display_errors',($flag ? true : false));
            return self::$mlog_debug = $flag ? true : false;
        }
    
        private function _getDebug(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return self::$mlog_debug ? true : false;
        }
    
        private function _setLogMask($mask){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return self::$mlog_log_mask = $mask;
        }
    
        private function _getLogMask(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return self::$mlog_log_mask;
        }
    
        protected function _isInitialized(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            return self::$mlog_init;
        }

        public function __construct(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END

            if ( !self::$mlog_init ){
                ini_set('track_errors',1);
                ini_set('log_errors',true);
                ini_set('html_errors',false);
                ini_set('display_errors',($flag ? true : false));
                self::$mlog_debug = false;
                self::$mlog_log_mask = ML_ALL;
                self::$mlog_init = true;
            }
            return;
        }
    
        // virtual
        public function __destruct(){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
        }
    
        public function dumpHash($hash){
            //DEBUG-BEG
            if ( DEBUG_MLog ) echo __CLASS__,"::",__FUNCTION__,DEBUG_MLog_ls;
            //DEBUG-END
    
            $text = '';
            while (list($k,$v) = each($hash)){
                $text .= "$k => $v\n";
            }
            return $this->mlog("\n$text");
        }

    }  // eof class MLog

    function mlog_error_handle_function($errno,$errmsg,$file,$line,$vars){
        $error_codes = array (
            0x0001 => ML_ERROR,
            0x0002 => ML_WARNING,
            0x0004 => ML_ERROR,
            0x0008 => ML_NOTICE,
            0x0010 => ML_ERROR,
            0x0020 => ML_WARNING,
            0x0040 => ML_ERROR,
            0x0080 => ML_WARNING,
            0x0100 => ML_ERROR,
            0x0200 => ML_WARNING,
            0x0400 => ML_NOTICE
        );
    
        //if ( $error_codes[ $errno ] == ML_NOTICE ){
        //    echo "<pre>";
        //    print_r(debug_backtrace());
        //    echo "</pre>";
        //}
    
        // format message
        $msg = "PHP in $file at $line say: $errmsg";
        $mlog_instance = new MLog;
        $mlog_instance->mlog($msg,$error_codes[$errno]);
        return true;
    }
    error_reporting(0);
    set_error_handler('mlog_error_handle_function');

}
 

si

Administrator
test.php
PHP:
<?php

include('class.foo.php');
include('class.foo.php');

?>
class.foo.php
PHP:
<?php
class Foo {}
?>
<b>Fatal error</b>: Cannot redeclare class foo in <b>Z:\public_html\dev\test\a1\class.foo.php</b> on line <b>2</b>

P.S. у вас ZendPlatforn/Performance/eAccelerator не стоит случайно ?

-~{}~ 22.11.05 12:37:

whirlwind

да уж

а if ( !class_exists('MLog') ){ по вашену что делает ?

уберите его и сравните резульатат с once и без ...
 

whirlwind

TDD infected, paranoid
А какая версия?

Говорю же - убирал и так и сяк. Ошибки cant redeclare нет! Есть аналогичный нотайс.
 

si

Administrator
whirlwind
не может такого быть !

-~{}~ 22.11.05 13:01:

P.S. у меня 5.0.4 и 5.1RC2

-~{}~ 22.11.05 13:03:

отключите все zend_extension если они есть, перезапусте апаче, и проверьте мой код.
 

Nimous

Guest
public function mlog();
-Это что, не второй конструктор?
Я вот её закомментировал, и, естественно, всё заработало.
 

whirlwind

TDD infected, paranoid
Че, правда? 8-0
Пляяяя. Вот что бывает, когда юзаются всякие меджик фанкшенс. Имя конструктора должно совпадать с именем класса и баста!

Вообще то оно и так работало, только нотайс был. Но спасибо за дельный вариант. Сейчас проверю.

-~{}~ 22.11.05 15:27:

Nimous Спасибо дружище, помогло! Вот же бывает, очевидных вещей не замечаешь...
 
Сверху