romegasoftware/Multitenancy

Could the documentation include examples for database seeding using model factories?

devonmather opened this issue · 14 comments

Not sure if I'm missing something but when trying to create tenant's and users using model factories, it doesn't seem to be working.

Kind Regards

@devonmather could you please paste your factory code here?

I removed the package and the changes I had made after trying to implement it. I was just curious in case the docs could have a section about it as that was where I got hung up. Feel free to close this if that isn't on the documentation roadmap.

factory(RomegaDigital\Multitenancy\Models\Tenant::class, 2)->create();
factory(App\User::class, 2)->create()
RomegaDigital\Multitenancy\Models\Tenant::first()->save(App\User::first()->toArray());

Sorry for the hassle. After the replies here I had another go at it, however, this seems to fail silently. And the tenant_user table remains empty?

@devonmather Looks like you need to simply define a factory for your Tenant model (or ours, if you're not extending it). Here's how I've done it:

//Your code with syntax fixes
factory(\RomegaDigital\Multitenancy\Models\Tenant::class, 2)->create();
factory(\App\User::class, 2)->create();
\RomegaDigital\Multitenancy\Models\Tenant::first()->save(\App\User::first()->toArray());
//TenantFactory.php
$factory->define(\RomegaDigital\Multitenancy\Models\Tenant::class, function (Faker $faker) {
    return [
        'name' => $faker->unique()->company,
        'domain' => $faker->unique()->word,
    ];
});

I just pushed to the master branch a factory that the package will provide so you don't have to write your own out of the box.

That's indeed what I had in my factory. Tenants were being created in the tenant's table correctly.

It just appears to me this isn't doing anything?
RomegaDigital\Multitenancy\Models\Tenant::first()->save(App\User::first()->toArray());

I would expect that to add a line in the table 'tenant_user'?

@devonmather that's right. And the code I pasted in my last response is exactly what I used to accomplish this. My next instinct would be to check your User model... could you copy the declaration of the class and it's trait uses?

Closing the issue. If further details are provided, we can reopen.

Hi @bradenkeith !
I've got the same problem as @devonmather here. :)
The line RomegaDigital\Multitenancy\Models\Tenant::first()->save(App\User::first()->toArray()); has no effect on the database table tenant_user and does not add an entry there.

Is this really the correct way to do this? As there's no reference for the tenant_user table anywhere in the Tenant model.

My current POC seeder code looks like this...

Use statements:

use App\Models\User;
use RomegaDigital\Multitenancy\Models\Tenant;

Code itself:

$user = User::where('email', 'admin@test.local')->first()->toArray();

$tenant = Tenant::create([
    'name' => 'User Tenant',
    'domain' => 'user',
]);
$tenant->save($user);

The code of the user model:

<?php

namespace App\Models;

use Iben\Statable\Statable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;
use RomegaDigital\Multitenancy\Traits\HasTenants;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens, HasTenants, HasRoles, Notifiable, Statable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    protected function getGraph()
    {
        return 'user'; // the SM config to use
    }
}

Do you possibly see anything wrong with my code?

Thank you very much for helping me with this!

Best wishes
Tom

Ok found the mistake and made a PR for the readme file to include the fix :)

Yes, this is a Laravel relationship and therefore accepts the model, not an array. Thanks for the PR.

Thanks for this, looks like the update on the readme cleared it up for me. However, timestamps aren't being set on the tenant_user table.

I believe the relationship needs ->withTimestamps() appended to it as below.

/**
* A Tenant belongs to many users.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users(): BelongsToMany
{
    return $this->belongsToMany(config('multitenancy.user_model'))->withTimestamps();
}

@Naoray Can you take a look at @devonmather 's comment?