elstc / cakephp-activity-logger
ActivityLogger plugin for CakePHP
Installs: 7 915
Dependents: 0
Suggesters: 0
Security: 0
Stars: 9
Watchers: 3
Forks: 4
Open Issues: 3
Type:cakephp-plugin
Requires
- php: >=8.1
- ext-json: *
- ext-pdo: *
- cakephp/cakephp: ^5.0
- psr/log: ^3.0
Requires (Dev)
- cakephp/authentication: ^3.0
- cakephp/cakephp-codesniffer: ^5.0
- cakephp/migrations: ^4.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.5.5 || ^11.1.3 || ^12.0.9
- dev-cake5
- v3.2.0
- v3.1.0
- v3.0.1
- v3.0.0
- v2.2.0
- v2.1.0
- v2.0.0
- v2.0.0-rc7
- v2.0.0-rc6
- v2.0.0-rc5
- v2.0.0-rc4
- v2.0.0-rc3
- v2.0.0-rc2
- v2.0.0-rc1
- v2.0.0-beta1
- v1.6.0
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.0
- v1.3.0
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.0
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- dev-translate-comments
- dev-feature/auto-issuer-middleware
- dev-cake4
- dev-cake3
This package is auto-updated.
Last update: 2025-06-27 14:08:12 UTC
README
ActivityLogger plugin automatically logs database operations (create, update, delete) in CakePHP applications. It tracks who, when, and what was changed.
Requirements
- PHP 8.1 or higher
- CakePHP 5.0 or higher
- PDO extension
- JSON extension
Installation
You can install this plugin into your CakePHP application using composer.
The recommended way to install composer packages is:
composer require elstc/cakephp-activity-logger:^3.0
Load plugin
Load the plugin by adding the following statement in your project's src/Application.php
:
$this->addPlugin('Elastic/ActivityLogger');
Create the activity_logs table
Run migration command:
bin/cake migrations migrate -p Elastic/ActivityLogger
Usage
Attach to Table
Attach the ActivityLogger plugin to your table to enable automatic logging:
class ArticlesTable extends Table { public function initialize(array $config): void { // ... $this->addBehavior('Elastic/ActivityLogger.Logger', [ 'scope' => [ 'Articles', 'Authors', ], ]); } }
Basic Activity Logging
Logging on create
$article = $this->Articles->newEntity([ /* data */ ]); $this->Articles->save($article); // saved log // [action='create', scope_model='Articles', scope_id=$article->id]
Logging on update
$article = $this->Articles->patchEntity($article, [ /* update data */ ]); $this->Articles->save($article); // saved log // [action='update', scope_model='Articles', scope_id=$article->id]
Logging on delete
$article = $this->Articles->get($id); $this->Articles->delete($article); // saved log // [action='delete', scope_model='Articles', scope_id=$article->id]
Activity Logging with Issuer
You can log information about the user who performed the operation:
$this->Articles->setLogIssuer($author); // Set issuer $article = $this->Articles->newEntity([ /* data */ ]); $this->Articles->save($article); // saved log // [action='create', scope_model='Articles', scope_id=$article->id, ...] // and // [action='create', scope_model='Authors', scope_id=$author->id, ...]
AutoIssuerMiddleware (Recommended for CakePHP 4.x+)
AutoIssuerMiddleware
is a PSR-15 compliant middleware that provides automatic issuer setting for applications using the Authorization
plugin.
This middleware operates at the application level and processes authentication information early in the request lifecycle.
Installation and Configuration
// In src/Application.php use Elastic\ActivityLogger\Http\Middleware\AutoIssuerMiddleware; class Application extends BaseApplication { public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue { $middlewareQueue // ... other middleware ->add(new AuthenticationMiddleware($this)) // Add AutoIssuerMiddleware AFTER authentication middleware ->add(new AutoIssuerMiddleware([ 'userModel' => 'Users', // User model name (default: 'Users') 'identityAttribute' => 'identity', // Request attribute name (default: 'identity') ])) // ... other middleware ->add(new RoutingMiddleware($this)); return $middlewareQueue; } }
Important Notes
- Middleware Order: Always place AutoIssuerMiddleware AFTER authentication middleware
AutoIssuerComponent (Legacy Approach)
If you're using Authorization
plugin or AuthComponent
, the AutoIssuerComponent
will automatically set the issuer to Tables:
// In AppController class AppController extends Controller { public function initialize(): void { // ... $this->loadComponent('Elastic/ActivityLogger.AutoIssuer', [ 'userModel' => 'Users', // Specify user model name ]); // ... } }
Activity Logging with Scope
You can log operations related to multiple models:
class CommentsTable extends Table { public function initialize(array $config): void { // ... $this->addBehavior('Elastic/ActivityLogger.Logger', [ 'scope' => [ 'Articles', 'Authors', 'Users', ], ]); } }
$this->Comments->setLogScope([$user, $article]); // Set scope $comment = $this->Comments->newEntity([ /* data */ ]); $this->Comments->save($comment); // saved log // [action='create', scope_model='Users', scope_id=$user->id, ...] // and // [action='create', scope_model='Articles', scope_id=$article->id, ...]
Activity Logging with Custom Messages
You can use the setLogMessageBuilder
method to generate custom messages for each log action:
class ArticlesTable extends Table { public function initialize(array $config): void { // ... $this->addBehavior('Elastic/ActivityLogger.Logger', [ 'scope' => [ 'Articles', 'Authors', ], ]); // Add message builder $this->setLogMessageBuilder(static function (ActivityLog $log, array $context) { if ($log->message !== null) { return $log->message; } $message = ''; $object = $context['object'] ?: null; $issuer = $context['issuer'] ?: null; switch ($log->action) { case ActivityLog::ACTION_CREATE: $message = sprintf('%3$s created article #%1$s: "%2$s"', $object->id, $object->title, $issuer->username); break; case ActivityLog::ACTION_UPDATE: $message = sprintf('%3$s updated article #%1$s: "%2$s"', $object->id, $object->title, $issuer->username); break; case ActivityLog::ACTION_DELETE: $message = sprintf('%3$s deleted article #%1$s: "%2$s"', $object->id, $object->title, $issuer->username); break; default: break; } return $message; }); } }
Alternatively, you can use setLogMessage
before save/delete operations to set a log message:
$this->Articles->setLogMessage('Custom Message'); $this->Articles->save($entity); // saved log // [action='update', 'message' => 'Custom Message', ...]
Save Custom Log
You can also record your own activity logs:
$this->Articles->activityLog(\Psr\Log\LogLevel::NOTICE, 'Custom Message', [ 'action' => 'custom', 'object' => $article, ]); // saved log // [action='custom', 'message' => 'Custom Message', scope_model='Articles', scope_id=$article->id, ...]
Find Activity Logs
You can search recorded activity logs:
$logs = $this->Articles->find('activity', ['scope' => $article]);
Advanced Usage Examples
Conditional Logging
When you want to log only under certain conditions:
// Log only when specific fields are changed if ($article->isDirty('status')) { $this->Articles->setLogMessage('Status was changed'); } $this->Articles->save($article);
Batch Processing with Logging
During large data processing, you can temporarily disable logging:
// Temporarily disable logging $behavior = $this->Authors->disableActivityLog(); // Batch processing foreach ($articles as $article) { $this->Articles->save($article); } // Re-enable logging $this->Articles->enableActivityLog();
Troubleshooting
Common Issues
Q: Logs are not being recorded
A: Please check the following:
- Whether migrations have been executed
- Whether the Behavior is properly attached
- Whether there are any database connection issues
Q: Issuer information is not being recorded
A: Please check the following:
- If using AutoIssuerMiddleware: Ensure it's placed AFTER authentication middleware in the middleware queue
- If using AutoIssuerComponent: Verify it's loaded in your controller's initialize() method
- Check if
setLogIssuer()
is manually set when needed - Verify the user model configuration matches your application's user table
Q: AutoIssuerMiddleware vs AutoIssuerComponent - Which should I use?
A:
-
Use AutoIssuerMiddleware (Recommended for CakePHP 4.x+):
- For new applications
- When you need application-wide issuer tracking
- For better performance and cleaner architecture
- When using PSR-15 middleware stack
-
Use AutoIssuerComponent:
- For legacy applications or CakePHP 3.x
- When you need controller-specific issuer handling
- For backward compatibility
Q: Is there any performance impact?
A:
- AutoIssuerMiddleware has minimal performance impact as it processes once per request
- When handling large amounts of data, consider temporarily disabling logging as needed
Q: The issuer is not set for dynamically loaded Tables
A: The AutoIssuerMiddleware hooks into Model.initialize
events. Ensure:
- The middleware is loaded before any Table access
- Tables are loaded through the TableLocator (not manually instantiated)
- The LoggerBehavior is attached to the Table
License
MIT License. See LICENSE.txt for details.
Contributing
Bug reports and feature requests are welcome at GitHub Issues.
Pull requests are also welcome. We recommend discussing large changes in an Issue first.