phplaravelmulti-tenantdistributed-database

How to use laravel notifications for serialized models in a cross database setup?


My current setup is that User and Notification are saved to my main database, Post is saved to a different database. User and Notification db connections are:

protected $connection = "main";

and Post db connections is:

protected $connection = "second";

My notification table is saved to the main database. I have a notification class called "PostReplied" that takes a $post as a parameter. so it's serialized when it's queued. When it started processing this job, it's trying to get the post from the "main" database instead of Post's connection "second" database.

Any suggestions on how to make the notifications work with cross-database models?


Solution

  • Solution 1

    Depending on what multi-tenant setup you use, it may rely on setting the connection name on the model. You could for instance set the connection for the Post model like this:

    Models/Post.php

    /**
     * Get the current connection name for the model.
     *
     * @return string|null
     */
    public function getConnectionName()
    {
        return 'tenant_connection';
    }
    

    Then you need to define a tenant_connection key in the database.connections config (config/database.php). I know hyn/multitenant does it like this (https://packagist.org/packages/hyn/multi-tenant).

    Solution 2

    One other, lesser way to do it is to switch connection on-the-go while you are creating the queries, like so:

    DB::setDefaultConnection('custom_connection');
    Post::query()->where('status', 1)->get();
    
    // Revert to default connection, assuming `mysql` here.
    DB::setDefaultConnection('mysql');
    

    This gives you more freedom but your code gets messier and I don't recommend it.

    Solution 3

    This one can also make your code harder to understand. You can incorporate the database name in your queries, like so:

    DB::table('database1.posts as d1p')
        ->leftjoin('database2.users as d2u', 'd1p.user_id', '=', 'd2u.id');        
    

    You can probably mix and match this using Eloquent builder functions.