tenancy
tenancy copied to clipboard
Synced resources between tenants throws error when inserting new model on tenant
Describe the bug
When using Synced resources between tenants, the method updateResourceInCentralDatabaseAndGetTenants
on the listener UpdateSyncedResource
trows the following error:
SQLSTATE[42S22]:
Column not found: 1054 Unknown column 'code' in 'field list' (SQL: insert into
`users` (`name`, `email`, `password`, `remember_token`, `code`, `global_id`)
values (Hiram Hermann, [email protected], secret, fd9ca932-23c3-4e2f-abb6-38bc82cd92c4))
Steps to reproduce
Assuming we want to sync users:
- Set up Synced resources between tenants following the documentation
- Add some extra columns on the tenant's users migration, for example
code
- Try to add a NEW user on the tenant that doesn't exist on the central database
Expected behavior
Since the user doesn't exists on the central database the updateResourceInCentralDatabaseAndGetTenants
method will try to insert the new user on the central database using all the attributes from the model on the tenant's database, but like the columns from the tenants are not the same the insert can't happen.
Your setup
- Laravel version: 8.41.0
- stancl/tenancy version: 3.4.4
Does getSyncedAttributeNames()
not work?
Does
getSyncedAttributeNames()
not work?
To make it work I override the method updateResourceInCentralDatabaseAndGetTenants
in this specific part:
BEFORE
// If the resource doesn't exist at all in the central DB, we create
// the record with all attributes, not just the synced ones.
$centralModel = $event->model->getCentralModelName()::create($event->model->getAttributes());
event(new SyncedResourceChangedInForeignDatabase($event->model, null));
NOW
// If the resource doesn't exist at all in the central DB, we create
// the record with all attributes, not just the synced ones.
$centralModel = $event->model->getCentralModelName()::create($syncedAttributes); <----CHANGED THIS LINE
event(new SyncedResourceChangedInForeignDatabase($event->model, null));
Also I have to add global_id
in the fields to be synced.
I have same error :c
I guess there should be more configuration for how synced resources should be created, i.e. whether it should use all attributes, just the synced one, or something else. I'll add this in v4.
@stancl This is how I solve it, just exclude the id
when creating to the central model
$attr = collect($event->model->getAttributes())->except(['id'])->toArray()
$centralModel = $event->model->getCentralModelName()::create($attr);
event(new SyncedResourceChangedInForeignDatabase($event->model, null));
Then for temporary solution before the official release, I need to override UpdateSyncedResource.php
in my composer.json
"autoload": {
"exclude-from-classmap": [
"vendor/stancl/tenancy/src/Listeners/UpdateSyncedResource.php"
],
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
},
"files": [
"app/Overides/UpdateSyncedResource.php"
]
},
@amjeed-ay you can also make a new listener which extends the original one and override the method on it. then, replace it in the TenanceServiceProvider