Derek Derek - 6 days ago 5
PHP Question

How to use Laravel Package LandLord

Im still fairly new to Laravel and have worked through some of the fundamental laracasts. Now I'm starting my first laravel project but I am stuck on how to use my first package "Landlord". Basically I need a setup for Multi-Tenants in my application. I have a company table and a user table, the user table has a company_id column. When a company registers it successfully creates the company and attaches the company_id to the user.

I assume Landlord is the best way to implement a multi-tenant application so I worked through the installation instructions and now I have it included in my app.

However the first line in the USAGE section says:
IMPORTANT NOTE: Landlord is stateless. This means that when you call addTenant(), it will only scope the current request.


Make sure that you are adding your tenants in such a way that it
happens on every request, and before you need Models scoped, like in a
middleware or as part of a stateless authentication method like OAuth.


And it looks like I need to attach a the
Landlord::addTenant('tenant_id', 1);
facade.

This may be a pretty simple answer I am overlooking but where is the best place to to use
addTenant
and do I have to redeclare it with every controller or model? Should I attach it when the user signs in, use it in my routes or use as a middleware? If it is a middleware is the following correct in order to pull the company_id from the current user and use it with
addTenant
?

Middleware:

public function handle($request, Closure $next){
$tenantId = Auth::user()->tenant_id;

Landlord::addTenant('tenant_id', $tenantId);

return $next($request);
}


UPDATE

Here is my middleware (MultiTenant.php)

<?php

namespace App\Http\Middleware;

use Closure;
use App\User;
use Illuminate\Support\Facades\Auth;

class MultiTenant
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/

public function handle($request, Closure $next)
{
if (Auth::check()) {
$tenantId = Auth::user()->company_id;

Landlord::addTenant('company_id', $tenantId); // Different column name, but same concept
}

return $next($request);
}
}


My routes/web.php

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| This file is where you may define all of the routes that are handled
| by your application. Just tell Laravel the URIs it should respond
| to using a Closure or controller method. Build something great!
|
*/

Route::get('/', function () {
return view('welcome');
});

Auth::routes();
Route::group(['middleware' => ['multitenant']], function () {
Route::get('/home', 'HomeController@index');

//Clients
Route::resource('clients', 'ClientController');
});


My Client.php Model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use HipsterJazzbo\Landlord\BelongsToTenants;

class Client extends Model
{
use BelongsToTenants;
//
protected $fillable = [
'organization',
];

}


https://github.com/HipsterJazzbo/Landlord#user-content-usage

Answer

While just one option, I also went the middleware route. I saw it as an easy way to implement it.

I added the middleware to my routes/web.php file:

Route::group(['middleware' => ['landlord']], function () {
    // Your routes
});

And my landlord middleware looks like this:

public function handle($request, Closure $next)
{        
    if (Auth::check()) {
        $tenantId = Auth::user()->company_id;

        Landlord::addTenant('company_id', $tenantId); // Different column name, but same concept
    }

    return $next($request);
}

Then I just add the trait to the models that I want scoped:

use HipsterJazzbo\Landlord\BelongsToTenant;

class User extends Authenticatable
{
    use BelongsToTenant;
}

Update

Also, make sure in your config/app.php file you have added landlord to the providers array:

'providers' => [
    // ...
    HipsterJazzbo\Landlord\LandlordServiceProvider::class
    // ...
],

And to the aliases array:

'aliases' => [

    // ...
    'Landlord'   => HipsterJazzbo\Landlord\Facades\Landlord::class,
    // ...
],

Then finally composer dump-autoload when completed to refresh the autoloading.