Simple package which dcode uses to manage activity logs
dcodegroup/activity-log is a Laravel package for simple package which dcode uses to manage activity logs.
It currently has 4 GitHub stars and 133.936 downloads on Packagist (latest version 4.0.6).
Install it with composer require dcodegroup/activity-log.
Discover more Laravel packages by dcodegroup
or browse all Laravel packages to compare alternatives.
Last updated
The dcodegroup/activity-log package provides a simple and unified approach to track and record activity / interactions
against your Laravel models (and relations). Capture changes, updates, and user interactions to enhance transparency and
auditing in your application in a centralised and consistent approach.
| Package version | PHP | Laravel |
| --- | --- | --- |
| 4.0.1+ / 4.x | ^8.3 | ^10.10, ^11, ^12, ^13 |
| 4.0.0 | ^8.3 | ^11, ^12, ^13 |
| 3.x | ^8.3 | ^11, ^12, ^13 |
| 2.x | ^8.2 | ^10.2, ^11, ^12 (later 2.x) |
| 1.1.x | ^8.2 / ^8.3 | ^10, ^11 |
| 1.0.x | ^8.0–^8.2 | ^7–^10 |
Upgrading to 4.x? See UPGRADE.md for the step-by-step file changes.
Since version 1.1.1 we are no longer need to use observers to listen for changes from the
model. bootActivityLoggable in ActivityLoggable trait solved that. Make sure to remove duplicate observers before
updating
This package is a PHP Laravel package and no longer ships Vue/JS/CSS. Frontend components live in a separate package (install with pnpm):
@dcodegroup-au/vue-activity-logInstall the backend via Composer:
composer require dcodegroup/activity-log
Run the installer and migrations:
php artisan activity-log:install
php artisan migrate
If you need the UI, install the Vue package and follow its README (or the 4.x upgrade guide if migrating from 3.x).
Add the following contract to the User model.
<?php
namespace App\Models;
use Dcodegroup\ActivityLog\Contracts\HasActivityUser;
class User extends Authenticatable implements HasActivityUser
{
public function getActivityLogUserName(): string
{
return $this->name;
}
public function getActivityLogEmail(): string
{
return $this->email;
}
public function getActivityLogUser(): array
{
return [
'id' => $this->id,
'full_name' => $this->getActivityLogUserName(),
'email' => $this->getActivityLogEmail(),
];
}
}
Add the following to the EventServiceProvider if you want to listen for mail events:
<?php
use Dcodegroup\ActivityLog\Listeners\ActivityLogMessageSentListener;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Mail\Events\MessageSent;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
MessageSent::class => [
ActivityLogMessageSentListener::class,
],
];
}
Most of configuration has been set the fair defaults. However you can review the configuration file
at config/activity-log.php and adjust as needed
<?php
use Dcodegroup\ActivityLog\Models\ActivityLog;
return [
/*
|--------------------------------------------------------------------------
| Middleware
|--------------------------------------------------------------------------
|
| What middleware should the package apply.
|
*/
'middleware' => ['web', 'auth'],
/*
|--------------------------------------------------------------------------
| Routing
|--------------------------------------------------------------------------
|
| Here you can configure the route paths and route name variables.
|
| What should the route path for the activity log be
| eg 'api/generic/activity-logs'
|
| What should the route name for the activity log be
| eg eg 'api.generic.activity-logs',
*/
'route_path' => env('LARAVEL_ACTIVITY_LOG_ROUTE_PATH', 'activity-logs'),
'route_name' => env('LARAVEL_ACTIVITY_LOG_ROUTE_NAME', 'activity-logs'),
/*
|--------------------------------------------------------------------------
| Model and Binding
|--------------------------------------------------------------------------
|
| binding - eg 'activity-logs'
| model - eg 'ActivityLog'
|
*/
'binding' => env('LARAVEL_ACTIVITY_LOG_MODEL_BINDING', 'activity-logs'),
'activity_log_model' => ActivityLog::class,
/*
|--------------------------------------------------------------------------
| Attachments
|--------------------------------------------------------------------------
*/
'attachment_url' => env('LARAVEL_ACTIVITY_LOG_ATTACHMENT_URL'),
'attachment_model' => \Dcodegroup\LaravelAttachments\Models\Media::class,
/*
|--------------------------------------------------------------------------
| Formatting
|--------------------------------------------------------------------------
|
| Configuration here is for display configuration
|
*/
'datetime_format' => env('LARAVEL_ACTIVITY_LOG_DATETIME_FORMAT', 'd-m-Y H:ia'),
'date_format' => env('LARAVEL_ACTIVITY_LOG_DATE_FORMAT', 'd.m.Y'),
/*
|--------------------------------------------------------------------------
| Pagination
|--------------------------------------------------------------------------
|
| Configuration here is for pagination
|
*/
'default_filter_pagination' => env('LARAVEL_ACTIVITY_LOG_PAGINATION', 50),
/*
|--------------------------------------------------------------------------
| User
|--------------------------------------------------------------------------
|
| Configuration here is for the user model and table
| eg 'User'
*/
'user_relationship' => env('LARAVEL_ACTIVITY_LOG_USER_RELATIONSHIP', 'user'),
'user_model' => \App\Models\User::class,
'user_table' => env('LARAVEL_ACTIVITY_LOG_USERS_TABLE', 'users'),
/*
|--------------------------------------------------------------------------
| Communication log
|--------------------------------------------------------------------------
|
|
*/
'communication_log_model' => \Dcodegroup\ActivityLog\Models\CommunicationLog::class,
'communication_log_table' => env('LARAVEL_ACTIVITY_LOG_COMMUNICATION_LOG_TABLE', 'communication_logs'),
'communication_log_relationship' => env('LARAVEL_ACTIVITY_LOG_COMMUNICATION_LOG_RELATIONSHIP', 'communicationLog'),
/*
|--------------------------------------------------------------------------
| Filter Builder
|--------------------------------------------------------------------------
|
| Configuration here is for the filter builder
| eg 'FilterBuilder class: App\Support\QueryBuilder\Filters\FilterBuilder'
*/
'filter_builder_path' => env('LARAVEL_ACTIVITY_LOG_FILTER_BUILDER_PATH', ''),
/*
|--------------------------------------------------------------------------
| Events
|--------------------------------------------------------------------------
|
| Configuration here is for the events
| eg 'open_modal_event' => 'openModal'
*/
'open_modal_event' => env('LARAVEL_ACTIVITY_LOG_EVENT_OPEN_MODEL', 'openModal'),
'reload_event' => env('LARAVEL_ACTIVITY_LOG_EVENT_RELOAD', 'getActivities'),
/*
|--------------------------------------------------------------------------
| Email Queue Name
|--------------------------------------------------------------------------
|
*/
'queue_name' => env('LARAVEL_ACTIVITY_LOG_QUEUE_NAME', 'default'),
];
| Value | Options | Description | |-----------------|---------|---------------------------------------------------------------------------------------------| | middleware | | Include a specification of what middleware this package should include. | | layout_path | | The dot notation path to the resource/view that you would like to use for the Activity Log. | | content_section | | The variable in the view that will contain the output of the Activtity Log. |
Set attachment_model to the attachment library's Eloquent model. attachment_url
accepts either a base URL or a URL containing {attachment} (or
{attachment_id}), for example /attachments/{attachment}.
Create comments with files by sending multipart/form-data. Add every file
under the attachments[] field:
modelClass=App\Models\Post
modelId=123
comment=See the attached files.
currentUrl=https://example.test/posts/123
attachments[][email protected]
attachments[][email protected]
The target model must support the attachment package's addMedia method.
Existing media can still be linked with attachment_id or attachment_ids[].
The activity resource returns the linked models in its attachments array and
includes the resolved url for each attachment.
The package provides an endpoints which you can use. See the full list by running
php artisan route:list --name=activity-log
They are
[example.com/activity-logs] Which is where you will form index. This is by default protected auth middleware but you can modify in the configuration. This is where you want to link to in your admin and possibly a new window
Located in
src\Support\QueryBuilder\Filters\DateRangeFilter.php
src\Support\QueryBuilder\Filters\TermFilter.php
Located in
src\Support\Traits\ActivityLoggable.php
src\Support\Traits\LastModifiedBy.php
The ActivityLoggable trait provides functionality for logging activities and communication logs related to a model.
logCreate(): void: Automatically create activity log every time a new model is created. (support from version
1.1.1)logUpdate(): void: Automatically create activity log every time when model is updated. (support from version
1.1.1)logDelete(): void: Automatically create activity log every time when model is deleted. (support from version
1.1.1)getActivityLogEmails(): array: Get the emails associated with activity logs.activities(): Collection: Get the collection of activities associated with the model.modelRelation(): Collection: Get the relationship between the model column with the related
table. modelRelation also has the effect of limiting logging to defined columns instead of logging all changes from
the model when you declare getModelChangesJson(true)Example of define modelRelation via model using ActivityLoggable
public function modelRelation(): Collection
{
return collect([
'account_id' => collect([ // column change in model
'label' => 'Account', // attribute label display in activity log description
'modelClass' => Account::class, // relationship model
'modelKey' => 'name', // columns display instead
]),
......
])
when declared like this instead of activity log shows like this. account_id: 1 -> 20 The result will return like
this: Account: Alison Cahill -> Annie Pollock.
getModelChanges(?array $modelChangesJson = null): string: Get the model changes as a formatted string.getModelChangesJson(bool $allowCustomAttribute = false): array: Get the model changes as an array of JSON.
If $allowCustomAttribute = true If we want to limit the storage of fields defined in modelRelation; false : If
we want to storage all model changecreateActivityLog(array $description): ActivityLog: Create a new activity log.Example of define activity log via model using ActivityLoggable
// Creating an activity log
$activityLog = $model->createActivityLog([
'type' => \Dcodegroup\ActivityLog\Models\ActivityLog::TYPE_DATA // if type is null default type will be TYPE_DATA, we support 3 other types: TYPE_STATUS, TYPE_COMMENT, TYPE_NOTIFICATION
'title' => 'Updated profile information',
'description' => 'Updated user profile information',
// Additional custom fields as needed
'communication_log_id' => '' // required when type = TYPE_NOTIFICATION to link activity log with communication log
]);
If you have a user case where you want the log messages to be logged against another model, Example. You have an Order
model and you want the OrderItem models to be recorded against the Order. Then do as below.
with the OrderItem model add the method targetModel
class OrderItem extends Model
{
...
public function targetModel(): self|Model
{
return $this->order;
}
}
Normally a model with have the field name title or label. This package can work this out in most cases. However if you have a none standard field used to name a model you can use the below method to customise the label for the model.
If no label is found then a ModelLabelNotDefinedException exception will be thrown.
public function getActivityLogModelLabel(): string
{
/**
* This can be any field or method to return the label but the return must be a string
*/
return $this->reference;
}
You can give any model a custom label by adding the following method to the model. If this is not set then Str::headline will be used on the model.
public function getActivityLogModelLabel(): string
{
/**
* This can be any field or method to return the label but the return must be a string
*/
return __('order.title');
}
Automatically the package will try and find the key for the model. Typically, this will be a field named name, title or label.
However this may not always be the case and the key may change depending on the the state of a model. Eg type Quote might be quote_number Order might use sales_order_number.
If one of the defaults is not found then an ModelKeyNotDefinedException exception will be thrown.
This should only ever occur in your local environment. If this occurs then implement the follow method in your model.
public function getActivityLogModelKey(): string
{
return (string) $this->custom_field_name;
}
By default this package will log all fields except for created_at, updated_at, deleted_at, password, and id.
If you wish to exclude other fields on your model such as third party api tokens. Then implement the following method in your model.
public function getActivityLogModelExcludeFields(): array
{
return ['xero_api_token', 'stripe_api_token'];
}
You can use a custom formatter for fields in your model by using the activityLogFieldFormatters method.
example. Add the following to the model
use Illuminate\Support\Collection;
public function activityLogFieldFormatters(): Collection
{
return collect([
'price' => fn ($value) => Number::currency(($value / 100), 'AUD'),
]);
}
price is the key for the field.
Right hand side should be a closure than can then be used for format the value that will be present.
You can override the default name / label for an entity. Simply create a method named `` that returns a string. Below is the default.
public function activityLogEntityName(): string
{
return Arr::join(Str::ucsplit(class_basename($this)), ' ').' (id:'.$this->id.')';
}
If you have a field such as Approved By. You may have a field in your database such as approved_by with a
relationship name such as approvedBy that links to the User::class model. This would prefix the activity log message with User: for the field modified.
This is not useful when you may have multiple relationships to users on the one model. You can customise the relationship name with this field, or multiple at once.
public function activityLogRelationNames(): Collection
{
return collect([
'assignedUser' => __('tickets.fields.assigned_user_id'),
'requestor' => __('tickets.fields.requestor_id'),
'approvedBy' => __('tickets.fields.approved_by'),
]);
}
*createCommunicationLog(array $data, string $to, string $content, string $type = CommunicationLog::TYPE_EMAIL): CommunicationLog
**: Create a new communication log.
Example of define Communication log via model using ActivityLoggable
// Creating a communication log
$communicationLog = $model->createCommunicationLog([
'type' =>
'cc' => ['[email protected]'],
'bcc' => ['[email protected]'],
'subject' => 'Subject of the email',
], '[email protected]', 'Content of the email');
Located in
src\Support\Traits\ReadMailableTrait.php
Frontend components have been removed from this package. Use @dcodegroup-au/vue-activity-log (repo), call the package routes/controllers directly (php artisan route:list --name=activity-log), or build your own UI against those endpoints. See UPGRADE.md when moving from ≤ 3.x.
The package provides the following events:
ActivityLogCommentCreated: This event is fired when an activity log comment is created. The event receives the
activity log
instance.ActivityLogCommentDeleted: This event is fired when an activity log comment is deleted. The event receives the
activity log instance.ActivityLogCommentUpdated: This event is fired when an activity log comment is update. The event receives the
activity log instance.ActivityLogCommunicationRead: This event is fired when an communication log is marked read. The event receives the
activity log instance.In order to log anything add the following trait to a model you want to log on.
...
use Dcodegroup\ActivityLog\Support\Traits\ActivityLoggable;
class Order extends Model
{
use ActivityLoggable;
...
}
In addition, we can add activity log wherever we want the model
$model->createActivityLog([
'type' => \Dcodegroup\ActivityLog\Models\ActivityLog::TYPE_COMMENT // if type is null default type will be TYPE_DATA, we support 3 other types: TYPE_STATUS, TYPE_COMMENT, TYPE_NOTIFICATION
'title' => 'left a comment.',
'description' => 'left a comment',
]);
Please see UPGRADE.md for upgrading to 4.x (including moving frontend assets to @dcodegroup-au/vue-activity-log via pnpm).
Please see CHANGELOG for more information about recent changes.
We believe in the power of collaboration! If you share our passion for pushing the boundaries of business software, feel free to contribute, report issues, or suggest improvements. Your insights make us better.
This package is a backend-only Laravel package. For local PHP development and testing, use the included testbench setup and run PHPUnit:
composer install
vendor/bin/phpunit
If you've found an issue related to this package that includes any security concerns; please email [email protected] to ensure that we can prioritise the concerns in a confidential manner.
This project is supported & funded by Dcode Group and the team - both past and present. Special mention to:
Dcode Group specializes in crafting tailored software solutions utilizing the Laravel framework. Our focus lies in developing business, financial, and process-driven systems designed to support unique business operations. Leveraging packages like this one, we streamline common features/functions across projects, ensuring swift integration of broad functionalities while enhancing overall code base maintenance and management. Find out more about