2017-06-19 4 views
0

En cours d'exécution dans un problème où les travaux ne peuvent pas se connecter à la base de données.Travail multi-locataire Laravel

Invalid catalog name: 1046 No database selected

J'ai besoin de définir le compte dans le travail donc j'ai une classe étendue pour vous assurer que le compte est envoyé avec le travail afin que je puisse assurer la base de données peut se connecter à la base de données correcte.

<?php 

namespace App\Jobs; 

use Illuminate\Support\Facades\DB; 

abstract class Job 
{ 
    protected $account; 

    public function start() 
    { 
     // runs when creating the job, so the config holds the correct value 
     $this->account = config('database.connections.tenant.database'); 
    } 

    public function handle() 
    { 
     // since the handle function runs outside of setting the job 
     // the database is no longer set in the config 
     config()->set('database.connections.tenant.database', $this->account); 
     // try to force it to reconnect incase it already did for some reason. 
     DB::reconnect(); 
    } 
} 

Ceci est ma version actuelle Je joue avec, les variations semblent ne pas l'affecter. Je exécute en principe start dans le constructeur, puis m'assure qu'il exécute le parent handle dans le travail afin qu'il amorce la configuration correcte de la base de données.

Le résultat final que je recherche est de définir la base de données des locataires comme account et lors de son exécution, elle utilise cette base de données pour toutes les requêtes.

Répondre

0

J'ai trouvé un moyen de contourner cela. Ce n'est pas joli, mais basé sur ce que je peux voir les files d'attente de larves ne gèrent pas vraiment ce genre de chose. D'abord j'ai supprimé le remplacement pour la fonction handle, tout ce dont j'avais vraiment besoin était de m'assurer que le compte sur lequel la file d'attente était nécessaire était disponible dans la classe Job.

abstract class Job 
{ 
    protected $account; 

    public function start() 
    { 
     // runs when creating the job, so the config holds the correct value 
     $this->account = config('database.connections.tenant.database'); 
    } 
} 

Ensuite, je déplacé le passage à la base de données de locataire correcte au AppServiceProvider dans la méthode boot.

Event::listen(JobProcessing::class, function ($event) { 
    if ($payload = $event->job->payload()) { 
     preg_match('/"account";s:[0-9]+:"(.*?)"/', $payload['data']['command'], $matches); 
     if (count($matches)) { 
     if (isset($matches[1])) { 
      config()->set('database.connections.tenant.database', $matches[1]); 
      config()->set('database.default', 'tenant'); 
     } 
     } 
    } 
}); 

Ce que j'ai fait ici est de regarder dans l'objet serialize pour le compte avec une certaine regex. Peut-être des améliorations à faire ici, mais travaille jusqu'à présent dans les tests. Il définit ensuite la base de données correcte une fois qu'il confirme le compte.

La raison pour laquelle je devais aller aussi loin est que le Job fait des requêtes lorsque le travail lui-même est sérialisé, donc pour passer le compte il fallait le faire avant qu'il soit sérialisé.