### Implement Pagination for Audit Log Queries Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Configures pagination for audit log queries by specifying the limit of results per page and the offset for the starting record. This example fetches the first 25 'Product' audit entries. ```php $page1 = $this->auditReader ->forEntity(Product::class) ->limit(25) ->offset(0) ->getResults(); ``` -------------------------------- ### Install AuditTrailBundle using Composer Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md This command installs the AuditTrailBundle package using Composer. It is the first step in setting up the bundle in a Symfony project. ```bash composer require rcsofttech/audit-trail-bundle ``` -------------------------------- ### Build Custom Audit Queries (Updates, Deletions, Time-based) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Illustrates building custom audit queries using a fluent API. Examples include finding recent entity updates, filtering deletions by a specific user, and applying time-based constraints. ```php //Find all updates to User entities in the last 30 days $recentUpdates = $this->auditReader ->forEntity(User::class) ->updates() ->since(new \DateTimeImmutable('-30 days')) ->limit(50) ->getResults(); //Find all deletions by a specific admin use Rcsofttech\AuditTrailBundle\Entity\AuditLog; $deletions = $this->auditReader ->byUser(adminUserId: 1) ->action( AuditLog::ACTION_DELETE, AuditLog::ACTION_SOFT_DELETE ) ->getResults(); ``` -------------------------------- ### HTTP Request with Signature Header Example Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-transports.md Illustrates an example HTTP POST request to an audit API, including the 'X-Signature' header for payload authenticity when integrity checks are enabled. The signature is an HMAC of the JSON body. ```http POST /api/logs HTTP/1.1 X-Signature: a1b2c3d4... Content-Type: application/json { ... } ``` -------------------------------- ### Working with Audit Diffs and Field Changes Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Demonstrates how to inspect the differences (diff) between old and new values for an audit entry. It shows how to retrieve the entire diff, check if a specific field changed, and get old/new values for a field. ```php $entry = $this->auditReader ->forEntity(User::class, '123') ->updates() ->getFirstResult(); if ($entry) { $diff = $entry->getDiff(); /* * Example: * [ * 'name' => ['old' => 'John', 'new' => 'Jane'], * 'email' => ['old' => 'a@x.com', 'new' => 'b@x.com'] * ] */ if ($entry->hasFieldChanged('email')) { $oldEmail = $entry->getOldValue('email'); $newEmail = $entry->getNewValue('email'); echo "Email changed from $oldEmail to $newEmail"; } $changedFields = $entry->getChangedFields(); // ['name', 'email'] } ``` -------------------------------- ### Check for Existence of Matching Audit Records Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Efficiently checks if any audit log records matching specific criteria exist without retrieving the full dataset. This example checks if there are any 'delete' actions for 'User' entities. ```php $hasDeletes = $this->auditReader ->forEntity(User::class) ->deletes() ->exists(); ``` -------------------------------- ### Add Messenger Stamps to Audit Messages with PHP Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Utilize the AuditMessageStampEvent to add custom stamps, such as DelayStamp or AmqpStamp, to audit messages before they are sent via the Messenger transport. This example adds a 5-second delay. ```php namespace App\EventSubscriber; use Rcsofttech\AuditTrailBundle\Event\AuditMessageStampEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Messenger\Stamp\DelayStamp; class AuditStampSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ AuditMessageStampEvent::class => 'onAuditMessageStamp', ]; } public function onAuditMessageStamp(AuditMessageStampEvent $event): void { // Add a 5-second delay to all audit messages $event->addStamp(new DelayStamp(5000)); } } ``` -------------------------------- ### Querying Audit Logs within a Date Range Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Retrieves audit log entries for a specific entity within a defined date range. This example fetches all audits for 'Order' entities between January 1st and December 31st, 2024. ```php $audits = $this->auditReader ->forEntity(Order::class) ->between( new \DateTimeImmutable('2024-01-01'), new \DateTimeImmutable('2024-12-31') ) ->getResults(); ``` -------------------------------- ### Cross-Platform Audit Log Message Serialization (JSON) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt This example shows the structure of an audit log message serialized into JSON format. This format is language-agnostic, allowing audit logs to be consumed by any application. It includes details about the entity, action, changes, user, and context. ```json { "entity_class": "App\\Entity\\User", "entity_id": "123", "action": "update", "old_values": { "email": "old@example.com" }, "new_values": { "email": "new@example.com" }, "changed_fields": ["email"], "user_id": "42", "username": "admin", "ip_address": "127.0.0.1", "user_agent": "Mozilla/5.0...", "transaction_hash": "a1b2c3d4...", "signature": "hmac-signature...", "context": { "app_version": "1.0.0", "impersonation": { "impersonator_id": "1", "impersonator_username": "superadmin" } }, "created_at": "2024-01-20T12:00:00+00:00" } ``` -------------------------------- ### Filter Audit Log Collections in Memory Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Applies in-memory filtering to a collection of audit logs. This example filters the previously fetched 'Order' audits to include only those where the 'price' field has changed. ```php $priceChanges = $audits->filter( fn ($entry) => $entry->hasFieldChanged('price') ); ``` -------------------------------- ### Get Complete Audit History for an Entity Instance Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Retrieves all audit log entries for a specific entity instance. It iterates through the history, displaying action, entity name, user, and timestamp for each entry. ```php $user = $userRepository->find(123); $history = $this->auditReader->getHistoryFor($user); foreach ($history as $entry) { printf( "%s: %s by %s at %s\n", $entry->getAction(), // create, update, delete $entry->getEntityShortName(), // User $entry->getUsername(), // admin@example.com $entry->getCreatedAt()->format('Y-m-d H:i:s') ); } ``` -------------------------------- ### Automatically Add Messenger Stamps via Event Subscriber (PHP) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-transports.md Provides an example of an event subscriber that listens for AuditMessageStampEvent to automatically add Messenger stamps, like DelayStamp, to audit log messages before they are dispatched. This is the recommended approach for transport-specific stamps. ```php namespace App\EventSubscriber; use Rcsofttech\AuditTrailBundle\Event\AuditMessageStampEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Messenger\Stamp\DelayStamp; class AuditMessengerSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ AuditMessageStampEvent::class => 'onAuditMessageStamp', ]; } public function onAuditMessageStamp(AuditMessageStampEvent $event): void { // Add a 5-second delay to all audit logs sent via Queue $event->addStamp(new DelayStamp(5000)); } } ``` -------------------------------- ### Find Audit Updates for a Specific Field Change Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Filters audit logs to find updates where a particular field has been modified. This example specifically looks for changes to the 'email' field in User entities. ```php $emailChanges = $this->auditReader ->forEntity(User::class) ->updates() ->changedField('email') ->getResults(); ``` -------------------------------- ### Group Audit Log Collections by Property Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Groups a collection of audit logs based on specific properties. Examples include grouping by action type (create, update, delete) and by entity class name. ```php $byAction = $audits->groupByAction(); // ['create' => [...], 'update' => [...], 'delete' => [...] $byEntity = $audits->groupByEntity(); // ['App\Entity\Order' => [...]] ``` -------------------------------- ### Set up Database Schema for Doctrine Transport Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md These commands are used to generate and apply database migrations when using the default Doctrine Transport. This ensures the necessary tables for storing audit logs are created. ```bash php bin/console make:migration php bin/console doctrine:migrations:migrate ``` -------------------------------- ### Audit Trail Bundle CLI Commands (Bash) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Lists various command-line interface commands for managing audit logs within the Audit Trail Bundle. Includes functionalities for listing logs with filters, purging old logs, exporting logs to different formats, viewing entity differences, reverting entity states, and verifying log integrity. ```bash # List audit logs with filters php bin/console audit:list --entity=User --action=update --limit=50 php bin/console audit:list --entity=Product --action=create --limit=100 # Purge old logs php bin/console audit:purge --before="30 days ago" --force php bin/console audit:purge --before="2023-01-01" --force # Export logs to file php bin/console audit:export --format=json --output=audits.json php bin/console audit:export --format=csv --output=audits.csv # View diff for an entity php bin/console audit:diff User 42 php bin/console audit:diff Product 123 # Revert entity to previous state php bin/console audit:revert 123 php bin/console audit:revert 123 --dry-run php bin/console audit:revert 123 --context='{"reason": "Recovery", "ticket": "T-101"}' # Verify audit log integrity (detect tampering) php bin/console audit:verify-integrity ``` -------------------------------- ### Inject AuditReader Service in Symfony Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Demonstrates how to inject the AuditReaderInterface into a Symfony controller using constructor property promotion. This allows access to the audit log querying capabilities. ```php use Rcsofttech\AuditTrailBundle\Contract\AuditReaderInterface; class UserController extends AbstractController { public function __construct( private readonly AuditReaderInterface $auditReader ) {} } ``` -------------------------------- ### List Audit Logs via CLI Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Command to list audit logs filtered by entity, action, and limit. Useful for quickly reviewing specific audit trails. ```bash php bin/console audit:list --entity=User --action=update --limit=50 ``` -------------------------------- ### Configure Audit Trail Bundle Settings Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md This configuration file sets up the global parameters for the Audit Trail Bundle. It allows enabling/disabling the bundle, defining ignored properties and entities, setting log retention, tracking context, configuring various transports (Doctrine, HTTP, Queue), and managing integrity checks for audit logs. ```yaml audit_trail: # Enable or disable the bundle globally enabled: true # Global list of properties to ignore (e.g., timestamps) ignored_properties: ['updatedAt', 'updated_at', 'password', 'token'] # Global list of entities to ignore ignored_entities: [] # Retention period for database logs (in days) retention_days: 365 # Context tracking track_ip_address: true track_user_agent: true # enable or disable delete tracking enable_hard_delete: true enable_soft_delete: true soft_delete_field: 'deletedAt' transports: # Store logs in the local database doctrine: true # Send logs to an external API http: enabled: false endpoint: 'https://audit-service.internal/api/logs' # Dispatch logs to a message queue queue: enabled: false bus: 'messenger.bus.default' # Optional: specify a custom bus # Integrity & Signing # ------------------- # Enable cryptographic signing of audit logs to prevent tampering. integrity: enabled: true secret: '%env(AUDIT_INTEGRITY_SECRET)%' algorithm: 'sha256' # Transaction Safety & Performance # -------------------------------- # true (Default): Audits are sent AFTER the transaction commits (postFlush). # - Pros: High performance, non-blocking. Main transaction succeeds even if audit fails. # - Cons: Small risk of "data without audit" if app crashes between commit and audit. # - Recommended for: External transports (HTTP, Queue). # # false: Audits are sent DURING the transaction (onFlush). # - Pros: Strict atomicity. Data and audit are committed together. # - Cons: Slower. If audit transport fails, the entire transaction rolls back. # - Recommended for: Doctrine transport (when strict compliance is required). defer_transport_until_commit: true # If true, an exception in the transport will stop execution (and rollback if defer=false). # If false (default), transport errors are logged but execution continues. fail_on_transport_error: false ``` -------------------------------- ### View Audit Log Differences via CLI Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Command to display the differences between two versions of an entity's audit trail, identified by entity name and ID. ```bash php bin/console audit:diff User 42 ``` -------------------------------- ### Revert Product Entity Changes with Audit Trail Bundle (PHP) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Demonstrates how to use the AuditReverterInterface to revert changes to a Product entity. It includes a dry run to preview changes and an actual revert with custom context. Requires the AuditReverterInterface and AuditReaderInterface services. ```php auditReader ->forEntity(Product::class) ->getFirstResult(); if (!$entry) { throw new \RuntimeException('Audit log not found'); } $auditLog = $entry->getAuditLog(); // Dry run - preview changes without applying $previewChanges = $this->auditReverter->revert( $auditLog, dryRun: true, force: false, context: [] ); echo "Preview: Would apply these changes:\n"; print_r($previewChanges); // Actually apply the revert with custom context $appliedChanges = $this->auditReverter->revert( $auditLog, dryRun: false, force: false, context: [ 'reason' => 'Accidental deletion recovery', 'ticket_id' => 'TICKET-456', 'approved_by' => 'admin@example.com', ] ); // The bundle automatically adds 'reverted_log_id' to the new audit log context return $appliedChanges; } } // CLI usage: // php bin/console audit:revert 123 // php bin/console audit:revert 123 --dry-run // php bin/console audit:revert 123 --context='{"reason": "Recovery", "ticket": "T-101"}' ``` -------------------------------- ### Audit Trail Bundle Configuration Reference (YAML) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Provides a complete YAML configuration for the Audit Trail Bundle, detailing options for enabling/disabling the bundle, ignoring properties and entities, log retention, table naming, context tracking, delete tracking, transport methods (database, HTTP, queue), integrity checks, and transaction safety. ```yaml # config/packages/audit_trail.yaml audit_trail: # Enable or disable the bundle globally enabled: true # Global list of properties to ignore (e.g., timestamps) ignored_properties: ['updatedAt', 'updated_at', 'password', 'token'] # Global list of entities to ignore entirely ignored_entities: [] # Retention period for database logs (in days) retention_days: 365 # Table naming customization table_prefix: '' table_suffix: '' timezone: 'UTC' # Context tracking options track_ip_address: true track_user_agent: true # Delete tracking enable_hard_delete: true enable_soft_delete: true soft_delete_field: 'deletedAt' # Transport configuration transports: # Store logs in the local database (default) doctrine: true # Send logs to an external API http: enabled: false endpoint: 'https://audit-service.internal/api/logs' headers: 'Authorization': 'Bearer your-api-token' 'X-App-Name': 'MySymfonyApp' timeout: 10 # Dispatch logs to a message queue queue: enabled: false bus: 'messenger.bus.default' api_key: null # Integrity & Signing integrity: enabled: true secret: '%env(AUDIT_INTEGRITY_SECRET)%' algorithm: 'sha256' # sha256, sha384, sha512 # Transaction Safety & Performance # true: Audits sent AFTER transaction commits (high performance, non-blocking) # false: Audits sent DURING transaction (strict atomicity, slower) defer_transport_until_commit: true # If true, transport errors will stop execution (and rollback if defer=false) fail_on_transport_error: false # Fallback to database if HTTP/Queue transport fails fallback_to_database: true ``` -------------------------------- ### Query Audit Logs Programmatically with AuditReaderInterface (PHP) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Shows how to use the AuditReaderInterface to query audit logs programmatically. This interface offers a fluent API for filtering, pagination, and retrieving audit data for specific entities, actions, users, or time ranges. ```php auditReader->getHistoryFor($user); foreach ($history as $entry) { printf( "%s: %s by %s at %s\n", $entry->getAction(), // create, update, delete $entry->getEntityShortName(), // User $entry->getUsername(), // admin@example.com $entry->getCreatedAt()->format('Y-m-d H:i:s') ); } return new Response('OK'); } public function getRecentUpdates(): Response { // Find all updates to User entities in the last 30 days $recentUpdates = $this->auditReader ->forEntity(User::class) ->updates() ->since(new \DateTimeImmutable('-30 days')) ->limit(50) ->getResults(); // Find all deletions by a specific admin $deletions = $this->auditReader ->byUser(userId: '1') ->action( AuditLog::ACTION_DELETE, AuditLog::ACTION_SOFT_DELETE ) ->getResults(); // Find everything in a single transaction $transactionAudits = $this->auditReader ->byTransaction('019b5aca-60ed-70bf-b139-255aa96c96cb') ->getResults(); // Find updates where a specific field was changed $emailChanges = $this->auditReader ->forEntity(User::class) ->updates() ->changedField('email') ->getResults(); // Query with date range $yearAudits = $this->auditReader ->forEntity(Product::class) ->between( new \DateTimeImmutable('2024-01-01'), new \DateTimeImmutable('2024-12-31') ) ->getResults(); // Check if records exist $hasDeletes = $this->auditReader ->forEntity(User::class) ->deletes() ->exists(); return new Response('OK'); } } ``` -------------------------------- ### Analyze Field Diffs with AuditEntry in PHP Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Demonstrates how to use the AuditEntry class to retrieve and analyze field-level differences (diffs) between old and new values for an entity. It covers checking if a field has changed, accessing old and new values, and identifying the type of audit action performed. ```php auditReader ->forEntity(User::class, $entityId) ->updates() ->getFirstResult(); if ($entry) { // Get full diff with old and new values $diff = $entry->getDiff(); // Returns: [ // 'name' => ['old' => 'John', 'new' => 'Jane'], // 'email' => ['old' => 'old@example.com', 'new' => 'new@example.com'] // ] // Check if specific field changed if ($entry->hasFieldChanged('email')) { $oldEmail = $entry->getOldValue('email'); $newEmail = $entry->getNewValue('email'); echo "Email changed from $oldEmail to $newEmail"; } // Get list of all changed fields $changedFields = $entry->getChangedFields(); // ['name', 'email'] // Get all old/new values $allOldValues = $entry->getOldValues(); $allNewValues = $entry->getNewValues(); // Action helpers $entry->isCreate(); // true if ACTION_CREATE $entry->isUpdate(); // true if ACTION_UPDATE $entry->isDelete(); // true if ACTION_DELETE $entry->isSoftDelete(); // true if ACTION_SOFT_DELETE $entry->isRestore(); // true if ACTION_RESTORE // Access underlying AuditLog entity $auditLog = $entry->getAuditLog(); } } } ``` -------------------------------- ### Integrate Audit Log Viewing into EasyAdmin Dashboard (PHP) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt This snippet demonstrates how to add a menu item for viewing audit logs within the EasyAdmin dashboard. It requires EasyAdminBundle and the AuditTrailBundle itself. The code adds a new menu item linking to the AuditLogCrudController. ```php render('admin/dashboard.html.twig'); } public function configureMenuItems(): iterable { yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home'); // Add Audit Logs to sidebar yield MenuItem::linkToCrud('Audit Logs', 'fas fa-history', AuditLog::class) ->setController(AuditLogCrudController::class); } } ``` -------------------------------- ### Export Audit Logs via CLI Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Command to export audit logs to a file in a specified format (e.g., JSON). ```bash php bin/console audit:export --format=json --output=audits.json ``` -------------------------------- ### Implement Custom Auditing Logic with AuditVoterInterface (PHP) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Demonstrates how to create a custom voter by implementing the AuditVoterInterface to define specific conditions for auditing changes. This voter automatically registers as a service and can be used to conditionally audit entity updates, such as price changes exceeding a certain percentage. ```php $changeSet */ public function vote(object $entity, string $action, array $changeSet): bool { // Skip auditing minor price changes (less than 5%) if ($entity instanceof Product && $action === 'update' && isset($changeSet['price'])) { $oldPrice = $changeSet['price']['old'] ?? 0; $newPrice = $changeSet['price']['new'] ?? 0; if ($oldPrice > 0) { $percentChange = abs(($newPrice - $oldPrice) / $oldPrice) * 100; return $percentChange >= 5; // Only audit if >= 5% change } } return true; // Audit all other changes } } // The voter is automatically tagged with 'audit_trail.voter' via AutoconfigureTag // No manual configuration required - just create the class ``` -------------------------------- ### EasyAdmin Integration for Audit Logs Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Integrates the Audit Log management into EasyAdmin by adding the 'AuditLogCrudController' to your DashboardController. This provides a user interface for viewing audit logs within the admin panel. ```php use Rcsofttech\AuditTrailBundle\Controller\Admin\AuditLogCrudController; use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem; // In your DashboardController yield MenuItem::linkToCrud('Audit Logs', 'fas fa-history', AuditLog::class) ->setController(AuditLogCrudController::class); ``` -------------------------------- ### Add Custom Audit Context with PHP Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Implement the AuditContextContributorInterface to manually add application-specific metadata to audit logs. The bundle automatically discovers and merges results from all tagged contributors into the context JSON column. ```php namespace App\Audit; use Rcsofttech\AuditTrailBundle\Contract\AuditContextContributorInterface; class SystemInfoContributor implements AuditContextContributorInterface { public function contribute(object $entity, string $action, array $changeSet): array { return [ 'app_version' => 'v2.4.1', 'server_node' => gethostname(), ]; } } ``` -------------------------------- ### Collection Utilities for Audit Logs Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-reader.md Provides utility methods for working with collections of audit logs, such as retrieving the first or last entry, counting the total number of entries, and checking if the collection is empty. ```php $first = $audits->first(); $last = $audits->last(); $count = $audits->count(); $empty = $audits->isEmpty(); ``` -------------------------------- ### Filter and Group Audits with AuditEntryCollection in PHP Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Illustrates how to use the AuditEntryCollection to efficiently filter, group, and manipulate lists of audit entries. This includes filtering by field changes, grouping by action or entity, and performing collection-level operations like counting and mapping. ```php auditReader ->forEntity(Order::class) ->between( new \DateTimeImmutable('2024-01-01'), new \DateTimeImmutable('2024-12-31') ) ->getResults(); // Filter results in memory $priceChanges = $audits->filter( fn (AuditEntry $entry) => $entry->hasFieldChanged('price') ); // Group by action type $byAction = $audits->groupByAction(); // Returns: ['create' => [...], 'update' => [...], 'delete' => [...]] // Group by entity class $byEntity = $audits->groupByEntity(); // Returns: ['App\Entity\Order' => [...]] // Group by entity ID $byEntityId = $audits->groupByEntityId(); // Returns: ['App\Entity\Order:123' => [...], 'App\Entity\Order:456' => [...]] // Get specific action types $creates = $audits->getCreates(); $updates = $audits->getUpdates(); $deletes = $audits->getDeletes(); // Collection utilities $first = $audits->first(); $last = $audits->last(); $count = $audits->count(); $isEmpty = $audits->isEmpty(); // Find first matching entry $found = $audits->find(fn (AuditEntry $e) => $e->getUserId() === '42'); // Check if any/all match $hasAdminChanges = $audits->any(fn (AuditEntry $e) => $e->getUsername() === 'admin'); $allByAdmin = $audits->all(fn (AuditEntry $e) => $e->getUsername() === 'admin'); // Map to custom array $summaries = $audits->map(fn (AuditEntry $e) => [ 'action' => $e->getAction(), 'date' => $e->getCreatedAt()->format('Y-m-d'), ]); // Iterate directly foreach ($audits as $entry) { echo $entry->getAction() . "\n"; } } } ``` -------------------------------- ### Configure Multiple Transports (Chain Transport) (YAML) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-transports.md Enables multiple audit log transports simultaneously, such as Doctrine and Queue. The bundle automatically uses a ChainAuditTransport to dispatch logs to all enabled transports. ```yaml audit_trail: transports: doctrine: true queue: enabled: true ``` -------------------------------- ### Mark Entities for Auditing with #[Auditable] Attribute Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Demonstrates how to use the #[Auditable] attribute to mark Doctrine entities for automatic audit tracking. It shows how to enable/disable auditing and specify properties to ignore. ```php id; } public function getName(): string { return $this->name; } public function setName(string $name): self { $this->name = $name; return $this; } public function getPrice(): float { return $this->price; } public function setPrice(float $price): self { $this->price = $price; return $this; } } ``` -------------------------------- ### Control Auditing Per Entity with Attributes Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md This PHP code demonstrates how to apply granular control over auditing for a specific entity using the `#[Auditable]` attribute. You can enable or disable auditing globally for the entity and specify properties to be ignored during the audit process. ```php forEntity(Product::class, '123')->getFirstResult(); if ($entry) { $context = $entry->getContext(); if (isset($context['impersonation'])) { echo "Action performed by " . $context['impersonation']['impersonator_username']; } } ``` -------------------------------- ### Add Custom Metadata to Audit Logs with AuditContextContributorInterface (PHP) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Implement the AuditContextContributorInterface to automatically inject application-specific metadata into every audit log entry. This allows for enriching logs with details like application version, server node, deployment environment, and correlation IDs. The contributed context is stored in the 'context' column of the audit log. ```php $changeSet * @return array */ public function contribute(object $entity, string $action, array $changeSet): array { return [ 'app_version' => 'v2.4.1', 'server_node' => gethostname(), 'deployment_env' => $_ENV['APP_ENV'] ?? 'unknown', 'correlation_id' => $_SERVER['HTTP_X_CORRELATION_ID'] ?? uniqid('corr_'), ]; } } // All contributors are automatically discovered via AutoconfigureTag('audit_trail.context_contributor') // The context is stored in the JSON 'context' column of the audit log // Access it via: $entry->getContext()['app_version'] ``` -------------------------------- ### Add Messenger Stamps Programmatically to Audit Logs (PHP) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-transports.md Demonstrates how to manually add Messenger stamps, such as DelayStamp, to audit logs via the $context array when creating an audit log. This allows for programmatic control over message dispatching. ```php use Symfony\Component\Messenger\Stamp\DelayStamp; // Programmatic audit log with a 5-second delay $auditService->createAuditLog($entity, 'custom_action', null, null, [ 'messenger_stamps' => [new DelayStamp(5000)] ]); ``` -------------------------------- ### Conditional Auditing with #[AuditCondition] Attribute Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Explains how to use the #[AuditCondition] attribute for conditional auditing based on runtime expressions using Symfony ExpressionLanguage. It lists the available context variables. ```php 100")] class Product { #[ORM\Id, ORM\GeneratedValue, ORM\Column] private ?int $id = null; #[ORM\Column] private string $name; #[ORM\Column] private float $price; public function getPrice(): float { return $this->price; } public function setPrice(float $price): self { $this->price = $price; return $this; } } // Available context variables in expressions: // - object: The entity being audited // - action: 'create', 'update', 'delete', 'soft_delete', 'restore' // - changeSet: Array of changes ['field' => ['old' => value, 'new' => value]] // - user: Object with id, username, and ip properties ``` -------------------------------- ### Enable Doctrine Transport for Audit Logs (YAML) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-transports.md Enables the default Doctrine transport for storing audit logs directly in the application's database. This is the default behavior if no other transports are explicitly configured. ```yaml audit_trail: transports: doctrine: true ``` -------------------------------- ### Revert Entity Changes via CLI Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Command to revert an entity to its state recorded in a specific audit log entry. Supports custom context for tracking revert reasons. ```bash # Revert an entity to its state in a specific audit log php bin/console audit:revert 123 # Revert with custom context (JSON) php bin/console audit:revert 123 --context='{"reason": "Accidental deletion", "ticket": "T-101"}' ``` -------------------------------- ### Purge Old Audit Logs via CLI Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Command to remove audit logs older than a specified date. The --force flag is required to execute the purge. ```bash php bin/console audit:purge --before="30 days ago" --force ``` -------------------------------- ### Retrieve Signature from Messenger Envelope (PHP) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-transports.md Shows how to access the SignatureStamp from a Messenger envelope in a message handler when payload signing is enabled for the queue transport. This allows verification of the audit log's authenticity. ```php use Rcsofttech\AuditTrailBundle\Message\Stamp\SignatureStamp; // In your message handler $signature = $envelope->last(SignatureStamp::class)?->signature; ``` -------------------------------- ### Cross-Platform Audit Log Serialization (JSON) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md The AuditLogMessageSerializer provides cross-platform JSON serialization for audit logs. This allows publishing logs in a language-agnostic format and consuming them in any application, including Node.js, Python, Go, or other Symfony apps. ```json { "entity_class": "App\\Entity\\User", "entity_id": "123", "action": "update", "old_values": { "email": "old@example.com" }, "new_values": { "email": "new@example.com" }, "changed_fields": ["email"], "user_id": "42", "username": "admin", "ip_address": "127.0.0.1", "created_at": "2024-01-20T12:00:00+00:00" } ``` -------------------------------- ### Configure Queue Transport for Audit Logs (YAML) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-transports.md Enables the queue transport for audit logs using Symfony Messenger. Requires defining an 'audit_trail' transport in messenger.yaml. The 'bus' option is optional for specifying a custom bus. ```yaml audit_trail: transports: queue: enabled: true bus: 'messenger.bus.default' # Optional: specify a custom bus framework: messenger: transports: audit_trail: '%env(MESSENGER_TRANSPORT_DSN)%' ``` -------------------------------- ### Programmatically Revert Entity Changes with PHP Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md Programmatically revert an entity using the AuditReverter service, optionally providing custom context to document the reason for the revert. The bundle automatically adds 'reverted_log_id' to the new log's context. ```php $auditReverter->revert($log, false, false, [ 'reason' => 'Accidental deletion', 'ticket_id' => 'TICKET-456' ]); ``` -------------------------------- ### Conditional Auditing with ExpressionLanguage Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md This PHP code illustrates how to conditionally audit entity actions using the `#[AuditCondition]` attribute. The condition is defined using Symfony's ExpressionLanguage, allowing dynamic checks based on the action, the object itself, its changes, and the current user. ```php 100")] class Product { public function getPrice(): int { /* ... */ } } ``` -------------------------------- ### Implement Custom Audit Voter Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/README.md This PHP code defines a custom voter class that implements the `AuditVoterInterface`. This allows for complex conditional logic to determine whether an audit should be performed, providing a flexible way to skip auditing based on specific criteria. ```php isAdmin(); } private function isAdmin(): bool { // Add your logic here to determine if the current user is an admin return false; } } ``` -------------------------------- ### Configure HTTP Transport for Audit Logs (YAML) Source: https://github.com/rcsofttech85/audittrailbundle/blob/main/docs/symfony-audit-transports.md Configures the HTTP transport to send audit logs to a specified external API endpoint. Includes options for the endpoint URL, custom headers (like Authorization and X-App-Name), and request timeout. ```yaml audit_trail: transports: http: enabled: true endpoint: 'https://audit-api.example.com/v1/logs' headers: 'Authorization': 'Bearer your-api-token' 'X-App-Name': 'MySymfonyApp' timeout: 10 # seconds ``` -------------------------------- ### Mask Sensitive Data with #[Sensitive] Attribute Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Illustrates the use of the #[Sensitive] attribute to mask sensitive field values in audit logs. It shows how to use a custom mask string and the default mask. ```php auditReader ->byTransaction('019b5aca-60ed-70bf-b139-255aa96c96cb') ->getResults(); ``` -------------------------------- ### Hook Into Audit Log Creation with AuditLogCreatedEvent (PHP) Source: https://context7.com/rcsofttech85/audittrailbundle/llms.txt Subscribe to the AuditLogCreatedEvent to intercept audit logs before they are persisted. This allows for modifying the log entry, adding custom metadata to the context, triggering external notifications, or logging specific actions like entity deletions. The event provides access to the audit log object, the entity being audited, and the action performed. ```php 'onAuditLogCreated', ]; } public function onAuditLogCreated(AuditLogCreatedEvent $event): void { $log = $event->getAuditLog(); $entity = $event->entity; // Add custom metadata to context $context = $log->getContext(); $context['server_id'] = 'node-01'; $context['request_timestamp'] = time(); $log->setContext($context); // Log high-value changes if ($event->action === 'delete') { $this->logger->warning('Entity deleted', [ 'entity_class' => $event->entityClass, 'entity_id' => $log->getEntityId(), 'user' => $log->getUsername(), ]); } // Trigger alerts for sensitive entities if ($event->entityClass === 'App\Entity\User' && $event->action === 'update') { // Send notification, webhook, etc. } } } ```