PHP code example of andydefer / php-jsonl
1. Go to this page and download the library: Download andydefer/php-jsonl library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
andydefer / php-jsonl example snippets
use AndyDefer\PhpJsonl\Records\LogJsonlRecord;
use AndyDefer\PhpVo\ValueObjects\DateTimeVO;
use AndyDefer\DomainStructures\Utils\StrictDataObject;
$log = new LogJsonlRecord(
time: new DateTimeVO('2026-01-15T14:35:00+00:00'),
level: 'info',
type: 'user_login',
payload: new StrictDataObject(['user_id' => 123, 'username' => 'john_doe']),
);
use AndyDefer\PhpJsonl\Records\CacheJsonlRecord;
$cache = new CacheJsonlRecord(
key: 'user_123',
value: json_encode(['name' => 'John', 'email' => '[email protected] ']),
expires_at: new DateTimeVO('+1 hour'), // null = jamais expiré
);
use AndyDefer\PhpJsonl\Strategies\TemporalPathStrategy;
$strategy = new TemporalPathStrategy('/var/logs');
$service = new JsonlService($strategy, $fileSystem, $context);
use AndyDefer\PhpJsonl\Strategies\KeyBasedPathStrategy;
$strategy = new KeyBasedPathStrategy('/var/cache', hashLevels: 2);
$service = new JsonlService($strategy, $fileSystem, $context);
use AndyDefer\PhpJsonl\JsonlService;
use AndyDefer\PhpJsonl\Contexts\JsonlContext;
use AndyDefer\PhpJsonl\Strategies\TemporalPathStrategy;
use AndyDefer\PhpServices\Services\FileSystemService;
use AndyDefer\PhpServices\Enums\PermissionMode;
// 1. Créer la stratégie de chemin
$strategy = new TemporalPathStrategy('/var/app/logs');
// 2. Créer le service de fichiers
$fileSystem = new FileSystemService();
// 3. Créer le contexte unifié (état)
$context = new JsonlContext();
// 4. Instancier le service
$service = new JsonlService(
pathStrategy: $strategy,
fileSystem: $fileSystem,
context: $context,
defaultBufferSize: 100, // Buffer de 100 entrées
directoryPermission: PermissionMode::DIRECTORY // Permissions 755
);
use AndyDefer\PhpJsonl\Strategies\KeyBasedPathStrategy;
$cacheStrategy = new KeyBasedPathStrategy(
basePath: '/var/app/cache',
hashLevels: 2 // 2 niveaux de hash (16² = 256 dossiers possibles)
);
$cacheService = new JsonlService($cacheStrategy, $fileSystem, $context);
public function write(AbstractRecord $entity, bool $lock = true): void
$log = new LogJsonlRecord(/* ... */);
$service->write($log);
$service->write($log, lock: false); // Sans verrouillage
public function writeBatch(array $entities, bool $lock = true): void
$logs = [/* 100 entrées */];
$service->writeBatch($logs);
public function writeBuffered(AbstractRecord $entity): void
$service->enableBuffer(50); // Buffer de 50 entrées
for ($i = 0; $i < 1000; $i++) {
$service->writeBuffered($log);
// Écriture automatique après 50 entrées
}
$service->flushBuffer(); // Écriture manuelle du reste
public function readAll(string $filePath): array
$lines = $service->readAll('/var/logs/2026-01-15/14.jsonl');
foreach ($lines as $line) {
echo $line['level'] . ': ' . $line['type'] . "\n";
}
public function readLineByLine(string $filePath, callable $callback): void
$service->readLineByLine('/var/logs/large_file.jsonl', function ($line) {
if ($line['level'] === 'error') {
echo "ERREUR: " . $line['type'] . "\n";
}
});
public function getFirstLine(string $filePath): ?array
public function getLastLine(string $filePath): ?array
$first = $service->getFirstLine('/var/logs/app.jsonl');
$last = $service->getLastLine('/var/logs/app.jsonl');
echo "Premier log: " . $first['type'] . "\n";
echo "Dernier log: " . $last['type'] . "\n";
public function search(string $filePath, callable $filter): array
$errors = $service->search('/var/logs/14.jsonl', function ($line) {
return $line['level'] === 'error';
});
foreach ($errors as $error) {
echo $error['time'] . ': ' . $error['type'] . "\n";
}
public function searchMultiple(array $filePaths, callable $filter): array
$files = [
'/var/logs/2026-01-15/14.jsonl',
'/var/logs/2026-01-15/15.jsonl',
'/var/logs/2026-01-15/16.jsonl',
];
$payments = $service->searchMultiple($files, function ($line) {
return $line['type'] === 'payment_success';
});
echo "Nombre de paiements: " . count($payments);
public function enableBuffer(int $size = 100): void
$service->enableBuffer(200); // Écrit toutes les 200 entrées
public function disableBuffer(): void
$service->disableBuffer(); // Écriture immédiate
public function flushBuffer(?string $filePath = null): void
$service->writeBuffered($log1);
$service->writeBuffered($log2);
$service->flushBuffer(); // Écrit les 2 entrées
public function onFlush(callable $callback): void
$service->onFlush(function (string $filePath, int $count) {
echo "Flush: {$count} lignes écrites dans {$filePath}\n";
});
public function cleanOlderThan(int $days, string $basePath): int
$deleted = $service->cleanOlderThan(30, '/var/logs');
echo "Supprimé {$deleted} fichiers de logs de plus de 30 jours";
public function cleanExpired(string $basePath, callable $isExpired): int
$deleted = $service->cleanExpired('/var/cache', function ($line) {
if (!isset($line['expires_at'])) {
return false;
}
$expiresAt = new DateTimeVO($line['expires_at']);
$now = new DateTimeVO();
return $expiresAt->isBefore($now);
});
echo "Supprimé {$deleted} entrées de cache expirées";
public function cleanByPattern(string $pattern): int
$pattern = '/var/logs/2026-01-15/*.jsonl';
$deleted = $service->cleanByPattern($pattern);
echo "Supprimé {$deleted} fichiers";
public function dryRun(string $basePath, callable $filter): array
$filesToDelete = $service->dryRun('/var/logs', function ($file) {
return filemtime($file) < strtotime('-90 days');
});
echo "Fichiers qui seraient supprimés:\n";
foreach ($filesToDelete as $file) {
echo " - {$file}\n";
}
if (count($filesToDelete) > 0) {
$confirm = readline("Procéder à la suppression? (y/n): ");
if ($confirm === 'y') {
$deleted = $service->cleanOlderThan(90, '/var/logs');
echo "{$deleted} fichiers supprimés\n";
}
}
public function clear(string $basePath): int
$deleted = $service->clear('/var/cache');
echo "Cache vidé: {$deleted} fichiers supprimés";
public function acquire(string $filePath, int $timeout = 5): bool
if ($service->acquire('/var/logs/app.jsonl', timeout: 3)) {
try {
// Opérations exclusives
$service->append($filePath, $data);
} finally {
$service->release('/var/logs/app.jsonl');
}
}
public function release(string $filePath): void
public function executeWithLock(string $filePath, callable $callback): mixed
$result = $service->executeWithLock('/shared/data.jsonl', function () use ($service) {
$existing = $service->readAll('/shared/data.jsonl');
$newData = ['timestamp' => time(), 'value' => rand(1, 100)];
$existing[] = $newData;
$content = '';
foreach ($existing as $item) {
$content .= json_encode($item) . "\n";
}
file_put_contents('/shared/data.jsonl', $content);
return count($existing);
});
echo "Total après opération atomique: {$result}";
public function isLocked(string $filePath): bool
if ($service->isLocked('/var/logs/app.jsonl')) {
echo "Fichier verrouillé, réessayez plus tard";
} else {
$service->acquire('/var/logs/app.jsonl');
// ...
}
public function isExpired(CacheJsonlRecord $record): bool
$record = CacheJsonlRecord::fromArray($line);
if ($service->isExpired($record)) {
echo "Cache expiré, rafraîchissement nécessaire";
} else {
echo "Cache valide: " . $record->value;
}
public function decodeCacheValue(string $encodedValue, string $typeString): StrictDataObject
$cachedData = $service->readAll('/cache/a/b/user_123.jsonl');
if (!empty($cachedData)) {
$decoded = $service->decodeCacheValue(
$cachedData[0]['value'],
$cachedData[0]['value_type']
);
echo "Nom: " . $decoded->name;
echo "Email: " . $decoded->email;
}
public function getFilePath(AbstractRecord $entity): string
$record = new LogJsonlRecord(/* ... */);
$path = $service->getFilePath($record);
echo "Le log sera stocké dans: {$path}";
public function getFilesToScan(AbstractRecord $query): array
$query = new TemporalLogQueryRecord(
from: new DateTimeVO('2026-01-15T10:00:00+00:00'),
to: new DateTimeVO('2026-01-15T14:00:00+00:00'),
);
$files = $service->getFilesToScan($query);
echo "Fichiers à scanner: " . count($files);
public function getContext(): JsonlContext
$context = $service->getContext();
if ($context->hasError()) {
echo "Erreur: " . $context->getLastError();
}
echo "Total lignes traitées: " . $context->getTotalLinesProcessed();
public function resetProcessingState(): self
$service->resetProcessingState(); // Réinitialise les stats
public function setPathStrategy(JsonlPathStrategyInterface $pathStrategy): void
// Passer de logs à cache
$service->setPathStrategy($keyBasedStrategy);
$service->enableBuffer(1000);
$service->onFlush(function ($path, $count) {
echo "[PERF] Écriture de {$count} logs dans {$path}\n";
});
for ($i = 0; $i < 100000; $i++) {
$service->writeBuffered(new LogJsonlRecord(
time: new DateTimeVO(),
level: 'info',
type: 'api_request',
payload: new StrictDataObject(['request_id' => $i]),
));
}
$service->flushBuffer();
class UserCache
{
public function __construct(private JsonlService $cache) {}
public function get(int $userId): ?array
{
$key = "user_{$userId}";
$path = $this->cache->getFilePath(new CacheJsonlRecord(key: $key, value: '', expires_at: null));
if (!$this->cache->fileExists($path)) {
return null;
}
$lines = $this->cache->readAll($path);
$record = CacheJsonlRecord::fromArray($lines[0]);
if ($this->cache->isExpired($record)) {
$this->cache->delete($path);
return null;
}
return $this->cache->decodeCacheValue($record->value, $record->value_type)->toArray();
}
public function set(int $userId, array $data, int $ttlSeconds = 3600): void
{
$record = new CacheJsonlRecord(
key: "user_{$userId}",
value: json_encode($data),
expires_at: new DateTimeVO("+{$ttlSeconds} seconds"),
);
$this->cache->write($record);
}
}
function analyzeLogs(JsonlService $service, string $logDir): array
{
$stats = ['total' => 0, 'errors' => 0, 'warnings' => 0];
// Parcourir tous les fichiers du dernier jour
$today = (new DateTime())->format('Y-m-d');
$hourFiles = [];
for ($hour = 0; $hour < 24; $hour++) {
$path = "{$logDir}/{$today}/{$hour}.jsonl";
if ($service->fileExists($path)) {
$hourFiles[] = $path;
}
}
// Analyser ligne par ligne (économie mémoire)
foreach ($hourFiles as $file) {
$service->readLineByLine($file, function ($line) use (&$stats) {
$stats['total']++;
if ($line['level'] === 'error') {
$stats['errors']++;
} elseif ($line['level'] === 'warning') {
$stats['warnings']++;
}
});
}
return $stats;
}
class LogRotator
{
public function __construct(
private JsonlService $logs,
private JsonlService $archive,
private int $retentionDays = 30
) {}
public function rotate(): void
{
// Simuler pour voir ce qui serait supprimé
$toDelete = $this->logs->dryRun('/var/logs', function ($file) {
return filemtime($file) < strtotime("-{$this->retentionDays} days");
});
if (empty($toDelete)) {
echo "Aucun log à archiver\n";
return;
}
echo "Fichiers à archiver ({$this->retentionDays} jours):\n";
foreach ($toDelete as $file) {
echo " - {$file}\n";
}
$confirm = readline("Archiver ces fichiers? (y/n): ");
if ($confirm !== 'y') {
echo "Opération annulée\n";
return;
}
// Archiver avant suppression
foreach ($toDelete as $file) {
$content = $this->logs->readAll($file);
$archiveFile = str_replace('/logs/', '/archive/', $file);
$this->archive->writeBatch($content);
echo "Archivé: {$file} → {$archiveFile}\n";
}
// Supprimer les originaux
$deleted = $this->logs->cleanOlderThan($this->retentionDays, '/var/logs');
echo "Supprimé {$deleted} fichiers\n";
}
}
class CounterService
{
public function __construct(private JsonlService $storage) {}
public function increment(string $counterName): int
{
$filePath = "/counters/{$counterName}.jsonl";
return $this->storage->executeWithLock($filePath, function () use ($filePath, $counterName) {
$value = 0;
if ($this->storage->fileExists($filePath)) {
$lastLine = $this->storage->getLastLine($filePath);
$value = $lastLine['value'] ?? 0;
}
$newValue = $value + 1;
$record = new LogJsonlRecord(
time: new DateTimeVO(),
level: 'info',
type: 'counter_increment',
payload: new StrictDataObject([
'counter' => $counterName,
'value' => $newValue,
'increment' => 1,
]),
);
$this->storage->write($record, lock: false); // Déjà locké
return $newValue;
});
}
}
$service->write($record);
$context = $service->getContext();
if ($context->hasError()) {
echo "Erreur: " . $context->getLastError() . "\n";
echo "Opération: " . $context->getCurrentOperation()->value . "\n";
echo "Fichiers traités: " . implode(', ', $context->getProcessedFiles()->toArray()) . "\n";
echo "Lignes traitées: " . $context->getTotalLinesProcessed() . "\n";
}
// Réinitialiser pour la prochaine opération
$service->resetProcessingState();
$service->enableBuffer(1000); // 1000 logs avant écriture disque
$service->readLineByLine($path, $callback); // Pas de chargement mémoire
$toDelete = $service->dryRun($path, $filter); // Vérifier avant de supprimer
$service->write($record, lock: false); // Pas de lock si écriture unique
// Initialisation
$strategy = new TemporalPathStrategy('/var/logs');
$context = new JsonlContext();
$service = new JsonlService($strategy, new FileSystemService(), $context);
// Écrire un log
$service->write(new LogJsonlRecord(
time: new DateTimeVO(),
level: 'info',
type: 'user_login',
payload: new StrictDataObject(['user_id' => 123]),
));
// Lire les logs
$logs = $service->readAll('/var/logs/2026-01-15/14.jsonl');
// Rechercher des erreurs
$errors = $service->search('/var/logs/14.jsonl', fn($line) => $line['level'] === 'error');
// Nettoyer les vieux logs
$service->cleanOlderThan(30, '/var/logs');
// Accéder au contexte
$context = $service->getContext();
echo "Total lignes: " . $context->getTotalLinesProcessed();
// Réinitialiser l'état
$service->resetProcessingState();
bash
composer jsonl
{"time":"2026-01-15T14:35:00+00:00","level":"info","type":"user_login"}
{"time":"2026-01-15T14:36:00+00:00","level":"info","type":"user_login"}
{"time":"2026-01-15T14:37:00+00:00","level":"error","type":"payment_failed"}
/var/logs/
├── 2026-01-15/
│ ├── 00.jsonl
│ ├── 01.jsonl
│ └── ...
│ └── 23.jsonl
├── 2026-01-16/
│ └── ...