127호. Laravel Eloquent Model 의 변경 사항을 기록해주는 laravel-auditing 패키지 free

2020-04-17

개요


웹 서비스를 구현하다 보면 사용자가 실수로 데이타를 삭제하거나 수정하는 경우에 대비해야 할 필요가 있습니다.


DBMS 차원의 백업과 복구는 시스템 장애나 해킹등의 비상 상황에 대비하는 작업이고 개별 레코드의 변경을 추적하고 관리하는 데에는 적합하지 않습니다.


물론 DBMS 를 archiving mode 로 설정하고 운영하면 레코드 단위의 변경을 추적할 수도 있지만 비상시 복구용이라 DBA 의 도움과 시스템 차원의 작업이 필요하므로 레코드 단위 실수 방지는 app 레벨에서 대응하는 게 적절합니다.


삭제 실수는 일단 soft delete 기능을 적용하면 되지만 실수로 잘못된 데이터로 업데이트하는 것은 변경 이력을 별도로 추적하는 기능을 구현해야 합니다.


이런 요구 사항이 다른 곳에도 많은지 라라벨에서 쉽게 모델의 변경 이력을 관리해주는 Revisionable 이라는 패키지와 laravel-auditing 이라는 패키지가 github 에 올라와 있고 상당히 많은 star 를 받고 있습니다.


별점은 Revisionable 이 좀 더 많지만 저는 매뉴얼이 체계적으로 되어 있는 laravel-auditing 을 사용하고 있는데 간략한 사용법을 공유해 봅니다.



Revisionable은 1일 1식 라라벨 2호 모델 변경 이력을 자동을 저장해주는 패키지 Revisionable 을 참고하세요.



설치


composer 로 패키지를 설치합니다.


composer require owen-it/laravel-auditing

config/app.php 에 프로바이더를 등록합니다.


'providers' => [
// ...

OwenIt\Auditing\AuditingServiceProvider::class,

// ...
],

vendor 파일을 퍼블리싱합니다.


php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="config"

config/audit.php 에서 auditing 패키지의 동작을 설정할 수 있습니다.


<?php

return [
// auditing 동작 여부를 설정합니다.
'enabled' => env('AUDITING_ENABLED', true),

// User, IP Address 정보등을 가져올 리졸버를 설정합니다.
'resolver' => [
'user' => OwenIt\Auditing\Resolvers\UserResolver::class,
'ip_address' => OwenIt\Auditing\Resolvers\IpAddressResolver::class,
'user_agent' => OwenIt\Auditing\Resolvers\UserAgentResolver::class,
'url' => OwenIt\Auditing\Resolvers\UrlResolver::class,
],
// Audit 을 할 event 를 지정합니다. 기본적으로 생성, 갱신, 삭제, 복구시 동작합니다.
'events' => [
'created',
'updated',
'deleted',
'restored',
],

DB migration 파일을 퍼블리싱합니다.


php artisan vendor:publish --provider "OwenIt\Auditing\AuditingServiceProvider" --tag="migrations"

audit 컬럼을 text 에서 json 으로 바꾸면 JSON Where 구문을 사용할 수 있으므로 생성된 migration 파일(날자_create_audits_table.php)에서 다음 내용을 수정합니다.


create_audits_table.php

// $table->text('old_values')->nullable();
// $table->text('new_values')->nullable();

$table->json('old_values')->nullable();
$table->json('new_values')->nullable();

DB migration 을 실행하면 Model 의 변경 사항을 기록하는 audits 테이블이 생성됩니다.


php artisan migrate

Model 설정


변경을 추적하려는 Eloquent Model 에 implements \OwenIt\Auditing\Contracts\Auditable 를 추가하고 Auditable trait 을 사용하도록 설정합니다.


class Customer extends Model implements \OwenIt\Auditing\Contracts\Auditable
{
use \OwenIt\Auditing\Auditable;

Audit 레코드 처리


레코드 가져오기


audit 레코드에 접근하려면 먼저 audit 이 저장된 모델을 가져옵니다.


// audit 이 저장된 고객 id
$c = Customer::find(94);

// 해당 모델의 모든 이력들
$audits = $c->audits;

// 첫 번째 이력
$f = $audits->first();

// 마지막 이력
$f = $c->audits()->latest()->first();

// id 로 가져오기
$f = $c->audits()->find(2);

eager loading 으로 연관 모델 가져오기


이거 로딩으로 연관 모델을 가져오려면 with() 메서드에 가져오려는 relation 을 설정합니다. 아래는 레코드를 변경한 사용자 정보를 join 으로 같이 가져오는 예제입니다.


$c = Customer::find(94);

$audits = $c->audits()->with('user')->get();

audit 메타 데이타 가져오기


audit 과 관련한 메타 데이타를 array 로 가져오려면 audit 모델의 getMetadata 메서드를 호출하면 됩니다.


$audits = Customer::find(94)->audits;

$f = $audits->first();

var_dump($f->getMetadata());

변경된 properties 만 가져오기


audit 모델의 getModified 메서드를 호출하면 audit 테이블의 old_values 와 new_values 만 가져올 수 있습니다.


$audits = Customer::find(94)->audits;
$f = $audits->first();
var_dump($f->getModified ());

편집자 한마디


old_values와 new_values를 text에서 json으로 변경하는거 정말 꿀팁이네요! Revisionable은 한 번에 여러 컬럼이 변경되는 경우 변경된 컬럼 수 만큼 레코드가 생성되는게 아쉬웠는데, 이 패키지는 하나의 레코드로 모든 변경 사항을 처리해서 좋네요.


이 글은 정광섭님의 블로그에서도 보실 수 있습니다. 원문 링크 https://www.lesstif.com/php-and-laravel/laravel-eloquent-model-laravel-auditing-87949476.html


정광섭

쉽게 배우는 라라벨 5 프로그래밍 저자. 20년 경력의 야크 털깍이 전문가.