file_put_contents()

Using PHP's standard file writing function for logging purposes. Enables simplest file log implementation, but features like log levels, rotation, formatting require manual implementation. Limited suitability for small-scale projects and learning purposes.

File WritingPHPSimple LoggingDebugFlat File

Library

file_put_contents

Overview

file_put_contents is "a built-in function for file writing in PHP" that provides basic logging functionality as a simple tool. It executes file open, data write, and file close operations in a single function, supporting append mode with the FILE_APPEND flag and exclusive control with LOCK_EX. Lightweight and suitable for debugging purposes and prototype development, it enables log file creation and management using only PHP's standard functionality.

Details

The file_put_contents function is a standard library function available since PHP 5.0, characterized by its simplicity in completing file operations in a single line. For log output, it preserves existing content with the FILE_APPEND flag and avoids race conditions during concurrent access with the LOCK_EX flag for exclusive control. It can implement basic logging functions such as structured log output in JSON format, timestamped entries, and error level classification. While it doesn't have the advanced functionality of dedicated logging libraries, it offers the convenience of low learning cost and immediate implementation.

Key Features

  • Simple One-Function Implementation: Execute file operations in one line
  • Append Mode Support: Preserve existing logs with FILE_APPEND flag
  • Exclusive Control: Avoid concurrent write race conditions with LOCK_EX
  • Flag Combinations: Simultaneous specification of multiple options possible
  • Error Handling: File operation success determination via return values
  • Performance: Lightweight and fast file writing processing

Pros and Cons

Pros

  • Zero dependencies as a PHP built-in function, no additional libraries required
  • Extremely low learning cost, immediate implementation and utilization possible
  • Practical logging functionality with FILE_APPEND and LOCK_EX flags
  • Performance through lightweight and fast file writing processing
  • Convenience and flexibility in debugging and prototype development
  • Structured logs and parsing ease through JSON output support

Cons

  • No advanced log management features like log levels or rotation
  • Performance constraints and memory usage during high-volume log output
  • Manual handling of file permission settings and directory rights management
  • Insufficient functionality for serious log analysis or monitoring system integration
  • Limited support for enterprise requirements like error handling and retry mechanisms
  • Scalability constraints for multiple files and log aggregation

Reference Pages

Code Examples

Basic Setup

<?php
// Basic log output
$message = "Application started: " . date('Y-m-d H:i:s');
file_put_contents('app.log', $message . PHP_EOL);

// Check and create log directory
$logDir = __DIR__ . '/logs';
if (!is_dir($logDir)) {
    mkdir($logDir, 0755, true);
}

// Set log file path
$logFile = $logDir . '/application.log';

// Permission check
if (!is_writable(dirname($logFile))) {
    throw new Exception('No write permission to log directory');
}

Basic Log Output

<?php
// Log output in append mode
$logFile = 'logs/app.log';
$message = '[' . date('Y-m-d H:i:s') . '] INFO: User login successful';

// Preserve existing content with FILE_APPEND flag
file_put_contents($logFile, $message . PHP_EOL, FILE_APPEND);

// Log output with exclusive control (concurrent access support)
file_put_contents(
    $logFile,
    $message . PHP_EOL,
    FILE_APPEND | LOCK_EX  // Combination of multiple flags
);

// Message with log level
function writeLog($level, $message, $logFile = 'logs/app.log') {
    $timestamp = date('Y-m-d H:i:s');
    $logEntry = "[{$timestamp}] {$level}: {$message}" . PHP_EOL;
    
    $result = file_put_contents($logFile, $logEntry, FILE_APPEND | LOCK_EX);
    
    if ($result === false) {
        error_log("Failed to write to log file: {$logFile}");
    }
    
    return $result !== false;
}

// Usage examples
writeLog('INFO', 'Application started');
writeLog('WARNING', 'Memory usage approaching threshold');
writeLog('ERROR', 'Database connection error');

Advanced Configuration (Structured Logs, Error Handling)

<?php
class SimpleLogger {
    private $logFile;
    private $dateFormat;
    
    public function __construct($logFile, $dateFormat = 'Y-m-d H:i:s') {
        $this->logFile = $logFile;
        $this->dateFormat = $dateFormat;
        
        // Check and create log directory
        $dir = dirname($logFile);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
    }
    
    public function log($level, $message, $context = []) {
        $logEntry = [
            'timestamp' => date($this->dateFormat),
            'level' => strtoupper($level),
            'message' => $message,
            'context' => $context,
            'memory_usage' => memory_get_usage(true),
            'process_id' => getmypid()
        ];
        
        // Structured log in JSON format
        $jsonLog = json_encode($logEntry, JSON_UNESCAPED_UNICODE) . PHP_EOL;
        
        $result = file_put_contents(
            $this->logFile,
            $jsonLog,
            FILE_APPEND | LOCK_EX
        );
        
        if ($result === false) {
            // Fallback: output to system log
            error_log("File log output failed: {$this->logFile}");
            error_log($message);
        }
        
        return $result !== false;
    }
    
    public function info($message, $context = []) {
        return $this->log('info', $message, $context);
    }
    
    public function warning($message, $context = []) {
        return $this->log('warning', $message, $context);
    }
    
    public function error($message, $context = []) {
        return $this->log('error', $message, $context);
    }
    
    public function debug($message, $context = []) {
        return $this->log('debug', $message, $context);
    }
}

// Usage examples
$logger = new SimpleLogger('logs/app.log');

$logger->info('User login', ['user_id' => 123, 'ip' => '192.168.1.100']);
$logger->warning('API limit approaching', ['current_calls' => 950, 'limit' => 1000]);
$logger->error('Payment processing error', [
    'order_id' => 'ORD-12345',
    'amount' => 9800,
    'error_code' => 'PAYMENT_DECLINED'
]);

Error Handling

<?php
// Log output with retry functionality
function writeLogWithRetry($message, $logFile, $maxRetries = 3, $delay = 100000) {
    $attempts = 0;
    
    while ($attempts < $maxRetries) {
        $result = file_put_contents(
            $logFile,
            $message . PHP_EOL,
            FILE_APPEND | LOCK_EX
        );
        
        if ($result !== false) {
            return true;
        }
        
        $attempts++;
        if ($attempts < $maxRetries) {
            usleep($delay); // Wait in microseconds
            $delay *= 2; // Exponential backoff
        }
    }
    
    // Final failure handling
    error_log("Log write failed after {$maxRetries} attempts: {$logFile}");
    return false;
}

// Log output with disk capacity check
function writeLogWithDiskCheck($message, $logFile, $minFreeSpace = 100 * 1024 * 1024) { // 100MB
    $freeSpace = disk_free_space(dirname($logFile));
    
    if ($freeSpace < $minFreeSpace) {
        error_log("Insufficient disk space: {$freeSpace} bytes");
        return false;
    }
    
    return file_put_contents(
        $logFile,
        $message . PHP_EOL,
        FILE_APPEND | LOCK_EX
    ) !== false;
}

// Log output with file size limit
function writeLogWithSizeLimit($message, $logFile, $maxSize = 10 * 1024 * 1024) { // 10MB
    if (file_exists($logFile) && filesize($logFile) > $maxSize) {
        // Log rotation (simple version)
        $backupFile = $logFile . '.old';
        rename($logFile, $backupFile);
    }
    
    return file_put_contents(
        $logFile,
        $message . PHP_EOL,
        FILE_APPEND | LOCK_EX
    ) !== false;
}

// Comprehensive error handling example
function safeLogWrite($level, $message, $context = []) {
    $logFile = 'logs/app.log';
    
    try {
        // Build log entry
        $logEntry = [
            'timestamp' => date('c'), // ISO 8601 format
            'level' => $level,
            'message' => $message,
            'context' => $context,
            'request_id' => $_SERVER['HTTP_X_REQUEST_ID'] ?? uniqid()
        ];
        
        $jsonLog = json_encode($logEntry, JSON_UNESCAPED_UNICODE);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception('JSON encode error: ' . json_last_error_msg());
        }
        
        // Disk capacity and file size check
        if (!writeLogWithDiskCheck($jsonLog, $logFile)) {
            throw new Exception('Disk space or file size limit exceeded');
        }
        
        // Write with retry
        if (!writeLogWithRetry($jsonLog, $logFile)) {
            throw new Exception('Failed to write log after retries');
        }
        
        return true;
        
    } catch (Exception $e) {
        // Fallback: output to syslog
        syslog(LOG_ERR, "Log write failed: {$e->getMessage()} - Original: {$message}");
        return false;
    }
}

// Usage examples
safeLogWrite('INFO', 'User registration completed', ['user_id' => 456]);
safeLogWrite('ERROR', 'Database connection failed', ['dsn' => 'mysql:host=localhost', 'code' => 2002]);

Practical Examples (Full Log Management)

<?php
// Daily log file management class
class DailyLogger {
    private $logDir;
    private $prefix;
    
    public function __construct($logDir = 'logs', $prefix = 'app') {
        $this->logDir = rtrim($logDir, '/');
        $this->prefix = $prefix;
        
        if (!is_dir($this->logDir)) {
            mkdir($this->logDir, 0755, true);
        }
    }
    
    private function getLogFile($date = null) {
        $date = $date ?: date('Y-m-d');
        return "{$this->logDir}/{$this->prefix}-{$date}.log";
    }
    
    public function log($level, $message, $context = []) {
        $logFile = $this->getLogFile();
        
        $logEntry = [
            'timestamp' => microtime(true),
            'datetime' => date('Y-m-d H:i:s.u'),
            'level' => strtoupper($level),
            'message' => $message,
            'context' => $context,
            'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)
        ];
        
        $jsonLog = json_encode($logEntry, JSON_UNESCAPED_UNICODE) . PHP_EOL;
        
        return file_put_contents($logFile, $jsonLog, FILE_APPEND | LOCK_EX) !== false;
    }
    
    // Automatic log file deletion (retention period management)
    public function cleanup($retentionDays = 30) {
        $cutoffDate = date('Y-m-d', strtotime("-{$retentionDays} days"));
        
        $files = glob("{$this->logDir}/{$this->prefix}-*.log");
        
        foreach ($files as $file) {
            if (preg_match('/-(\d{4}-\d{2}-\d{2})\.log$/', $file, $matches)) {
                if ($matches[1] < $cutoffDate) {
                    unlink($file);
                }
            }
        }
    }
    
    // Log file compression (monthly)
    public function compress($month = null) {
        $month = $month ?: date('Y-m');
        $files = glob("{$this->logDir}/{$this->prefix}-{$month}-*.log");
        
        if (empty($files)) {
            return false;
        }
        
        $archiveFile = "{$this->logDir}/{$this->prefix}-{$month}.tar.gz";
        $tar = new PharData($archiveFile);
        
        foreach ($files as $file) {
            $tar->addFile($file, basename($file));
            unlink($file); // Delete original
        }
        
        return true;
    }
}

// Log output with performance monitoring
class PerformanceLogger extends DailyLogger {
    private $startTimes = [];
    
    public function startTimer($label) {
        $this->startTimes[$label] = microtime(true);
    }
    
    public function endTimer($label, $context = []) {
        if (!isset($this->startTimes[$label])) {
            $this->log('WARNING', "Timer '{$label}' was not started");
            return;
        }
        
        $duration = microtime(true) - $this->startTimes[$label];
        unset($this->startTimes[$label]);
        
        $context['duration_ms'] = round($duration * 1000, 2);
        $context['duration_s'] = round($duration, 4);
        
        $this->log('PERF', "Timer '{$label}' completed", $context);
    }
    
    public function logQuery($sql, $params = [], $duration = null) {
        $context = [
            'sql' => $sql,
            'params' => $params,
            'duration_ms' => $duration ? round($duration * 1000, 2) : null
        ];
        
        $this->log('SQL', 'Database query executed', $context);
    }
}

// Usage examples
$logger = new PerformanceLogger();

$logger->startTimer('user_registration');

// User registration processing
$logger->logQuery('INSERT INTO users (name, email) VALUES (?, ?)', ['John Doe', '[email protected]']);

$logger->endTimer('user_registration', ['user_id' => 789]);

// Monthly cleanup (run with cron)
$logger->cleanup(90); // Delete logs older than 90 days
$logger->compress(); // Compress current month's logs