2015-09-06 14 views
13

widziałem w kilku miejscach do „Trzymaj się z dala” od tego, ale niestety - to jest jak mój DB jest zbudowany:laravel Należy do relacji z różnych baz danych nie działa

class Album extends Eloquent { 

    // default connection 

    public function genre() { 
     return $this->belongsTo('genre'); 
    } 

i tabela Gatunek:

class Genre extends Eloquent { 
    protected $connection = 'Resources'; 

} 

Moja database.php:

'Resources' => array(
        'driver' => 'mysql', 
        'host'  => 'localhost', 
        'database' => 'resources', 
        'username' => 'user', 
        'password' => 'password', 
        'charset' => 'utf8', 
        'collation' => 'utf8_unicode_ci', 
        'prefix' => '', 
      ), 

'mysql' => array(
        'driver' => 'mysql', 
        'host'  => 'localhost', 
        'database' => 'my_data', 
        'username' => 'user', 
        'password' => 'password', 
        'charset' => 'utf8', 
        'collation' => 'utf8_unicode_ci', 
        'prefix' => '', 
      ), 

i gdy próbuję uruchomić

Album::whereHas('genre', function ($q) { 
    $q->where('genre', 'German HopScotch'); 
}); 

nie wybrać prawidłowo (nie dodać nazwę bazy danych do tabeli "gatunki"):

Next exception 'Illuminate\Database\QueryException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'my_data.genres' doesn't exist 

Ważne, aby pamiętać, że działa to doskonale:

Album::first()->genre; 

Aktualizacja

Najlepsze, co do tej pory znalazłem, to użycie metody "od" konstruktora do konkretnej nazwij poprawne połączenie. odkryłem, że budowniczy wewnątrz zapytania można otrzymać „od”

Album::whereHas('genre', function ($q) { 
    $q->from('resources.genres')->where('genre', 'German HopScotch'); 
}); 

To jest przyzwoity rozwiązanie, ale wymaga to mnie kopać w php bazy i znaleźć dobry sposób, aby uzyskać odpowiednią tabelę i bazy danych nazwa z relacji "gatunek".

Będę wdzięczny, jeśli ktoś inny będzie mógł zbudować na tym rozwiązaniu i uczynić go bardziej ogólnym.

+0

Jaka wersja laravel należy rozwiązać tę kwestię? –

+0

Używam laravel 4.2 – NiRR

Odpowiedz

6

To jest moje własne rozwiązanie i ogólnie działa dla mnie, ale jest mega-skomplikowane.

Używam metody budowania "od" do prawidłowego ustawienia tabeli i bazy danych w podzapytaniu. Po prostu muszę podać prawidłowe informacje w środku.

Załóżmy podzapytanie może być tak skomplikowane, jak „genres.sample” lub jeszcze głębiej (co oznacza albumy ma związek z gatunków, a gatunki ma związek z próbek) to jak

$subQuery = 'genres.samples'; 
$goDeep = (with (new Album)); 

$tableBreakdown = preg_split('/\./', $subQuery); // = ['genres', 'samples'] 

// I recurse to find the innermost table $album->genres()->getRelated()->sample()->getRelated() 
foreach ($tableBreakdown as $table) 
    $goDeep = $goDeep->$table()->getRelated(); 

// now I have the innermost, get table name and database name 

$alternativeConnection = Config::get("database.connections." . $goDeep->getConnectionName() . ".database"); // should be equal to the correct database name 

$tableName = $goDeep->getTable(); // I have to use the table name in the "from" method below 

Album::whereHas($subQuery, function ($q) use ($alternativeConnection, $tableName) { 
$q->from("$alternativeConnection.$tableName"); 
$q->where(....... yadda yadda); 
    }); 

tl :dr;

Album::whereHas('genres', function ($q) { 
    $q->from('resources.genres')->where(....); 
}); 
5

znalazłem bardzo dobry artykuł o tym tutaj: http://fideloper.com/laravel-multiple-database-connections

Zasadniczo trzeba określić swoje dwa połączenia w pliku konfiguracyjnym tak:

<?php 
return array(

    'default' => 'mysql', 

    'connections' => array(

     # Our primary database connection 
     'mysql' => array(
      'driver' => 'mysql', 
      'host'  => 'host1', 
      'database' => 'database1', 
      'username' => 'user1', 
      'password' => 'pass1' 
      'charset' => 'utf8', 
      'collation' => 'utf8_unicode_ci', 
      'prefix' => '', 
     ), 

     # Our secondary database connection 
     'mysql2' => array(
      'driver' => 'mysql', 
      'host'  => 'host2', 
      'database' => 'database2', 
      'username' => 'user2', 
      'password' => 'pass2' 
      'charset' => 'utf8', 
      'collation' => 'utf8_unicode_ci', 
      'prefix' => '', 
     ), 
    ), 
); 

więc dwa połączenia są aliasem mysql i mysql2.

Wtedy można powiedzieć wymowny który „alias” używać tak:

<?php 

class SomeModel extends Eloquent { 

    protected $connection = 'mysql2'; 

} 

Następnie można skonfigurować swoje relacje jak normalne.

tl; dr: Zasadniczo zamiast podając nazwę tabeli jako $connection w wymowny określić alias połączenia w konfiguracji i powinno działać.

+1

to jest dokładnie to, co zrobiłem, myślę, że w moim przykładzie było jasne, że używam modelu i ustawiłem połączenie. Możesz wypróbować dokładnie to i zobaczyć, że używanie "whereHas" nie działa poprawnie, jak już wspomniałem. – NiRR

+0

Czy możesz pokazać mi swój plik konfiguracyjny 'database.php'? – Jamesking56

+0

Mam zaktualizowane pytanie z moim database.php – NiRR

0

Aby rozpocząć zmianę "Zasoby" w database.php przez "zasoby", będzie lepiej!

Jestem ciekawa, możesz spróbować?

Album::whereHas('genre', function ($q) { 
    $q->setConnection('resources')->where('genre', 'German HopScotch'); 
}); 
+0

:(Wezwanie do niezdefiniowanej metody Iluminuj \ Baza danych \ Zapytanie \ Budowniczy :: setConnection() – NiRR

0

Miałem ten sam problem, gdy związek nie pracował poza model połączenia.

Moim rozwiązaniem było przesłonięcie metody belongsToMany na modelu próbującym ustalić. Zobacz przykład poniżej.

<?php 

namespace App\Model; 

use Illuminate\Database\Eloquent\Model; 
use Illuminate\Database\Eloquent\Relations\BelongsToMany; 

class ConnectionModel extends Model 
{ 
    /** 
    * Override method to allow inheriting connection of parent 
    * 
    * Define a many-to-many relationship. 
    * 
    * @param string $related 
    * @param string $table 
    * @param string $foreignKey 
    * @param string $otherKey 
    * @param string $relation 
    * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany|BelongsToMany 
    */ 
    public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null) 
    { 
     // If no relationship name was passed, we will pull backtraces to get the 
     // name of the calling function. We will use that function name as the 
     // title of this relation since that is a great convention to apply. 
     if (is_null($relation)) { 
      $relation = $this->getBelongsToManyCaller(); 
     } 

     // First, we'll need to determine the foreign key and "other key" for the 
     // relationship. Once we have determined the keys we'll make the query 
     // instances as well as the relationship instances we need for this. 
     $foreignKey = $foreignKey ?: $this->getForeignKey(); 

     $instance = new $related; 

     // get connection from parent 
     $instance->setConnection(parent::getConnectionName()); 

     $otherKey = $otherKey ?: $instance->getForeignKey(); 

     // If no table name was provided, we can guess it by concatenating the two 
     // models using underscores in alphabetical order. The two model names 
     // are transformed to snake case from their default CamelCase also. 
     if (is_null($table)) { 
      $table = $this->joiningTable($related); 
     } 

     // Now we're ready to create a new query builder for the related model and 
     // the relationship instances for the relation. The relations will set 
     // appropriate query constraint and entirely manages the hydrations. 
     $query = $instance->newQuery(); 

     return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation); 
    } 
} 
0

Miałem ten sam problem, gdy związek nie pracował off połączenia nadrzędnego.

Moim rozwiązaniem było przesłonięcie metody belongsToMany na modelu próbującym ustalić. Zobacz przykład poniżej.

<?php 

namespace App\Model; 

use Illuminate\Database\Eloquent\Model; 
use Illuminate\Database\Eloquent\Relations\BelongsToMany; 

class ConnectionModel extends Model 
{ 
    /** 
    * Override method to allow inheriting connection of parent 
    * 
    * Define a many-to-many relationship. 
    * 
    * @param string $related 
    * @param string $table 
    * @param string $foreignKey 
    * @param string $otherKey 
    * @param string $relation 
    * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany|BelongsToMany 
    */ 
    public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null) 
    { 
     // If no relationship name was passed, we will pull backtraces to get the 
     // name of the calling function. We will use that function name as the 
     // title of this relation since that is a great convention to apply. 
     if (is_null($relation)) { 
      $relation = $this->getBelongsToManyCaller(); 
     } 

     // First, we'll need to determine the foreign key and "other key" for the 
     // relationship. Once we have determined the keys we'll make the query 
     // instances as well as the relationship instances we need for this. 
     $foreignKey = $foreignKey ?: $this->getForeignKey(); 

     $instance = new $related; 

     $instance->setConnection(parent::getConnectionName()); 

     $otherKey = $otherKey ?: $instance->getForeignKey(); 

     // If no table name was provided, we can guess it by concatenating the two 
     // models using underscores in alphabetical order. The two model names 
     // are transformed to snake case from their default CamelCase also. 
     if (is_null($table)) { 
      $table = $this->joiningTable($related); 
     } 

     // Now we're ready to create a new query builder for the related model and 
     // the relationship instances for the relation. The relations will set 
     // appropriate query constraint and entirely manages the hydrations. 
     $query = $instance->newQuery(); 

     return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation); 
    } 
} 
0

Dodaj zmienną połączenia z połączeniem domyślnym na modelu Gatunek:

protected $connection = 'mysql'; 

miałem pewne problemy z relacji przez nie dodanie tego produktu.

1

Wygląda Eager Loading będą robić to, co chcesz zrobić

Album::with(['genre' => function ($q) { 
    $q->connection('Resources') 
    ->where('genre', 'German HopScotch'); 
}]); 
Powiązane problemy