PHP Integration
Complete guide to integrating CronMonitor with your PHP applications.
Basic Integration #
Using file_get_contents() #
Simplest method for basic use cases:
<?php
// Your cron job logic
performBackup();
// Ping CronMonitor
$pingUrl = 'https://cronmonitor.io/ping/your-monitor-id';
file_get_contents($pingUrl);
Using cURL (Recommended) #
More reliable with timeout and error handling:
<?php
function pingCronMonitor($monitorId) {
$url = "https://cronmonitor.io/ping/{$monitorId}";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode === 200;
}
// Your cron job
try {
performBackup();
pingCronMonitor('your-monitor-id');
} catch (Exception $e) {
// Don't ping on failure
error_log('Backup failed: ' . $e->getMessage());
}
With Guzzle HTTP Client #
If you're using Guzzle in your project:
<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
function pingCronMonitor(string $monitorId): bool
{
$client = new Client([
'timeout' => 10,
'verify' => true, // SSL verification
]);
try {
$response = $client->get("https://cronmonitor.io/ping/{$monitorId}");
return $response->getStatusCode() === 200;
} catch (GuzzleException $e) {
error_log('CronMonitor ping failed: ' . $e->getMessage());
return false;
}
}
// Usage
performBackup();
pingCronMonitor('your-monitor-id');
Symfony Integration #
Command with CronMonitor #
<?php
// src/Command/BackupDatabaseCommand.php
namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
#[AsCommand(
name: 'app:backup-database',
description: 'Backup database with CronMonitor integration'
)]
class BackupDatabaseCommand extends Command
{
public function __construct(
private HttpClientInterface $httpClient,
private string $cronMonitorId
) {
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
try {
// Your backup logic
$this->performBackup();
$output->writeln('Backup completed successfully');
// Ping CronMonitor
$this->pingCronMonitor();
return Command::SUCCESS;
} catch (\Exception $e) {
$output->writeln('Backup failed: ' . $e->getMessage());
return Command::FAILURE;
}
}
private function performBackup(): void
{
// Your backup implementation
}
private function pingCronMonitor(): void
{
try {
$this->httpClient->request('GET',
"https://cronmonitor.io/ping/{$this->cronMonitorId}",
['timeout' => 10]
);
} catch (\Exception $e) {
// Log but don't fail the command
error_log('CronMonitor ping failed: ' . $e->getMessage());
}
}
}
Configuration (services.yaml) #
# config/services.yaml
services:
App\Command\BackupDatabaseCommand:
arguments:
$cronMonitorId: '%env(CRONMONITOR_BACKUP_ID)%'
Environment Variables #
# .env
CRONMONITOR_BACKUP_ID=abc123def456
Crontab Entry #
# Crontab
0 2 * * * cd /var/www/app && php bin/console app:backup-database >> /var/log/backup.log 2>&1
Laravel Integration #
Artisan Command #
<?php
// app/Console/Commands/BackupDatabase.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class BackupDatabase extends Command
{
protected $signature = 'backup:database';
protected $description = 'Backup database with CronMonitor';
public function handle()
{
try {
// Your backup logic
$this->performBackup();
$this->info('Backup completed successfully');
// Ping CronMonitor
$this->pingCronMonitor();
return 0;
} catch (\Exception $e) {
$this->error('Backup failed: ' . $e->getMessage());
return 1;
}
}
private function performBackup()
{
// Your backup implementation
}
private function pingCronMonitor()
{
$monitorId = config('services.cronmonitor.backup_id');
try {
Http::timeout(10)
->get("https://cronmonitor.io/ping/{$monitorId}");
} catch (\Exception $e) {
\Log::warning('CronMonitor ping failed', [
'error' => $e->getMessage()
]);
}
}
}
Laravel Scheduler #
<?php
// app/Console/Kernel.php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
protected function schedule(Schedule $schedule)
{
$schedule->command('backup:database')
->daily()
->at('02:00')
->timezone('Europe/Warsaw');
}
}
Configuration #
<?php
// config/services.php
return [
'cronmonitor' => [
'backup_id' => env('CRONMONITOR_BACKUP_ID'),
'cleanup_id' => env('CRONMONITOR_CLEANUP_ID'),
],
];
Reusable Service #
<?php
// app/Services/CronMonitorService.php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class CronMonitorService
{
public function ping(string $monitorKey): bool
{
$monitorId = config("services.cronmonitor.{$monitorKey}");
if (empty($monitorId)) {
Log::warning("CronMonitor ID not configured for: {$monitorKey}");
return false;
}
try {
$response = Http::timeout(10)
->retry(3, 100)
->get("https://cronmonitor.io/ping/{$monitorId}");
return $response->successful();
} catch (\Exception $e) {
Log::error('CronMonitor ping failed', [
'monitor' => $monitorKey,
'error' => $e->getMessage()
]);
return false;
}
}
}
// Usage in command:
public function handle(CronMonitorService $cronMonitor)
{
$this->performBackup();
$cronMonitor->ping('backup_id');
}
Advanced Patterns #
Ping with Execution Time #
Send execution duration as query parameter:
<?php
$startTime = microtime(true);
// Your job
performHeavyTask();
$executionTime = round(microtime(true) - $startTime, 2);
// Ping with execution time
$url = "https://cronmonitor.io/ping/{$monitorId}?duration={$executionTime}";
file_get_contents($url);
Ping with Status Message #
<?php
function pingWithStatus($monitorId, $status, $message = '') {
$url = "https://cronmonitor.io/ping/{$monitorId}";
$url .= "?status={$status}";
if ($message) {
$url .= "&message=" . urlencode($message);
}
file_get_contents($url);
}
// Usage
try {
$result = performBackup();
pingWithStatus('abc123', 'success', 'Backed up 1.2GB');
} catch (Exception $e) {
pingWithStatus('abc123', 'failed', $e->getMessage());
}
Wrapper Function #
Create a reusable wrapper:
<?php
class CronMonitor
{
private string $monitorId;
private float $startTime;
public function __construct(string $monitorId)
{
$this->monitorId = $monitorId;
$this->startTime = microtime(true);
}
public function success(string $message = ''): void
{
$this->ping('success', $message);
}
public function failure(string $message = ''): void
{
$this->ping('failure', $message);
}
private function ping(string $status, string $message): void
{
$duration = round(microtime(true) - $this->startTime, 2);
$url = "https://cronmonitor.io/ping/{$this->monitorId}";
$url .= "?status={$status}&duration={$duration}";
if ($message) {
$url .= "&message=" . urlencode($message);
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_exec($ch);
curl_close($ch);
}
}
// Usage
$monitor = new CronMonitor('abc123def456');
try {
performBackup();
$monitor->success('Backup completed: 1.2GB');
} catch (Exception $e) {
$monitor->failure($e->getMessage());
throw $e;
}
Error Handling Best Practices #
Don't Let Monitoring Fail Your Job #
<?php
// β Bad: Monitoring failure breaks the job
performBackup();
file_get_contents($pingUrl); // Throws exception if network fails
// β
Good: Job completes even if monitoring fails
try {
performBackup();
file_get_contents($pingUrl);
} catch (Exception $e) {
// Log but continue
error_log('CronMonitor ping failed: ' . $e->getMessage());
}
Timeout Configuration #
<?php
// Always set timeouts
$context = stream_context_create([
'http' => [
'timeout' => 10, // 10 seconds max
'ignore_errors' => true
]
]);
file_get_contents($pingUrl, false, $context);
Testing #
Unit Test Example (PHPUnit) #
<?php
use PHPUnit\Framework\TestCase;
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
class CronMonitorTest extends TestCase
{
public function testSuccessfulPing()
{
// Mock HTTP response
$mock = new MockHandler([
new Response(200, [], 'OK'),
]);
$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);
$response = $client->get('https://cronmonitor.io/ping/test123');
$this->assertEquals(200, $response->getStatusCode());
}
}
Video Tutorial #
πΊ Watch: "PHP Integration - Complete Guide" (8 minutes)
PHP Integration
Video coming soon
Topics covered:
- Basic integration methods (1:30)
- Symfony integration (2:30)
- Laravel integration (2:30)
- Best practices (1:30)
Complete Example #
Here's a production-ready example:
<?php
/**
* Production-ready backup script with CronMonitor
*/
class DatabaseBackup
{
private string $monitorId;
private float $startTime;
public function __construct(string $monitorId)
{
$this->monitorId = $monitorId;
$this->startTime = microtime(true);
}
public function run(): void
{
try {
echo "Starting backup...\n";
// Perform backup
$this->createBackup();
// Upload to S3
$this->uploadToS3();
// Cleanup old backups
$this->cleanupOldBackups();
echo "Backup completed successfully\n";
// Notify CronMonitor of success
$this->notifySuccess();
} catch (\Exception $e) {
echo "Backup failed: {$e->getMessage()}\n";
// Notify CronMonitor of failure
$this->notifyFailure($e->getMessage());
throw $e;
}
}
private function createBackup(): void
{
exec('mysqldump -u root database > backup.sql', $output, $returnCode);
if ($returnCode !== 0) {
throw new \Exception('mysqldump failed');
}
}
private function uploadToS3(): void
{
// S3 upload logic
}
private function cleanupOldBackups(): void
{
// Cleanup logic
}
private function notifySuccess(): void
{
$duration = round(microtime(true) - $this->startTime, 2);
$size = round(filesize('backup.sql') / 1024 / 1024, 2);
$this->ping("success", "Backup completed: {$size}MB in {$duration}s");
}
private function notifyFailure(string $error): void
{
$duration = round(microtime(true) - $this->startTime, 2);
$this->ping("failure", "Failed after {$duration}s: {$error}");
}
private function ping(string $status, string $message): void
{
$url = "https://cronmonitor.io/ping/{$this->monitorId}";
$url .= "?status={$status}&message=" . urlencode($message);
try {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_FOLLOWLOCATION => true,
]);
curl_exec($ch);
curl_close($ch);
} catch (\Exception $e) {
error_log('CronMonitor ping failed: ' . $e->getMessage());
}
}
}
// Run backup
$backup = new DatabaseBackup(getenv('CRONMONITOR_BACKUP_ID'));
$backup->run();