sobatcoding.com - Tutorial cara membuat Log Activity menggunakan Trait di Laravel 8
Ada beberapa cara membuat Log Activity pada Laravel, kalian bisa menggunakan middleware ataupun Trait. Pada artikel kali ini kita akan belajar membuat log activity sederhana menggunakan Trait. Trait merupakan sebuah mekanisme yang mirip dengan class yang memiliki berbagai method yang bisa digunakan kembali ( Reusable ) di beberapa class tanpa melalui turunan ( Inheritance ).
Kita buat table book terlebih dahulu menggunakan migration, dengan command php artisan make:migration create_books_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBooksTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->integer('price')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('books');
}
}
Kemudian jalankan perintah di terminal
php artisan migrate
Buat model bernama Book.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
use HasFactory;
protected $table = "books";
protected $fillable = ['title', 'price'];
}
Selanjutnya kita akan mencoba membuat data dummy menggunakan faker factory dengan cara menjalankan command php artisan make:factory BookFactory --model=Book
<?php
namespace Database\Factories;
use App\Models\Book;
use Illuminate\Database\Eloquent\Factories\Factory;
class BookFactory extends Factory
{
protected $model = Book::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'title' => $this->faker->name(),
'price' => $this->faker->numberBetween(50000, 500000)
];
}
}
Selanjutnya jalankan command composer dump-autoload agar auto load dependecies laravel
composer dump-autoload
Selanjutnya jalankan command berikut di terminal
php artisan tinker
Book::factory()->count(100)->create()
Command di atas berfungsi untuk create data dummy menggunakan faker factory sebanyak 100 record. Kalian bisa atur sendiri jumlah record yang akan kalian buat.
Buatlah controller bernama BookController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Validator;
use App\Models\Book;
class BookController extends Controller
{
public function index(Request $request)
{
return response()->json(Book::get());
}
public function show($book)
{
return response()->json(Book::findOrFail($book));
}
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'title' => 'required',
'price' => 'required|numeric',
],
[
'required' => ':attribute harus diisi',
'numeric' => ':numeric harus angka',
]);
if ($validator->fails()) {
return response()->json( $validator->errors()->first(), 422 );
die();
}
$insert = new Book;
$insert->title = $request->get('title');
$insert->price = $request->get('price');
$insert->save();
return response()->json("Berhasil insert data");
}
public function update($book, Request $request)
{
$validator = Validator::make($request->all(), [
'title' => 'required',
'price' => 'required|numeric',
],
[
'required' => ':attribute harus diisi',
'numeric' => ':numeric harus angka',
]);
if ($validator->fails()) {
return response()->json( $validator->errors()->first(), 422 );
die();
}
$update = Book::findOrFail($book);
$update->title = $request->get('title');
$update->price = $request->get('price');
$update->save();
return response()->json("Berhasil update data");
}
public function destroy($book)
{
$book = Book::findOrFail($book);
$book->delete();
return response()->json("Berhasil Hapus");
}
}
Buatlah route baru di file routes/api.php
use Illuminate\Support\Facades\Route;
Route::resources([
'books' => BookController::class
]);
Buatlah table Log terlebih dahulu menggunakan migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('logs', function (Blueprint $table) {
$table->id();
$table->string('method')->nullable();
$table->string('action')->nullable();
$table->string('url')->nullable();
$table->string('subject')->nullable();
$table->string('description')->nullable();
$table->text('old_properties')->nullable();
$table->text('properties')->nullable();
$table->string('ip_address')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('logs');
}
}
Jalankan perintah php artisan migrate
Buatlah model bernama Log
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Log extends Model
{
use HasFactory;
protected $table = "logs";
protected $fillable = ['method', 'action', 'url', 'subject', 'description', 'old_properties', 'properties', 'ip_address'];
}
Buat folder Traits, simpan di dalam folder app. jadi nanti struktur folder seperti berikut app\Traits. Kemudian buatlah file bernama LogTrait.php di dalam folder tersebut
<?php
namespace App\Traits;
use App\Models\Log;
use Illuminate\Support\Str;
trait LogTrait
{
/**
* Handle model event
*/
public static function bootLogTrait()
{
/**
* Data creating and updating event
*/
static::saved(function ($model) {
// create or update?
if ($model->wasRecentlyCreated) {
static::storeLog($model, static::class, 'CREATED');
} else {
if (!$model->getChanges()) {
return;
}
static::storeLog($model, static::class, 'UPDATED');
}
});
/**
* Data deleting event
*/
static::deleted(function ($model) {
static::storeLog($model, static::class, 'DELETED');
});
}
/**
* Generate the model name
* @param Model $model
* @return string
*/
public static function getTagName($model)
{
return !empty($model->tagName) ? $model->tagName : Str::title(Str::snake(class_basename($model), ' '));
}
/**
* Store model logs
* @param $model
* @param $modelPath
* @param $action
*/
public static function storeLog($model, $modelPath, $action)
{
$newValues = null;
$oldValues = null;
if ($action === 'CREATED') {
$newValues = $model->getAttributes();
} elseif ($action === 'UPDATED') {
$oldValues = $model->getOriginal();
$newValues = $model->getChanges();
}
$subject = static::getTagName($model);
$description = 'Data '. $subject. ' ['.$action.']';
$systemLog = new Log();
$systemLog->subject = $subject. ':'. $action;
$systemLog->action = $action;
$systemLog->method = request()->method();
$systemLog->old_properties = json_encode($oldValues);
$systemLog->url = request()->path();
$systemLog->description = $description;
$systemLog->properties = json_encode(request()->except('_token'));
$systemLog->created_at = now();
$systemLog->ip_address = request()->ip();
$systemLog->save();
}
}
Tambahkan trait tersebut di model Book.php, menjadi seperti berikut
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Traits\LogTrait;
class Book extends Model
{
use LogTrait, HasFactory;
protected $table = "books";
protected $fillable = ['title', 'price'];
protected $tagName = 'Book';
}
Jangan lupa tambahkan variable $tagName. Tag Name ini berfungsi sebagai informasi dari nama model yang digunakan. Sangat membantu ketika kita ingin mengubah nama model tanpa harus mengganti nama model itu sendiri
Langsung kita test menggunakan postman
Coba kalian lihat di table log di mysql, secara otomatis action berupa CREATED, DELETED, UPDATED terhadap database akan tersimpan di table log
Selamat mencoba. Semoga artikel ini bermanfaat.
Komentar 0