Друзья, на просторах интернетика можно найти много инфомрации, но, когда тебе необходимо не 1,5 млн страниц, как может предложить Ваша любимая поисковая система, а всего один точный ответ, на помощь приходит код ниже...

Чтобы логировать ошибки PHP, а также перехватывать ошибки самого PHP, понадобиться посмотреть видосик, а также следующий код...

Код, который необходимо разметить вверху приложения (в index.php). ОН НЕ ООП-шный, поэтому НЕ суйте его в классы, так как он не будет работать.

function handler($errno, $errMess, $errfile, $errline)//номер ошибки, ссобщение, файл, строка
{
    throw new Exception($errMess." FILE: {$errfile} LINE: {$errline}", $errno);
}

set_error_handler('handler');

Далее, чтобы заработало всё, как в видео, необходимы эти функции:


function repl($ar)/*просто что-то на что-то меняем (для безопасности)*/
 {
  $arTo=[];
  if(is_array($ar)){
   foreach ($ar as $item_=>$value_) {
    array_push($arTo," *00* {$value_} *00* ");
   }
  }
  return $arTo;
 }
 
 function clear($data,$newLine=false,$link=false){ /*очищаем данные...*/
  $array1 = array('?','%', '/*', '*/', '//', 'wss:', 'ws:', 'blob:', '\x', 'localhost', 'http:', 'https:', 'script', 'base64', 'mysql', 'union', 'select','update','where','\0x','delete','drop','information','schema');
  if($newLine){
   $data=str_ireplace("\n",'\r\n',$data);
  }
  if($link){
   $array1 = array('/*', '*/', 'wss:', 'ws:', 'blob:', 'localhost', 'script', 'base64', 'mysql', 'union', 'select','update','where','\0x','delete','drop','information','schema');
  }
  $data = trim(htmlspecialchars(strip_tags($data), ENT_QUOTES));
  $data = filter_var($data,FILTER_SANITIZE_STRING);
  return str_ireplace($array1, '', $data);
  
 }
 function ip(){/*получаем IP клиента*/
  if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
   return $_SERVER['HTTP_CLIENT_IP'];
  } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
   return $_SERVER['HTTP_X_FORWARDED_FOR'];
   
  } else { return $_SERVER['REMOTE_ADDR']; }
 }
 function url(){/*получаем базовую ссылку приложения (например, inversre.pro — т.е. сам адрес сайта)*/
  if(isset($_SERVER['HTTPS'])){
   $protocol = ($_SERVER['HTTPS'] && $_SERVER['HTTPS'] != "off") ? "https" : "http";
   
  }else{
   $protocol = 'http';
   
  } return $protocol . "://" . $_SERVER['HTTP_HOST'];
 }

Это пример того, как далее использовать саму функцию логирования внутри класса, ну, и сам класс.

Функцию логирования (logErrors) необходимо с помощью функции set_exception_handler запустить внутри __construct , чтобы перехватчик ошибок «завёлся»

public function __construct(){
set_exception_handler([$this, 'exceptionHandler']);
}

и внутри ЭТОГО ЖЕ класса должет быть сам метод...

public function exceptionHandler($e){
$this->logErrors($e->getMessage(), $e->getFile(), $e->getLine());
}

Пример классса:

class Start{
    public function __construct(){
        set_exception_handler([$this, 'exceptionHandler']);
    }
    public function exceptionHandler($e){
        $this->logErrors($e->getMessage(), $e->getFile(), $e->getLine());
    }

    public function logErrors($message=NULL,$file=NULL,$line=NULL){
        define('ROOT',getenv('DOCUMENT_ROOT').'/');
        define('LOGS',ROOT.'/logs/');
        /**
        may..
         * string(494)"LOGIN DATA (RAW): {"location_":"https: \/\/0.inverser.pro\/public-login","get":"public-login","data":{"login":"0@gmail.com","password":"y^gSh=K+i2^"},"publicToken":"9lJKbHlMUHg4WHYxcHUreG1JeEE2RVhxV1NFMVExdllzT3pLQkZYdEN2VXJYZFZXTEhIWXZReFc3SUlaTlo0czdzc0M0ZVdJT0N6bTd4QUwwWU1xbUs5NXlNeXlSS2VWemlFR2lpbXczZUdIRWFMTnJQWkVUdz0="}"
    
         */
        if(!empty($message)){
            $message=str_ireplace('https:\/\/p.com','',$message);
            $arFrom1=['https://','http://','ws://','wss://','\/','.','\\'];
            $arTo1=[' https ',' http ',' ws ',' wss ',' / ',' . ',''];
            $message=str_ireplace(
                $arFrom1,
                $arTo1,
                $message
            );
            $arFrom2=['<','>','?','&','eval','exec'];
            $arTo2=repl($arFrom2);
            $message=str_ireplace(
                $arFrom2,
                $arTo2,
                $message
            );
        }
        $mtime=round(explode(' ',microtime())[0],3);
        if(!empty($mtime) and strpos($mtime,'.')!==false){
            $mtime=explode('.',$mtime)[1];
        }
        $er_time=date("Y-m-d H:i:s").'.'.$mtime;
        $yyyymm=date("Y-m");
        $U=clear(getenv("HTTP_USER_AGENT"));
        $folder=LOGS;
        if(!is_dir($folder)){
            mkdir($folder, 0700);
        }
        $fNm=$folder.'log_'.$yyyymm.'.php';
        $toLogReferrer=clear(str_ireplace(url(),'',urldecode(getenv('HTTP_REFERER'))));
        $toLogRequest=clear(str_ireplace(url(),'',urldecode(getenv('REQUEST_URI'))));
        try{
            $firstData='';
            if(!file_exists($fNm)){
                $firstData='
    Если Вы видите в сообщение такие символы «*00*» — это значит, что скрипт заменил некоторые символы. К примеру, пароль в файле лога выглядит так:
    z9456567gqFafghgSh=K+i2^ *00* ? *00*
                        ^     ^
    а на самом деле он:
    z9456567gqFafghgSh=K+i2^?
                        ^
    '."\n";
            }
            file_put_contents(
                $fNm,
                "{$firstData}$er_time | IP: " . ip() . " | MSG: {$message} | F: {$file} | L: {$line} | RQ: ". $toLogRequest .' | RF: ' . $toLogReferrer . ' | Br: ' . clear($U) . ' | SID: ' . session_id() . " \r\n\n",
                FILE_APPEND /*| LOCK_EX*/
            );
            /*if(filesize($fNm)>1024000){//1 MB
                try {
                    $nameArch=date("Y-m-d__H_i_s").'_'. uniqid().'.tar';
                    $a = new PharData($folder.$nameArch );
                    $a->addFile($fNm);
                    $a->compress(Phar::GZ);
                    unlink($folder.$nameArch);//del archive
                    unlink($fNm);//del .txt
                } catch (Exception $e) {
                    throw new Exception('EB001. '. $e ,500);
                }
            }*/
        }catch(Exception $e){
            if(!file_exists($fNm)){
                $firstData=''."\n";
            }
            file_put_contents(
                $fNm,
                "{$firstData}$er_time | IP: " . ip() . " | MSG: {$e} | F: {$file} | L: {$line} | RQ: ". $toLogRequest .' | RF: ' . $toLogReferrer . ' | Br: ' . clear($U) . ' | SID: ' . session_id() . " \r\n\n",
                FILE_APPEND /*| LOCK_EX*/
            );
            throw new Exception('EB002. ' ,500);
        }
    }

}


new Start;//пример инициализации класса (чтобы логирование заработало)

Помните, чтобы метод логирования (logErrors) мог гзиповать файлы логов, перед классом (с рабочим autoload), вам необходимо использовать


use PharData;
use Phar;

Like this:

php логирование ошибок в файл