【问题标题】:Laravel HasMany across multiple connectionsLaravel HasMany 跨多个连接
【发布时间】:2020-09-25 00:32:29
【问题描述】:

我想在第二个表 offer_related 上检索与 Offer 相关的 Offers,因为我无法更改 Offer 表的架构。

我有两个不同连接的数据库,offers 在一个,offer_related 在另一个。

为了争论,我将在我的示例中为数据库命名如下,以便清楚地说明哪些可以更改,哪些不能更改。

  • 包含offers 的数据库此后称为immutable
  • 包含offer_related 的数据库此后称为mutable

示例架构如下

connection1.mutable.offer_related

offer_id | related_offer_id
---------------------------
1        | 2
1        | 3

connection2.immutable.offers

id | name
---------------------------
1  | foo
2  | bar
3  | baz

我假设这将是一个 belongsToMany 关系,但我似乎无法正确理解。

return $this->belongsToMany(Offer::class, 'immutable.offer', 'id');

// Syntax error or access violation: 1066 Not unique table/alias: 'offer'

我还尝试使用自定义查询手动构建 belongsToMany 关系,但没有成功。

我想打电话

Offer::find(1)->related; // Offer(2), Offer(3)

【问题讨论】:

  • 你可以试试这个,看看它是否有效? return $this->belongsToMany(Offer::class, 'mutable.offer_related', 'offer_id', 'related_offer_id');
  • 那行得通,太棒了!发布答案,我会接受。非常感谢。
  • 好的!我已经做到了。谢谢!

标签: php laravel laravel-5 eloquent


【解决方案1】:

将关系改为:

    return $this->belongsToMany(Offer::class, 'mutable.offer_related', 
                                'offer_id', 'related_offer_id');

您的原始查询试图在不使用关系表 (offer_related) 的情况下建立关系。这就是问题所在。

【讨论】:

    【解决方案2】:

    我也有这个问题,然后用一个 trait 解决了:

    <?php 
    
    namespace App\Traits\Model;
    
    use Illuminate\Support\Str;
    
    trait HasCrossDatabaseRelation {
    
        public function getTable() {
            if (! isset($this->table)) {
                $this->table = str_replace(
                    '\\', '', Str::snake(Str::plural(class_basename($this)))
                );
            }
    
            $configConnections = config('database.connections');
    
            $databaseName = $configConnections[$this->getConnectionName()]['database'];
    
            return $databaseName . "." . $this->table;
        }
    
    }
    

    然后使用该特征并在每个模型上设置 $connection 属性。希望对您有所帮助

    【讨论】:

      【解决方案3】:

      另一种解决方案是创建一个特征:

      trait HasCrossDbRelationships {
      
        /**
         * Define a one-to-many relationship with connection attribute
         *
         * @param  string  $connection
         * @param  string  $related
         * @param  string  $foreignKey
         * @param  string  $localKey
         * @return \Illuminate\Database\Eloquent\Relations\HasMany
         */
        public function hasManyCrossDb($connection, $related, $foreignKey = null, $localKey = null)
        {
            $instance = $this->newRelatedInstance($related);
            $instance->setConnection($connection);
      
            $foreignKey = $foreignKey ?: $this->getForeignKey();
      
            $localKey = $localKey ?: $this->getKeyName();
      
            return $this->newHasMany(
                $instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey
            );
        }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2016-04-09
        • 1970-01-01
        • 1970-01-01
        • 2018-07-03
        • 2022-01-16
        • 2014-12-29
        • 1970-01-01
        • 2010-10-21
        • 2015-12-04
        相关资源
        最近更新 更多