我在几个地方看到过“远离”这个,但唉 - 这就是我的数据库的构建方式:
class Album extends Eloquent {
// default connection
public function genre() {
return $this->belongsTo('genre');
}
和类型表:
class Genre extends Eloquent {
protected $connection = 'Resources';
}
我的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' => '',
),
当我尝试运行时
Album::whereHas('genre', function ($q) {
$q->where('genre', 'German HopScotch');
});
它没有正确选择(不将数据库名称添加到表“genres”):
Next exception 'Illuminate\Database\QueryException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'my_data.genres' doesn't exist
重要的是要注意这是完美的:
Album::first()->genre;
更新
到目前为止,我发现的最好的方法是使用构建器的“from”方法来专门命名正确的连接。 我发现查询中的构建器可以接收“from”
Album::whereHas('genre', function ($q) {
$q->from('resources.genres')->where('genre', 'German HopScotch');
});
这是一个不错的解决方案,但它需要我在数据库中挖掘php并找到从关系'genre'获取正确的表和数据库名称的好方法。
如果其他人能够在此解决方案的基础上进一步发展并使其更加通用,我将不胜感激。
答案 0 :(得分:7)
这是我自己的解决方案,它对我来说一般都适用,但它很复杂。
我正在使用构建器“from”方法在子查询中正确设置表和数据库。我只需要在里面传递正确的信息。
假设子查询可以像“genres.sample”一样复杂甚至更深(这意味着专辑与流派有关系,并且流派与样本有关系) 这就是
$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:博士;
Album::whereHas('genres', function ($q) {
$q->from('resources.genres')->where(....);
});
答案 1 :(得分:3)
您应该先克隆,否则您将更改模型的默认连接。它会产生副作用。
class Album extends Eloquent {
public function genre() {
$newResource = clone $this;
return $newResource->setConnection('Resources')->belongsTo('genre');
}
}
答案 2 :(得分:2)
我在这里发现了一篇非常好的文章:http://fideloper.com/laravel-multiple-database-connections
您基本上必须在配置文件中指定两个连接,如下所示:
<?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' => '',
),
),
);
因此,您的两个连接的别名为mysql
和mysql2
。
然后你可以告诉雄辩使用哪个“别名”如下:
<?php
class SomeModel extends Eloquent {
protected $connection = 'mysql2';
}
然后你可以像平常一样设置你的关系。
tl; dr:基本上不是在eloquent中将表名指定为$connection
,而是在配置中指定连接别名,它应该有效。
答案 3 :(得分:2)
看起来Eager Loading会做你想做的事
Album::with(['genre' => function ($q) {
$q->connection('Resources')
->where('genre', 'German HopScotch');
}]);
答案 4 :(得分:2)
这是它为我工作的方式:
在我的.env和config / database.php中,我定义了其他连接=> How to use multiple databases in Laravel
我以这种方式更新了模型:
class MyOtherDBModel extends Model
{
protected $table = 'tablename';
protected $connection = 'mysql2';
public function __construct(array $attributes = [])
{
$this->table = env('DB_DATABASE_2').'.'.$this->table;
parent::__construct();
}
}
class MyModel extends Model
{
public function myOtherModel()
{
return $this->belongsTo(MyOtherDBModel::class, 'field', 'field');
}
}
现在我可以打电话
$query = MyModel::whereHas('myOtherModel');
答案 5 :(得分:1)
使用类型模型上的默认连接添加连接变量:
protected $connection = 'mysql';
通过不添加此关系,我遇到了一些关系问题。
答案 6 :(得分:1)
我在Laravel 5.6上遇到了同样的问题。在多对多方案中,假设我ModelA
的连接是默认连接,我所做的是以下内容:
1.-在关系中添加模式名称:
// From ModelA and default connection (a.k.a connection1)
$this->belongsToMany('ModelB', 'schema.pivot-table-name');
// From ModelB and connection2
$this->belongsToMany('ModelA', 'schema.pivot-table-name');
2.-覆盖ModelB
类中的连接参数以及将模式指定为覆盖的$table
属性中的前缀,例如
protected $connection = 'connection2';
protected $table = 'connection2-schema-name.table';
3.-如果要求数据透视表的自定义行为,我所做的只是实现所需的模型,并通过模型关系上的->using('PivotModel');
函数指定它(如{{中所述) 3}})。最后我做了与上面第2点相同的事情,但是在枢轴模型上
我还没有尝试过,但我想其他类型的关系也是如此,至少对于基本关系(一对一,一对多等)
答案 7 :(得分:1)
laravel v5.7及更高版本的解决方案
class Album extends Eloquent {
// default connection
public function genre() {
return $this->setConnection('Resources')->belongsTo('genre');
}
...
}
答案 8 :(得分:0)
要通过'资源'开始更改 database.php 中的'资源',会更好!
我很好奇,你能试试吗?
Album::whereHas('genre', function ($q) {
$q->setConnection('resources')->where('genre', 'German HopScotch');
});
答案 9 :(得分:0)
当关系无法处理模型连接时,我遇到了同样的问题。
我的解决方案是覆盖试图建立的模型上的belongsToMany方法。见下面的例子。
<?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);
}
}
答案 10 :(得分:0)
当关系没有在父连接上工作时,我遇到了同样的问题。
我的解决方案是覆盖试图建立的模型上的belongsToMany方法。见下面的例子。
<?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);
}
}