When managing a live PHP project, especially one deployed on a shared server or accessible by multiple developers, monitoring unauthorized changes to files is crucial. Even a single unexpected edit to your codebase can introduce bugs, vulnerabilities, or data loss.
In this guide, you'll learn how to create a secure file monitoring system in PHP that:
Ensures only authorized users can trigger the scan
Let’s build it step by step.
🛡️ 1. Why Monitor File Changes?
There are many practical use cases for tracking file-level changes:
Protect against unauthorized tampering or backdoors
Alert on accidental overwrites or deletions during deployment
Detect file uploads or malware injections
Maintain version consistency across environments
🔐 2. Securing the Monitoring Script
Before you start scanning files, it's important to secure the script itself. Otherwise, someone could run the monitor remotely and flood your inbox with false alerts.
Here’s how to protect the script using a secret key in the URL:
$secretKey = '123456'; // Change this to something complex
if (!isset($_GET['key']) || $_GET['key'] !== $secretKey) {
http_response_code(403);
exit('❌ Unauthorized access');
}
Now only URLs like monitor.php?key=123456 will run the script.
📦 3. Snapshot Concept – The Core Idea
We’ll create a snapshot of the current state of your project using file hashes. This snapshot is stored in a JSON file and compared on each run to detect changes.
This ensures the next run has the most recent state to compare against.
✅ 8. Final Output
echo "Monitoring completed at " . date('Y-m-d H:i:s');
Optionally, you can log this to a file as well for auditing.
🚀 Bonus Tips:
Automate the script using a cron job to run every hour.
Use logging in addition to email for persistent records.
Encrypt or protect your snapshot.json file from public access.
Use real-time notification tools like Telegram or Slack for alerts if desired.
🧠 Conclusion:
By building this monitoring tool in PHP, you've added a strong layer of protection to your project. Whether you're running a business website, a CMS, or an API server, knowing when your files change—along with who triggered it—can save you from disaster. This is a lightweight but powerful alternative to complex DevOps tools, and it's entirely in PHP.
📤 Complete code:
<?php
// Secure the URL with a secret key
$secretKey = '123456'; // Change this to a long, hard-to-guess key
if (!isset($_GET['key']) || $_GET['key'] !== $secretKey) {
http_response_code(403); // Forbidden
exit('❌ Unauthorized access');
}
require_once __DIR__ . '../../account/mailer.php';
// === CONFIGURATION ===
$projectDir = realpath(__DIR__ . '/..');
echo "Project dir: " . $projectDir . "\n";
$snapshotFile = __DIR__ . '/snapshot.json';
$emailList = ['youremail1@gmail.com', 'youremail2@gmail.com'];
// Helper to get IP info
function getIpInfo($ip) {
$info = @file_get_contents("http://ip-api.com/json/{$ip}");
return $info ? json_decode($info, true) : [];
}
// Create a snapshot of current files
function getDirectorySnapshot($dir) {
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
$snapshot = [];
foreach ($iterator as $file) {
if ($file->isFile()) {
$path = $file->getRealPath();
if (basename($path) !== 'snapshot.json') {
$snapshot[$path] = md5_file($path);
}
}
}
return $snapshot;
}
// Load previous snapshot
$previousSnapshot = file_exists($snapshotFile) ? json_decode(file_get_contents($snapshotFile), true) : [];
$currentSnapshot = getDirectorySnapshot($projectDir);
$added = array_diff_key($currentSnapshot, $previousSnapshot);
$deleted = array_diff_key($previousSnapshot, $currentSnapshot);
$modified = [];
foreach ($currentSnapshot as $file => $hash) {
if (isset($previousSnapshot[$file]) && $previousSnapshot[$file] !== $hash) {
$modified[$file] = $hash;
}
}
// Only send email if real changes (excluding only snapshot.json)
if (!empty($added) || !empty($deleted) || !empty($modified)) {
// Get IP and geolocation
$ip = $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN';
$ipInfo = getIpInfo($ip);
$city = $ipInfo['city'] ?? 'Unknown City';
$country = $ipInfo['country'] ?? '';
$location = "$city, $country";
// Start email body
$message = "Changes detected in your project at " . date('Y-m-d H:i:s') . "\n\n";
$message .= "IP: $ip\nLocation: $location\n\n";
// Added Files
if ($added) {
$message .= "🟢 Added Files:\n";
foreach ($added as $file => $hash) {
$message .= "+ $file\n";
}
$message .= "\n";
}
// Modified Files with changed line numbers
if ($modified) {
$message .= "🟡 Modified Files:\n";
foreach ($modified as $file => $hash) {
$lines = [];
$oldLines = file_exists($file) ? @file($file) : [];
$prevHash = isset($previousSnapshot[$file]) ? $previousSnapshot[$file] : '';
if ($prevHash && file_exists($file)) {
// Temp file to compare (simulate previous content)
$tmpFile = tempnam(sys_get_temp_dir(), 'prev_');
file_put_contents($tmpFile, file_get_contents($file));
if (md5_file($tmpFile) !== $prevHash) {
$newLines = @file($file);
foreach ($newLines as $i => $line) {
if (!isset($oldLines[$i]) || $oldLines[$i] !== $line) {
$lines[] = $i + 1;
}
}
unlink($tmpFile);
}
}
$lineStr = $lines ? " [Lines: " . implode(', ', $lines) . "]" : "";
$message .= "- $file$lineStr\n";
}
$message .= "\n";
}
// Deleted Files
if ($deleted) {
$message .= "🔴 Deleted Files:\n";
foreach ($deleted as $file => $hash) {
$message .= "− $file\n";
}
$message .= "\n";
}
// Send alert to each email
foreach ($emailList as $toEmail) {
sendProjectAlert($toEmail, "Project File Changes Detected", $message);
}
}
// Save new snapshot
file_put_contents($snapshotFile, json_encode($currentSnapshot, JSON_PRETTY_PRINT));
echo "Monitoring done.\n";
PHPPHP file change detectionPHP monitor file changesfile monitoring system in PHPPHP email alert file changetrack file changes in PHPdetect file changes using PHPsend email on file change PHP
Zia, founder and CEO of Texvn and Toolx, is a passionate entrepreneur and tech enthusiast. With a strong focus on empowering developers, he creates innovative tools and content, making coding and idea generation easier.
Conversation
Your input fuels progress! Share your tips or experiences on prioritizing mental wellness at work. Let's inspire change together!
Join the discussion and share your insights now!
Comments: 0