I tried existing questions in the forum and I was not able to figure out how I can convert this below code using create_function. When I run the application I get a deprecated error in the logs. Can you please post the converted code?
private function _set_error_handler() {
set_error_handler(
create_function(
'$severity, $message, $file, $line',
'throw new Exception($message . " in file " . $file . " on line " . $line);'
)
);
}
set_error_handler() requires a Callable.
You can use anonymous function :
private function _set_error_handler() {
set_error_handler(
function($severity, $message, $file, $line) {
throw new Exception($message . " in file " . $file . " on line " . $line);
}
);
}
See live demo
Or a separated function :
private function _set_error_handler() {
set_error_handler([$this, 'on_error']);
}
// should be public
public function on_error($severity, $message, $file, $line) {
throw new Exception($message . " in file " . $file . " on line " . $line);
}
See live demo
I want to create a logfile for my system to register/log every action they do inside the system. But I have no idea how to do it.
For example, I have this php code that does the login function.
public function hasAccess($username,$password){
$form = array();
$form['username'] = $username;
$form['password'] = $password;
$securityDAO = $this->getDAO('SecurityDAO');
$result = $securityDAO->hasAccess($form);
//var_dump($form);
//var_dump($result);
if($result[0]['success']=='1'){
$this->Session->add('user_id', $result[0]['id']);
//$this->Session->add('username', $result[0]['username']);
//$this->Session->add('roleid', $result[0]['roleid']);
return $this->status(0,true,'auth.success',$result);
}else{
return $this->status(0,false,'auth.failed',$result);
}
}
now I want to create a logfile entitled 'the date today', then when that functions is used for loging in, it will write that user has logged in, the same with other functions. But I only want a single file for every day.
Could anyone be kind enough to guide and teach me how I should do my code?
To write to a log file and make a new one each day, you could use date("j.n.Y") as part of the filename.
//Something to write to txt log
$log = "User: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
"Attempt: ".($result[0]['success']=='1'?'Success':'Failed').PHP_EOL.
"User: ".$username.PHP_EOL.
"-------------------------".PHP_EOL;
//Save string to log, use FILE_APPEND to append.
file_put_contents('./log_'.date("j.n.Y").'.log', $log, FILE_APPEND);
So you would place that within your hasAccess() method.
public function hasAccess($username,$password){
$form = array();
$form['username'] = $username;
$form['password'] = $password;
$securityDAO = $this->getDAO('SecurityDAO');
$result = $securityDAO->hasAccess($form);
//Write action to txt log
$log = "User: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
"Attempt: ".($result[0]['success']=='1'?'Success':'Failed').PHP_EOL.
"User: ".$username.PHP_EOL.
"-------------------------".PHP_EOL;
//-
file_put_contents('./log_'.date("j.n.Y").'.txt', $log, FILE_APPEND);
if($result[0]['success']=='1'){
$this->Session->add('user_id', $result[0]['id']);
//$this->Session->add('username', $result[0]['username']);
//$this->Session->add('roleid', $result[0]['roleid']);
return $this->status(0,true,'auth.success',$result);
}else{
return $this->status(0,false,'auth.failed',$result);
}
}
create a logfile in php, to do it you need to pass data on function and it will create log file for you.
function wh_log($log_msg)
{
$log_filename = "log";
if (!file_exists($log_filename))
{
// create directory/folder uploads.
mkdir($log_filename, 0777, true);
}
$log_file_data = $log_filename.'/log_' . date('d-M-Y') . '.log';
// if you don't add `FILE_APPEND`, the file will be erased each time you add a log
file_put_contents($log_file_data, $log_msg . "\n", FILE_APPEND);
}
// call to function
wh_log("this is my log message");
Agree with the #jon answer. Just added modified the path to create the log directory inside the root
function wh_log($log_msg) {
$log_filename = $_SERVER['DOCUMENT_ROOT']."/log";
if (!file_exists($log_filename))
{
// create directory/folder uploads.
mkdir($log_filename, 0777, true);
}
$log_file_data = $log_filename.'/log_' . date('d-M-Y') . '.log';
file_put_contents($log_file_data, $log_msg . "\n", FILE_APPEND);
}
wh_log('log to file');
just added $_SERVER['DOCUMENT_ROOT']
Please check with this documentation.
http://php.net/manual/en/function.error-log.php
Example:
<?php
// Send notification through the server log if we can not
// connect to the database.
if (!Ora_Logon($username, $password)) {
error_log("Oracle database not available!", 0);
}
// Notify administrator by email if we run out of FOO
if (!($foo = allocate_new_foo())) {
error_log("Big trouble, we're all out of FOOs!", 1,
"operator#example.com");
}
// another way to call error_log():
error_log("You messed up!", 3, "/var/tmp/my-errors.log");
?>
Please check this code, it works fine for me.
$data = array('shopid'=>3,'version'=> 1,'value=>1'); //here $data is dummy varaible
error_log(print_r($data,true), 3, $_SERVER['DOCUMENT_ROOT']."/your-file-name.log");
//In $data we can mention the error messege and create the log
You could use built-in function trigger_error() to trigger user errors/warnings/notices and set_error_handler() to handle them. Inside your error handler you might want to use error_log() or file_put_contents() to store all records on files. To have a single file for every day just use something like sprintf('%s.log', date('Y-m-d')) as filename. And now you should know where to start... :)
This is my working code. Thanks to Paulo for the links. You create a custom error handler and call the trigger_error function with the correct $errno exception, even if it's not an error. Make sure you can write to the log file directory without administrator access.
<?php
$logfile_dir = "C:\workspace\logs\\"; // or "/var/log/" for Linux
$logfile = $logfile_dir . "php_" . date("y-m-d") . ".log";
$logfile_delete_days = 30;
function error_handler($errno, $errstr, $errfile, $errline)
{
global $logfile_dir, $logfile, $logfile_delete_days;
if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting, so let it fall
// through to the standard PHP error handler
return false;
}
$filename = basename($errfile);
switch ($errno) {
case E_USER_ERROR:
file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "ERROR >> message = [$errno] $errstr\n", FILE_APPEND | LOCK_EX);
exit(1);
break;
case E_USER_WARNING:
file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "WARNING >> message = $errstr\n", FILE_APPEND | LOCK_EX);
break;
case E_USER_NOTICE:
file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "NOTICE >> message = $errstr\n", FILE_APPEND | LOCK_EX);
break;
default:
file_put_contents($logfile, date("y-m-d H:i:s.").gettimeofday()["usec"] . " $filename ($errline): " . "UNKNOWN >> message = $errstr\n", FILE_APPEND | LOCK_EX);
break;
}
// delete any files older than 30 days
$files = glob($logfile_dir . "*");
$now = time();
foreach ($files as $file)
if (is_file($file))
if ($now - filemtime($file) >= 60 * 60 * 24 * $logfile_delete_days)
unlink($file);
return true; // Don't execute PHP internal error handler
}
set_error_handler("error_handler");
trigger_error("testing 1,2,3", E_USER_NOTICE);
?>
Use below function
// Enable error reporting
ini_set('display_errors', 1);
//Report runtime errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
//error_reporting(E_ALL & ~E_NOTICE);
// Tell php where your custom php error log is
ini_set('error_log', 'php_error.log');
$dateTime=date("Y-m-d H:i:s");
$ip= $_SERVER['REMOTE_ADDR'];
$errorString="Error occured on time $dateTime by ip $ip";
$php_error_msg.=$errorString;
// Append the error message to the php-error log
//error_log($php_error_msg);
error_log("A custom error has been triggered",1,"email_address","From: email_address");
Above function will create a log in file php_error with proper description and email will be sent.
For printing log use this function, this will create log file in log folder. Create log folder if its not exists .
logger("Your msg in log ", "Filename you want ", "Data to be log string or array or object");
function logger($logMsg="logger", $filename="logger", $logData=""){
$log = date("j.n.Y h:i:s")." || $logMsg : ".print_r($logData,1).PHP_EOL .
"-------------------------".PHP_EOL;
file_put_contents('./log/'.$filename.date("j.n.Y").'.log', $log, FILE_APPEND);
}
A custom log function (for php server):
Features:
logs will be hidden (invisible) to public (without doing setting on server)
easy to read logs data
function log_it($info)
{
$filename = $_SERVER['DOCUMENT_ROOT'] . '/' . '1LOGS.php';
$dieCode = "<?php die();?>";
$fileStart = #file_get_contents($filename, false, null, 0, 14);
if ($fileStart) {
if ($fileStart !== $dieCode)
file_put_contents($filename, $dieCode . file_get_contents($filename));
} else file_put_contents($filename, $dieCode);
if (is_string($info) || is_int($info) || is_float($info)) $txt = ' ' . $info;
elseif (is_array($info) || is_object($info)) $txt = PHP_EOL . ' ' . print_r($info, true);
else $txt = ' ' . 'Data Type: ' . gettype($info);
file_put_contents(
$filename,
PHP_EOL . '>>> ( Date:' . date("Y:m:d H:i:s") . ' )' . $txt,
FILE_APPEND
);
}
inform if it has room for improvement
Here's my PHP log function:
If you want to edit the log rows $maxLogs=5,
or the order to write your logs $logOrder='top'
<?php
##### Start Script
lg('Script start','start');
#Code......
lg('Script end','end');
function lg($str,$mod='Your Log Category'){
$ts = microtime(true);
if(!defined('logTimer')){
define('logTimer',microtime(true));
}
$diff=abs(round(($ts-logTimer)*1000,2));
$maxLogs=5;
$logOrder='top';#new Logs at top
$filename = './log.txt';
$log=[];
if(!file_exists($filename)){
if(!file_put_contents($filename,json_encode($log,128))){
echo "Can’t open to write '$filename' Check Permissions";
return;
}
}else{
$c=file_get_contents($filename);
if(trim($c)==''){$c='[]';}
$log =#json_decode($c,true);
if(!is_Array($log)){$log=[];}
}
$new=['mod'=>$mod,'date'=> date('Y-m-d H:i:s')." Scripttime: ".$diff."ms",'log'=>$str];
if($logOrder=='top'){
array_unshift($log , $new);
$log=array_slice($log,0,$maxLogs);
}else{
$log[]=$new;
$log=array_slice($log,0-$maxLogs,$maxLogs);
}
$logs=json_encode($log,128);
if(!file_put_contents($filename,$logs) ){echo ("Can’t open to write '$filename' Check Permissions") ;return;}
return $str;
}
?>
The Output looks like:
[
{
"mod": "delete",
"date": "2022-08-04 13:48:02 0.33ms",
"log": "test 2"
},
{
"mod": "start",
"date": "2022-08-04 13:48:29 0ms",
"log": "test"
},
{
"mod": "delete",
"date": "2022-08-04 13:48:29 0.27ms",
"log": "test 2"
}
]
I have written a very simple page counter and a logging script that increments a counter stored in a file and logs information about the client's operating system and which browser they use. It's a simple spare time project I've been working on, and as such it is extremely rudimentary, writing the counter and the logged information in a designated folder for each page on the site, in a new file for each day.
The thing is, I recently used blitz.io to test my site, and when I ran a "Rush" of 250 requests per second, the counters and the logs were completely flushed, except for the very last query.
I'm not perfectly sure what happened, but I suspect something along the lines of PHP not properly finishing up the previous query before taking on the next one.
I use file_get_contents()/file_put_contents() for the both of them, instead of file(). Would changing to file() solve the problem?
Here's the counter:
$filename = '.' . $_SERVER['PHP_SELF'];
$counterpath = '/Websites/inc/logs/counters/total/' . getCurrentFileName() . '-counter.txt';
$globalcounter = '/Websites/inc/logs/counters/total/global-counter.txt';
if (file_exists($counterpath)) {
$hit_count = file_get_contents($counterpath);
$hit_count++;
file_put_contents($counterpath,$hit_count);
}
else {
$hit_count = "1";
file_put_contents($counterpath, $hit_count);
}
And here's the logger:
$logdatefolder = '/Websites/inc/logs/ip/' . date('Y-m-d',$_SERVER['REQUEST_TIME_FLOAT']);
$logfile = $logdatefolder . "/" . getCurrentFileName() . '-iplog.html';
$ua = getbrowser();
if (false == (file_exists($logdatefolder))) {
mkdir($logdatefolder);
}
function checkRef() {
if (!isset($_SERVER['HTTP_REFERER'])) {
//If not isset -> set with dummy value
$_SERVER['HTTP_REFERER'] = 'N/A';
}
return $_SERVER['HTTP_REFERER'];
}
/* Main logger */
$logheader = "<!DOCTYPE html><html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en-US\"><head><title>" . getCurrentFileName() . " log</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /></head><body>";
$logentry = date("Y-m-d, H:i:s, O T") . ":" .
"<br />- Requesting: http://giphtbase.org" . $_SERVER['REQUEST_URI'] .
"<br />- Arriving from: " . checkRef() .
"<br />- Browser: " . $ua['browser'] .
"<br />- Full browser name: " . $ua['name'] .
"<br />- Operating system: " . $ua['platform'] .
"<br />- Full user agent: " . $ua['userAgent'] .
"<br />";
$logfooter = "<!-- Bottom --></body></html>";
if (file_exists($logfile)) {
$logPage = file_get_contents($logfile);
$logContents = str_replace("<!-- Bottom --></body></html>","",$logPage);
file_put_contents($logfile, $logContents . $logentry . $logfooter);
}
elseif (false == (file_exists($logfile))) {
file_put_contents($logfile, $logheader . $logentry . $logfooter);
}
You should use the FILE_APPEND flag in your file_put_contents() otherwise you will only ever see the last entry:
file_put_contents($logfile, $logContents . $logentry . $logfooter, FILE_APPEND);
As for the counter, it looks like the file is trying to be written to too many times by different threads, causing it to be inaccessible. You should either use a database, or create a file_lock, or create temporary files and run a cronjob to do the math.
I writing a command and then reading back from a server via sockets in PHP. We have 20 servers that all run a Node JS script which can receive these commands and execute them. The Node JS script will return "ok" which PHP reads back to confirm the command has gone through.
The Node JS script listens on port 9000 and is set to allow half open.
Most of the time this works fine, but when a high volume of commands are sent we get errors back occasionally that say this:
Contents: Message received back from socket was 'Unexpected token {'
Transport endpoint is not connected
The transport endpoint message suggests to me that it has not connected successfully.
I am no expert in sockets so I don't know whether the implementation I have used is "correct". It does work most of the time but I am aware that there are functions like socket_bind and socket_listen that may work better, though I am not sure what they do.
Here is the PHP code that we are using. Any suggestions would be most appreciated.
public function sendDaemonCommand($address, $template_id, $params = array()) {
$hostname = $this->getHostnameFromPrivateIP($address);
$port = 9000;
$command = array('template_id' => $template_id, 'params' => $params);
$command = json_encode($command);
// Create a TCP Stream socket
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
$this->mailError("Command Failed - " . $hostname, "Failed to create socket on " . $address . "\n\n" . socket_strerror(socket_last_error()) . "\n\nCommand:\n\n" . $command . "\n" . $this->functionTraceback());
return false;
}
// Connect to socket
if (socket_connect($sock, $address, $port) === false) {
$this->mailError("Command Failed - " . $hostname, "Failed to connect to socket on " . $address . "\n\n" . socket_strerror(socket_last_error($sock)) . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
socket_close($sock);
return false;
}
// Write command to socket
$_command = $command;
$length = strlen($_command);
while (true) {
$sent = socket_write($sock, $_command, $length);
if ($sent === false) {
$this->mailError("Command Failed - " . $hostname, "Failed to write command to socket on " . $address . "\n\n" . socket_strerror(socket_last_error($sock)) . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
socket_shutdown($sock, 2);
socket_close($sock);
return false;
}
if ($sent < $length) {
$_command = substr($_command, $sent);
$length -= $sent;
}
else {
break;
}
}
socket_shutdown($sock, 1);
// Read back from socket
if (($out = socket_read($sock, 1024)) !== false) {
#socket_shutdown($sock, 0);
$out = trim($out);
if ($out !== "ok") {
$this->mailError("Command Failed - " . $hostname, "Message received back from socket was '" . $out . "' on " . $address . "\n\n" . socket_strerror(socket_last_error($sock)) . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
socket_close($sock);
return false;
}
}
else {
$this->mailError("Command Failed - " . $hostname, "Failed to read from socket on " . $address . "\n\n" . socket_strerror(socket_last_error($sock)) . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
socket_shutdown($sock, 0);
socket_close($sock);
return false;
}
socket_close($sock);
return $out;
}
For a simple socket client such as this, I much prefer fsockopen() - it drastically reduces the complication of the client code and does not require the sockets extension, which is not available everywhere. The main disadvantage to this is that you lose the string error messages, but these are rarely that useful anyway - you still get an error string from creating the socket, and if read/write operations fail it's because the socket has become disconnected.
I'm also not sure how useful "allow half open" is in this context - I think it is likely to create more problems than it solves. The calls to socket_shutdown() are not doing anything useful here (and may be the source of your problems) - you would only use this if you are operating on a socket that will not be closed and may be operated on at a later point in time by some other code. Since you create a new socket and destroy it in the same routine, this is not the case.
Here is your code rewritten to use fsockopen() - as you can see, it is somewhat shorter and simpler. I have also modified it slightly so that it always returns a bool - your code returns either bool FALSE or string ok, and since there are only these two options it makes more sense for the function to always return a bool.
public function sendDaemonCommand($address, $template_id, $params = array()) {
// Prepare data
$hostname = $this->getHostnameFromPrivateIP($address);
$port = 9000;
$command = array('template_id' => $template_id, 'params' => $params);
$_command = $command = json_encode($command);
$length = strlen($_command);
// Connect to socket
if (!$sock = fsockopen($address, $port, $errNo, $errStr)) {
$this->mailError("Command Failed - " . $hostname, "Failed to connect to socket on " . $address . "\n\n" . $errStr . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
return false;
}
// Write command to socket
while (true) {
// Try and write data to socket
$sent = fwrite($sock, $_command, $length);
// If it failed, error out
if ($sent === false) {
$this->mailError("Command Failed - " . $hostname, "Failed to write command to socket on " . $address . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
fclose($sock);
return false;
}
// If there is data left to send, try again
if ($sent < $length) {
$_command = substr($_command, $sent);
$length -= $sent;
continue;
}
// If we get here the write operation was successful
break;
}
// Read back from socket and close it
$out = fread($sock, 1024);
fclose($sock);
// Test the response from the server
if ($out === false) {
$this->mailError("Command Failed - " . $hostname, "Failed to read from socket on " . $address . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
return false;
} else if (($out = trim($out)) !== "ok") {
$this->mailError("Command Failed - " . $hostname, "Message received back from socket was '" . $out . "' on " . $address . "\n\nCommand:\n\n" . $command. "\n" . $this->functionTraceback());
return false;
} else {
return true;
}
}