Coder Social home page Coder Social logo

tenanti's Introduction

Multi-tenant Database Schema Manager for Laravel

Tenanti allow you to manage multi-tenant data schema and migration manager for your Laravel application.

tests Latest Stable Version Total Downloads Latest Unstable Version License Coverage Status

Version Compatibility

Laravel Tenanti
5.5.x 3.5.x
5.6.x 3.6.x
5.7.x 3.7.x
5.8.x 3.8.x
6.x 4.x
7.x 5.x
8.x 6.x

Installation

To install through composer, run the following command from terminal:

composer require "orchestra/tenanti"

Configuration

Next add the following service provider in config/app.php.

'providers' => [

    // ...
    Orchestra\Tenanti\TenantiServiceProvider::class,
    Orchestra\Tenanti\CommandServiceProvider::class,
],

The command utility is enabled via Orchestra\Tenanti\CommandServiceProvider.

Aliases

To make development easier, you could add Orchestra\Support\Facades\Tenanti alias for easier reference:

'aliases' => [

    'Tenanti' => Orchestra\Support\Facades\Tenanti::class,

],

Publish Configuration

To make it easier to configuration your tenant setup, publish the configuration:

php artisan vendor:publish

Usage

Configuration Tenant Driver for Single Database

Open config/orchestra/tenanti.php and customize the drivers.

<?php

return [
    'drivers' => [
        'user' => [
            'model' => App\User::class,
            'paths' => [
                database_path('tenanti/user'),
            ],
            'shared' => true,
        ],
    ],
];

You can customize, or add new driver in the configuration. It is important to note that model configuration only work with Eloquent instance.

Setup migration autoload

For each driver, you should also consider adding the migration path into autoload (if it not already defined). To do this you can edit your composer.json.

composer.json
{
    "autoload": {
        "classmap": [
            "database/tenant/users"
        ]
    }
}

Setup Tenantor Model

Now that we have setup the configuration, let add an observer to our User class:

<?php 

namespace App;

use App\Observers\UserObserver;
use Orchestra\Tenanti\Tenantor;
use Illuminate\Notifications\Notifiable;
use Orchestra\Tenanti\Contracts\TenantProvider;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements TenantProvider
{
    use Notifiable;

    /**
     * Convert to tenantor.
     * 
     * @return \Orchestra\Tenanti\Tenantor
     */
    public function asTenantor(): Tenantor
    {
        return Tenantor::fromEloquent('user', $this);
    }

    /**
     * Make a tenantor.
     *
     * @return \Orchestra\Tenanti\Tenantor
     */
    public static function makeTenantor($key, $connection = null): Tenantor
    {
        return Tenantor::make(
            'user', $key, $connection ?: (new static())->getConnectionName()
        );
    }

    /**
     * The "booting" method of the model.
     */
    protected static function boot()
    {
        parent::boot();

        static::observe(new UserObserver);
    }
}

and your App\Observers\UserObserver class should consist of the following:

<?php 

namespace App\Observers;

use Orchestra\Tenanti\Observer;

class UserObserver extends Observer
{
    public function getDriverName()
    {
        return 'user';
    }
}

Console Support

Tenanti include additional command to help you run bulk migration when a new schema is created, the available command resemble the usage available from php artisan migrate namespace.

Command Description
php artisan tenanti:install {driver} Setup migration table on each entry for a given driver.
php artisan tenanti:make {driver} {name} Make a new Schema generator for a given driver.
php artisan tenanti:migrate {driver} Run migration on each entry for a given driver.
php artisan tenanti:rollback {driver} Rollback migration on each entry for a given driver.
php artisan tenanti:reset {driver} Reset migration on each entry for a given driver.
php artisan tenanti:refresh {driver} Refresh migration (reset and migrate) on each entry for a given driver.
php artisan tenanti:queue {driver} {action} Execute any of above action using separate queue to minimize impact on current process.
php artisan tenanti:tinker {driver} {id} Run tinker using a given driver and ID.

Multi Database Connection Setup

Instead of using Tenanti with a single database connection, you could also setup a database connection for each tenant.

Configuration Tenant Driver for Multiple Database

Open config/orchestra/tenanti.php and customize the drivers.

<?php

return [
    'drivers' => [
        'user' => [
            'model' => App\User::class,
            'paths' => [
                database_path('tenanti/user'),
            ],
            'shared' => false,
        ],
    ],
];

By introducing a migration config, you can now setup the migration table name to be tenant_migrations instead of user_{id}_migrations.

Database Connection Resolver

For tenanti to automatically resolve your multiple database connection, we need to setup the resolver. You can do this via:

<?php namespace App\Providers;

use Orchestra\Support\Facades\Tenanti;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Tenanti::connection('tenants', function (User $entity, array $config) {
            $config['database'] = "acme_{$entity->getKey()}"; 
            // refer to config under `database.connections.tenants.*`.

            return $config;
        });
    }
}

Behind the scene, $config will contain the template database configuration fetch from "database.connections.tenants" (based on the first parameter tenants). We can dynamically modify the connection configuration and return the updated configuration for the tenant.

Setting Default Database Connection

Alternatively you can also use Tenanti to set the default database connection for your application:

use App\User;
use Orchestra\Support\Facades\Tenanti;

// ...

$user = User::find(5);

Tenanti::driver('user')->asDefaultConnection($user, 'tenants_{id}');

Most of the time, this would be use in a Middleware Class when you resolve the tenant ID based on Illuminate\Http\Request object.

tenanti's People

Contributors

crynobone avatar fernandobandeira avatar i906 avatar pacharrin avatar xputerax avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tenanti's Issues

5.3 compatibility?

Just wanna know how stable is Tenanti on Laravel 5.3. Is production ready?

Love your package, btw. Thanks!

Model find

I have a dumpable array for user user_1_posts, as I use Model (Posts: all ()) to retrieve records from the appropriate array.

Multiple database with shared master users

I'm trying to write a login page where the application connects to a master database and take the database name from the authenticated user. After that, the multiple database tenancy comes to make every model (except the users) to take the tenant connection with a different database.

Sadly, I'm unable to do it and the docs is very confusing regarding multiple databases. Anybody got anything similar that could shed some light into why I can only get a connection in the database set on .env file?

Hostname based ?

Hi, I have a quick question, does this package load data from database based on the hostnames? If yes then can it use multiple host names for same tenant_id .
and 3rd thing is that can this package use a single database with same amount of columns and load tenant data based on a specific column declared in each table let say tenant_id?

Thanks

Dynamic drivers

I'm using this package with Multi Database Connection version 3.3.

I currently need to separate migrations by groups, so I thought that maybe using the driver's would help doing this since each driver has it's own migration folder,

However when running the migrations i'm seeing that the migrations are running for all drivers.
I'm using a single User model, the driver is changed by a column, right now i'm checking inside the migrations if the injected model should run the migration, however, it still runs the migration and creates a register on the tenants_migrations table (it just doesn't update/create the tabe since im checking this).

Ideally it should just run the migration if the model belongs to the specific driver that I passed when calling the console command avoiding creating these records.

Could you share some info about how the package checks which connection should run the migration?

To give you more info here's some code:

middleware

$user = User::whereSubdomain($request->route()->parameter('subdomain'))->first();       
Tenanti::driver($user->driver)->asDefaultConnection($user, $user->subdomain);

provider

Tenanti::connection('tenants', function (User $entity, array $config) {
      $connection = config('orchestra.connections.'.$entity->subdomain);
      $config['database'] = $entity->subdomain;
      if($connection !== null) {
          $config = $connection + $config;
      }

       return $config;
});

config

   'drivers' => [
        'website' => [
            'model'     => 'App\User',
            'migration' => 'tenant_migrations',
            'path'      => database_path('tenant/website'),
            'shared'    => false,
        ],
        'ecommerce' => [
            'model'     => 'App\User',
            'migration' => 'tenant_migrations',
            'path'      => database_path('tenant/ecommerce'),
            'shared'    => false,
        ],
    ],

Also since the observer doesn't inject the model instance for the getDriverName and getConnectionName how can I dynamic change those?

Ps: Probably this would work with two different models however I think it would be nice to also support this using a single model, i gave an example with 2 drivers but i'll be using this with way more drivers...

Also this package is awesome, everything else is working great ๐Ÿ˜„

--path is not enabled in the make, migrate and rollback command.

I want to migrate a specific migration and i can't because --path is not enabled in the titled commands.

Default Laravel examples
php artisan make:migration alter_table_web_directories --path=database/migrations/batch_1
php artisan migrate alter_table_web_directories --path=database/migrations/batch_1
php artisan migrate:rollback alter_table_web_directories --path=database/migrations/batch_1

Dump-Autoload

screen shot 2015-04-13 at 1 59 28 am

Upon running php artisan tenanti:make {driver} {migration-name} I get the above. Seems to stem from line 67 in tenanti/src/Console/MigrateMakeCommand.php.

I changed line 67 from:
$this->call('dump-autoload');

to:
$this->call('clear-compiled');

This fixed the issue on Laravel 5.0.16. I can PR a fix for this if you like.

Perform delete on model throws exception

When you try to perform delete on any driver Model, It will throw an exception
No query results for model [App\Company] 15

Since the code for reset migration at Factory.php is responsible for that as

public function reset($database, $id = null, $pretend = false)
    {
        if (! is_null($id)) {
           //while executeById will look for an id which actually does not exist any more
            return $this->executeById($id, function ($entity) use ($database, $pretend) {
                $this->runReset($entity, $database, $pretend);
            });
        }
        $this->executeByChunk(function ($entities) use ($database, $pretend) {
            foreach ($entities as $entity) {
                $this->runReset($entity, $database, $pretend);
            }
        });
    }

Code at CompanyController

            $company = Company::findOrFail($companyId);
            // $company->manager()->forceDelete();
            $company->delete();

Error while trying to execute "php artisan tenanti:install account"

public function boot()
    {
        Tenanti::connection('account', function (Account $account, array $config) {
            $config['database'] = "saas_{$account->slug}";

            return $config;
        });
    }

For some reason this resolver is throwing the error below:

Argument 2 passed to App\Providers\AppServiceProvider::App\Providers\{closure}() must be of the type array, object given 

Looking good

eventhough I havent looked thoroughly.

Multi tenant is just sexy to me at this moment in life

Add some examples for console support

Great package!

Might be better to add some examples of console migrations.

Took me sometime to figure-out how to create migrations. (They were missing the table name)

If anyone else is looking, the code to generate migrations properly: (to create a table called 'cars')
php artisan tenanti:make user cars --create=true --table=cars

How to queue a specify tenant

I have a multi database tenanti using orchestral, i want to work with queue, i'm current using database driver, but the problem is that everytime i run the queue fail with message of "No database Selected"

Migrations in Tenant Databases

maybe i'm short in knowledge but i'm having problems with the migrations of the tables in the tenant databases.
my primary database is main and the tenant databases are names of companies, i get the value from a custom field in the table users (company).

I have the driver migrations in this path.

'drivers' => [
        'user' => [
            'model'  => App\User::class,
            'path'   => database_path('tenanti/user'),
            'shared' => false,
        ],
    ],

And i want to migrate with this sentence php artisan tenanti:migrate user but i get this error.

[ErrorException]
Creating default object from empty value

do you know what is happening? do you need more information?

I thank you in advance.
David

Queries with() are failing.

Hello

I'm testing out Tenanti and I have successfully installed it, each time I create a new Tenant (Company) it runs the migrations just fine. The issue is I get an error when trying to load in related data using the with key.

I'm using a single database with tenant prefixed tables The tables in my database are as follows ...

company_1_members
company_1_migrations
companies
migrations

Here is the route and query ...

public function show($id)
{
    return Company::with(['members'])->find($id);
}

The error I get is ...

SQLSTATE[42S02]: Base table or view not found: 
1146 Table 'laravel_tenanti.members' doesn't exist 
(SQL: select * from `members` where `members`.`company_id` in (1))

I can see where the error is. The table name is incorrect, it should be ...

laravel_tenanti.company_1_members

I think I'm missing something ...

What should be in the middleware or attached to the query to make it scope correctly?

[3.3] Migration runDown isn't working

When using reset, or refresh, for example, the package isn't running the runDown migration, instead it's always pretending to run the migration and dumps the result on the console.

I've checked and the content that is being passed to the $pretend variable is

[
    'pretend' => false,
]

However on Migrator.php it's checking it like:

if ($pretend) {
    return $this->pretendToRun($instance, 'down');
}

I'll try to create a PR for this, but i'm not sure if this also happens with lower versions of the package so I'm posting here beforehand so you can check the issue too...

Database creation example

Do you have an example for the actual database creation for a multi-database setup? Do we actually have to call the create command?

When I call php artisan tenanti:migrate account

I get this error:

SQLSTATE[HY000] [1049] Unknown database 'app_account_1'

where my driver and model are both called account. Should I be doing something like this?

Tenanti::connection('tenants', function (Account $entity, array $config) {
            $config['database'] = "app_account_{$entity->getKey()}";
            // pseudo code
           if not database exists $config['database'] 
                create database;
            return $config;
        });

or is the creation of databases already handled by tenanti?

example project or code

hello,

i'm wondering if maybe someone could share any example project or code on how this exactly is implemented in practice. i've tried around multi database but there are certain things i do not understand correctly.

basically i'm having a centralized database for accounting (acounting_db), which stores all accounts and tenant instances available. when a new tenant instance is created, a new tent database should be created and the default database migration should be performed. this step happens for every new instance created. the new tenant databases contain all the data related to the tenants instance and are named like tenant_db_1, tenant_db_2, tenant_db_3, etc.. an overview of all available instances is kept in a table inside the accounting_db.

when a user logs in, i want to select the instance_id he belongs to from the accounting_db and open up a second db connection to his assigned tenant_db_x.

is tenanti capable of achieving this and how would i perform the according (second) tenant database connection after a user logs in? maybe i need a middleware?

thanks in advance

3.4.x@dev migrations

Hello,

I created driver user with php artisan tenanti:install user and then test migration with php artisan tenanti:make user test which resulted to Created Migration: 2017_03_08_083742_user_tenant_test

Now in the migration file am I supposed to use the Schema builder to make the tenanti migrations? I can't find example from the documentation.

I tried to use Schema. up() function creates the tables but the down() does not work when I try php artisan tenanti:refresh user. It gives me error [Symfony\Component\Debug\Exception\FatalThrowableError] Type error: Argument 2 passed to Illuminate\Database\Migrations\Migrator::resetMigrations() must be of the type array, string given, called in /home/vagrant/Code/erp/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator. php on line 277 for Schema::dropIfExists('test');

Laravel version 5.4.15
Tenanti is set to Multi Database Connection

Lumen Support

Hello, first of all thanks for this package it saved me decades :) Now I have to do SaaS app in Lumen and i want to use this package, but i can't figure out how to install it. The main problem is that

  [Symfony\Component\Debug\Exception\FatalThrowableError]                                                                                            
  Type error: Argument 1 passed to Orchestra\Tenanti\CommandServiceProvider::Orchestra\Tenanti\{closure}() must be an instance of Illuminate\Contra  
  cts\Foundation\Application, instance of Laravel\Lumen\Application given, called in /home/user/PersonalProjects/easycart/vendor/illuminate/conta  
  iner/Container.php on line 726   

So my question is do you plan do support Lumen ?

Update to laravel 5.5

Hi

When update to laravel 5.5?
I have laravel 5.5 and when I run composer update show me this error.
but It work on laravel 5.4 correctly

Problem 1
- orchestra/tenanti v3.3.5 requires illuminate/console ~5.3.26 -> satisfiable by illuminate/console[5.3.x-dev] but these conflict with your requirements or minimum-stability.
- orchestra/tenanti v3.3.4 requires illuminate/console ~5.3.26 -> satisfiable by illuminate/console[5.3.x-dev] but these conflict with your requirements or minimum-stability.
- orchestra/tenanti v3.3.3 requires illuminate/console ~5.3.26 -> satisfiable by illuminate/console[5.3.x-dev] but these conflict with your requirements or minimum-stability.
- orchestra/tenanti v3.3.2 requires illuminate/console ~5.3.26 -> satisfiable by illuminate/console[5.3.x-dev] but these conflict with your requirements or minimum-stability.
- Conclusion: remove laravel/framework v5.5.9
- Conclusion: don't install laravel/framework v5.5.9
- Conclusion: don't install laravel/framework v5.5.8
- Conclusion: don't install laravel/framework v5.5.7
- Conclusion: don't install laravel/framework v5.5.6
- Conclusion: don't install laravel/framework v5.5.5
- Conclusion: don't install laravel/framework v5.5.4
- Conclusion: don't install laravel/framework v5.5.3
- Conclusion: don't install laravel/framework v5.5.2
- Conclusion: don't install laravel/framework v5.5.1

Commands failed

I am using Laravel 5.3 using multiple database connection with sqlite driver. Got error when run php artisan tenanti:rollback user the tables are deleted but got following errors.

[Symfony\Component\Debug\Exception\FatalThrowableError]
Call to undefined method Orchestra\Tenanti\Console\RollbackCommand::writeMigrationOutput()

With php artisan tenanti:refresh user the output is very strange, it seems to be drops all tables but then saying Nothing to migrate

UserTenantCreatePostsTable [users:1]: drop table "posts"
....
Nothing to migrate.

When run php artisan tenanti:reset user no error thrown but the tables are not deleted.

Support uuid as tenant database id

I see that your implementation bind the database with Entity Id, which easily be conflicted after a reset migration. I propose to implement the uuid method instead, which can be randomize uniquely, or an option to connection methods (asConnection) on Orchestra\Tenanti\Migrator\Operation trait so that developer can by pass their own database name, instead of restrictedly following the '_{id}' pattern.

Route Model Binding type error with Route::resource()

Hello.
I'm developing an API using Laravel's Resource Controllers features and using Orchestral Multi-tenant Database Schema Manager as a Single Database.

In my control methods I am using the Route Model Binding to injecting a model ID to a route or controller action, often query to retrieve the model that corresponds to that ID.

Some relevant routes from my API:

| POST      | api/v1/{tenant}/fornecedores                     | store  | App\Http\Controllers\Api\Fornecedor\FornecedorController@store  | api,tenant,jwt.auth |
| GET|HEAD  | api/v1/{tenant}/fornecedores                     | index  | App\Http\Controllers\Api\Fornecedor\FornecedorController@index  | api,tenant,jwt.auth |
| GET|HEAD  | api/v1/{tenant}/fornecedores/count               |        | App\Http\Controllers\Api\Fornecedor\FornecedorController@count  | api,tenant,jwt.auth |
| PUT|PATCH | api/v1/{tenant}/fornecedores/{fornecedor}        | update | App\Http\Controllers\Api\Fornecedor\FornecedorController@update | api,tenant,jwt.auth |
| GET|HEAD  | api/v1/{tenant}/fornecedores/{fornecedor}        | show   | App\Http\Controllers\Api\Fornecedor\FornecedorController@show   | api,tenant,jwt.auth |
| GET|HEAD  | api/v1/{tenant}/fornecedores/{fornecedor}/audits |        | App\Http\Controllers\Api\Fornecedor\FornecedorController@audits | api,tenant,jwt.auth |
...

An example of my API route file:

// API V1
Route::group(['prefix' => 'v1/{tenant}', 'middleware' => 'tenant'], function () {
    
    // Fornecedores
    Route::group(['prefix' => 'fornecedores'], function () {
        Route::get('count', 'Api\Fornecedor\FornecedorController@count');
        Route::get('{fornecedor}/audits', 'Api\Fornecedor\FornecedorController@audits');

        Route::resource('/', 'Api\Fornecedor\FornecedorController', [
            'parameters' => ['' => 'fornecedor'],
            'except' => ['create', 'edit', 'destroy']
        ]);
    });
});

These are some methods of my FornecedorController.php:

public function index()
{
    return $this->fornecedorService->getFornecedoresPaginate();
}

// This is line 48 (throw below):
public function show(Fornecedor $fornecedor)
{
    return $fornecedor;
}

However when trying to access the URL that uses the Route Model Binding I get the following error:

URL: /api/v1/1/fornecedores/1

FatalThrowableError in FornecedorController.php line 48:
Type error: Argument 1 passed to App\Http\Controllers\Api\Fornecedor\FornecedorController::show() must be an instance of App\Models\Fornecedor, string given

And this is the all trace:

in FornecedorController.php line 48
at FornecedorController->show('1', object(Fornecedor))
at call_user_func_array(array(object(FornecedorController), 'show'), array('tenant' => '1', 'fornecedor' => object(Fornecedor))) in Controller.php line 55
at Controller->callAction('show', array('tenant' => '1', 'fornecedor' => object(Fornecedor))) in ControllerDispatcher.php line 44
at ControllerDispatcher->dispatch(object(Route), object(FornecedorController), 'show') in Route.php line 203
at Route->runController() in Route.php line 160
at Route->run() in Router.php line 559
at Router->Illuminate\Routing\{closure}(object(Request)) in Pipeline.php line 30
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in GetUserFromToken.php line 46
at GetUserFromToken->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in VerifyTenant.php line 25
at VerifyTenant->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in SubstituteBindings.php line 41
at SubstituteBindings->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in ThrottleRequests.php line 49
at ThrottleRequests->handle(object(Request), object(Closure), '60', '1') in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Pipeline.php line 102
at Pipeline->then(object(Closure)) in Router.php line 561
at Router->runRouteWithinStack(object(Route), object(Request)) in Router.php line 520
at Router->dispatchToRoute(object(Request)) in Router.php line 498
at Router->dispatch(object(Request)) in Kernel.php line 174
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request)) in Pipeline.php line 30
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in HandleCors.php line 36
at HandleCors->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in TransformsRequest.php line 30
at TransformsRequest->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in TransformsRequest.php line 30
at TransformsRequest->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in ValidatePostSize.php line 27
at ValidatePostSize->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in CheckForMaintenanceMode.php line 46
at CheckForMaintenanceMode->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Pipeline.php line 102
at Pipeline->then(object(Closure)) in Kernel.php line 149
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 116
at Kernel->handle(object(Request)) in index.php line 53

I could verify that there is apparently a confusion when retrieving the parameters. When inspecting route parameters, this is the result:

public function show($fornecedor)
{
    dd(\Route::current()->parameters());
}

URL: /api/v1/1/fornecedores/18

Result:

array:2 [
  "tenant" => "1"
  "fornecedor" => "18"
]

And when trying to retrieve the provider's route:

public function show($fornecedor)
{
    dd($fornecedor);
}

URL: /api/v1/1/fornecedores/18

Result:

"1"

Even using bind the parameter I get is not correct.
The other routes that do not use a second parameter are ok.

Thanks!

Error with Middleware

I'm getting an InvalidArgumentException thrown when I try to use the example in the docs for a multi-database setup:

    public function handle($request, Closure $next)
    {
        // Get account id
        $accountId = $request->route()->parameter('accountId');

        // Get account from id
        $account = Account::findOrFail($accountId);

        \Tenanti::driver()->asDefaultConnection($account, 'tenants_{id}');

        return $next($request);
    }

I get

InvalidArgumentException in TenantiManager.php line 52:
Default driver not implemented.

Am I doing this the wrong way?

Broken setupDriverConfig

I'm not sure if this will affect normal installation of tenanti since I'm using it in more complex way than the standard behavior. But judging from the code in the TenantiManager::connection

the array set for the $this->config will never have driver key thus when TenantiSetupDriverConfig is called it will always return null

        // This will always return null since there are no array key by driver name ever set
        if (isset($this->config[$driver])) {
            return;
        }

        // this will also always return null since no drivers key ever set
        if (is_null($config = Arr::pull($this->config, "drivers.{$driver}"))) {
            return;
        }

When changed to :

        if (is_null($config = Arr::get($this->config, "connection.template"))) {
            return;
        }

it will work again as expected.

not sure if this is a bug or just my installation that need this, so I didnt make proper fork and pull request.

Thank you for the great plugin btw

Noob question about getting data

Hello! This might be bit out of scope but still very much relevant for this project and there should be more documentation for this.. Or am I just missing it..?

So, I have the project set up and for now it works perfectly!
However I really don't understand how to retrieve the data/eloquent relationships..

Example:

I have users
Each user has multiple posts. The posts are stored in tenant tables. So the user with id of 1 has his posts inside users_1_posts table.

How do I set up the relationship so that for class User

class User extends Authenticatable
{
    //...
    public function posts()
    {
        return $this->hasMany(\App\Post::class);
    }
}

It would be very fitting to give some examples of how to deal with the data fetching/connections together with this package.

Using seeders in Single Database

Hi,
I'm trying to use seeders to set some data for users like below:
public function run()
{
$user = User::find(1);
Address::setTable("user_{$user->id}events");
Address::create([
'address' => 'some address for user 1',
'number' => '123',
'city' => 'some city for user 1',
]);
$user = User::find(2);
Address::setTable("user
{$user->id}_events");
Address::create([
'address' => 'some address for user 2',
'number' => '321',
'city' => 'some city for user 2',
]);
}
But I get this error when running php artisan db:seed

[Illuminate\Database\QueryException]
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'app_tenant.addresses' doesn't exist (SQL: insert into addresses (address, number, city, updated_at, created_at) values (some address for user 1, 123
some city for user 1, 2017-10-06 18:45:06, 2017-10-06 18:45:06))

[PDOException]
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'app_tenant.addresses' doesn't exist

The correct table should be user_1_addresses, but it tries to find in addresses table which does not exist. How can I set up a specific table to create, find, delete, update data?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.