wolfemm
wolfemm

Reputation: 1003

Logging user actions in laravel

I'm trying to log all actions that users do (login / logout / CRUD) to a logs table in my database, and from what I've seen events look to be the right way to do this.

I've added a did($action) method to the User model, which logs an action to the database for the given user.

Here's what I've got so far:

EventServiceProvider.php

namespace App\Events;

use Illuminate\Support\ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->events->subscribe(new UserEventSubscriber);
    }
}

UserEventSubscriber.php

namespace App\Events;

class UserEventSubscriber
{
    public function login(\User $user)
    {
        return $user->did('logged_in');
    }

    public function logout(\User $user)
    {
        return $user->did('logged_out');
    }

    public function subscribe($events)
    {
        $events->listen('user.login', 'App\Events\UserEventSubscriber@login');

        $events->listen('user.logout', 'App\Events\UserEventSubscriber@logout');
    }
}

To log an action:

Event::fire('user.logout', array(Auth::user()));

I'm still trying to wrap my mind around service providers, so I could be very off-base here.

My questions:

1) Is a service provider the right thing to use or this?

2) Is there a better approach that doesn't require manually passing Auth::user() to the event every time?

3) At what level should events be fired? I'm leaning towards model whenever possible, as it would provide more useful logs from bulk actions. Otherwise there's the controller or repository.

4) These events are only necessary in the admin area (/admin/*). Would it be beneficial to somehow restrict this to only that section of the site?

5) My searches regarding the logging of user actions have been very unfruitful. Is this just something developers don't do? If so, what do they do?

Upvotes: 6

Views: 11746

Answers (2)

Adel Abou Elezz
Adel Abou Elezz

Reputation: 1

you can make helper function like that

function LogSystem($table,$action,$custom=null)
{
    $table::$action(function ($service) use ($action,$custom){
        if( ! is_null($custom))
        {
            $url='/panel/'.$custom.'/'.$service->id.'/edit';
        }
        else
        {
            $url=\Illuminate\Support\Facades\Request::fullUrl();
        }
        \Illuminate\Support\Facades\DB::table('log_activity')->insert([
            'subject' => $action.'::=='.$service->title,
            'url' => $url,
            'method' => \Illuminate\Support\Facades\Request::method(),
            'agent' => \Illuminate\Support\Facades\Request::header('user-agent'),
            'ip' => \Illuminate\Support\Facades\Request::ip(),
            'created_at'=>\Carbon\Carbon::now(),
            'user_id' => auth('admin')->check() ? auth('admin')->user()->id : 1,
        ]);
//
    });
}

Then Go to serviceproviders

LogSystem('\App\Services','created','services');

you Can call this for all croud system for any module you want

Upvotes: 0

The Alpha
The Alpha

Reputation: 146219

Is a service provider the right thing to use or this?

Yes, it's a good idea to use a service provider for bootstraping things but not necessary. If you want you may completely exclude the EventServiceProvider service provider and can do same thing from your app/start/global.php file using this:

$app->events->subscribe(new Events\UserEventSubscriber);

Since $app is a global variable so you may use it here but it's not a cleaner way to do this in this (global.php) file but a service provider is only a neat and clean way to bootstrap things (like including php files using include "someClass.php") because the Laravel calls the register method defined in every service provider class during the bootup process of the framework so developers can do some bootstraping/initializing/including and such like things before the application dispatch the route.

Is there a better approach that doesn't require manually passing Auth::user() to the event every time?

There are other ways but in this case stick with you current approach because dependency is the Auth::user() means that, the currently logged in user so it's better to pass the use manually or you may also use \Auth::user()->did() directly like this:

public function login()
{
    return \Auth::user()->did('logged_in');
}

This is a different case but Laravel provides a nice way to automatically resolve the dependencies using the IoC container when you type cast any dependency in a __constructor class, for example:

class SomeClass {
    public function __construct(User $user)
    {
        $this->use = $user;
    }
}

In this case you don't need to pass the User class when you use this class because the IoC container can automatically inject the dependency when the framework instantiate it but in your case, he dependency is Auth::user()/looged in user so it's a bit different thing so manually do it or use Auth::user()->did() directly.

At what level should events be fired? I'm leaning towards model whenever possible, as it would provide more useful logs from bulk actions. Otherwise there's the controller or repository.

There is no level for this, it depends on your need and preference and maybe architecture of the application as well. Actually, you may build your application even without using events.

These events are only necessary in the admin area (/admin/*). Would it be beneficial to somehow restrict this to only that section of the site?

Maybe you can but no need, not a very big deal IMO.

My searches regarding the logging of user actions have been very unfruitful. Is this just something developers don't do? If so, what do they do?

Not completely sure what you are talking about but if you are talking about the logging of user actions then the answer is: depends. I did once for a travel agency, in their application the logging of user actions were very important so I logged almost everything a user does after (s)he logs in, such as: receiving a payment from a client, selling a ticket, their (employees/users) log in/out so higher authority could check their activities.

Don't hesitate about what others do, find out what you need to do, understand your requirements and develop accordingly.

Upvotes: 11

Related Questions