rmsramos/activitylog

got issue in multitenant

mlselegant opened this issue · 18 comments

What happened?

The model [Spatie\Activitylog\Models\Activity] does not have a relationship named [hospitals]. You can change the relationship being used by passing it to the [ownershipRelationship] argument of the [tenant()] method in configuration. You can change the relationship being used per-resource by setting it as the [$tenantOwnershipRelationshipName] static property on the [App\Filament\Resources\ActivityLogResource] resource class.

How to reproduce the bug

My Activity Model:
class Activity extends \Spatie\Activitylog\Models\Activity
{
use HasFactory;
public function hospital(): BelongsTo
{
return $this->belongsTo(Hospital::class);
}
}

My ActivityResource:

use App\Models\Activity;
class ActivityLogResource extends \Rmsramos\Activitylog\Resources\ActivitylogResource
{
protected static ?string $model = Activity::class;
protected static ?string $tenantOwnershipRelationshipName = 'hospitals';

.......

}

but when i browse activity-logs page, i got issue.

Package Version

1.0

PHP Version

8.2

Laravel Version

11.0

Which operating systems does with happen with?

Windows

Notes

No response

We have the following problem, in the relationship you created in your new Activity model, there is no hospital_id in the activity_log table, so you can create this field and pass the following:

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Spatie\Activitylog\Models\Activity as ModelsActivity;

class Activity extends ModelsActivity
{
    public function hospital(): BelongsTo
    {
        return $this->belongsTo(
            related: Hospital::class,
            foreignKey: 'hospital_id',
        );
    }
}

in your custom resource, override the getModel() function, calling the new activity model

namespace App\Filament\Resources;

use App\Models\Activity;
use Rmsramos\Activitylog\Resources\ActivitylogResource;

class CustomActivityLogResource extends ActivitylogResource
{
    public static function getModel(): string
    {
        return Activity::class;
    }
}

to automatically add the hospital_id, you can create an observer

namespace App\Observers;

use Filament\Facades\Filament;
use Spatie\Activitylog\Models\Activity;

class ActivityObserver
{
    public function creating(Activity $activity): void
    {
        $activity->hospital_id = Filament::getTenant()->id;
    }
}

and register the observer in your AppServiceProvider

namespace App\Providers;

use App\Observers\ActivityObserver;
use Illuminate\Support\ServiceProvider;
use Spatie\Activitylog\Models\Activity;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Activity::observe(ActivityObserver::class);
    }
}

I hope this helps, but you can look for better solutions in the spatie activity-log forum

I followed every steps that you suggested. But still i got same error:
The model [Spatie\Activitylog\Models\Activity] does not have a relationship named [hospitals]. You can change the relationship being used by passing it to the [ownershipRelationship] argument of the [tenant()] method in configuration. You can change the relationship being used per-resource by setting it as the [$tenantOwnershipRelationshipName] static property on the [App\Filament\Resources\ActivityLogResource] resource class.

I guess may be the reason:
$tenantOwnershipRelationshipName is not defined in Rmsramos\Activitylog\Resources\ActivitylogResource.

where as $tenantOwnershipRelationshipName is defined in Filament\Resources\Resource.

in your AdminPanelProvider (App\Providers\Filament)

you configured tenat and ActivitylogPlugin ?

public function panel(Panel $panel): Panel
{
    return $panel
        ->tenant(
            model: Hospital::class,
            ownershipRelationship: 'hospital'
        )
        ->tenantRegistration(App\Models\Hospital::class)
        ->plugins([
            ActivitylogPlugin::make()
                ->resource(App\Filament\Resources\CustomActivityLogResource::class),
        ]);
}

I do actually have the same issue, somehow it seems the ActivitylogPlugin::make()
->resource(App\Filament\Resources\CustomActivityLogResource::class),
]); does not work for me, it seems it still uses the Rmsramos\Activitylog\Resources\ActivitylogResource class

as a precaution, in terminal run : composer dumpautoload and php artisan config:clear

I did, I will be looking back into this tomorrow, somehow the scope to tenant gets applied on the Base Models altough I instruct it to use the custom one. I have to get my class name resolution knowledge up to date

@rmsramos yes of course i configured tenat and ActivitylogPlugin.

I can see "Activity Logs" menu also.
but when i click the "Activity Logs" menu then such issue arise.

The model [Spatie\Activitylog\Models\Activity] does not have a relationship named [hospitals]. You can change the relationship being used by passing it to the [ownershipRelationship] argument of the [tenant()] method in configuration. You can change the relationship being used per-resource by setting it as the [$tenantOwnershipRelationshipName] static property on the [App\Filament\Resources\ActivityLogResource] resource class.

@mlselegant Can you upload to your GitHub a project that simulates this error? Without seeing the code, I really don't have much to work with.

@mlselegant @pfried I uploaded an example of how it works
https://github.com/rmsramos/tenancy

I downloaded you code https://github.com/rmsramos/tenancy and it works perfectly.

I found my issue as well.
In class ActivityLogResource extends \Rmsramos\Activitylog\Resources\ActivitylogResource

Instead of ActivityLogResource i renamed LogResource

And in model also
class Activity extends \Spatie\Activitylog\Models\Activity

the code should be like below:

use Spatie\Activitylog\Models\Activity as ModelsActivity;

class Activity extends ModelsActivity

Its work perfectly now.
Thank you very much @rmsramos for you support.

I must be blind somehow, i setup a repro here: https://github.com/pfried/activitylog_repro

@rmsramos If you can take a look that would be awesome, but I dont expect you to

okay it has to do with the pages (the only difference there was), I guess the pages itself do not get the model from the resource field

It seems I did not read carefully enough, this should be in bold, because otherwise it simply doesnt work

If you wish to change the resource on List and View page be sure to replace the getPages method on the new resource and create your own version of the ListPage and ViewPage classes to reference the custom CustomResource.

@pfried good suggestion, in the next release I will add this to the documentation.

But now the problems have been resolved, right?

@pfried @mlselegant
I have a YouTube channel, but only in Brazilian Portuguese, but nothing that a caption can't solve, if you can help by subscribing and sharing, it would be a lot of help.
NOTE. There are two videos talking about my ActivityLog plugin:
Filament: Spatie/Laravel-activitylog | Filament plugin by rmsramos
Activitylog | Filament plugin by rmsramos - NEW FEATURES

@rmsramos I have already subscribed your YouTube channel (Rômulo Ramos).
Through your channel i have learned many ideas about filamentphp.
Language does not matter. Action speaks louder than word. Your video tutorial is more enough.

sure thing, thanks for your help!

@mlselegant I've seen reports of slowness when using the debugbar package, is this your case?

Hi @rmsramos, i have a query. Is it possible to display table pagination info [Showing 1 to 5 of 20 results] at the top of the table?
By default this is display at the bottom of the table.