Я правильно настроил соединение с двумя базами данных. Я также создал красноречивые модели таблиц и могу легко запросить отношение одной таблицы из другой базы данных, например.
$user->customer
Модель пользователя
class User extends Model
{
protected $connection = 'mysql';
protected $table = 'users';
public function customer()
{
return $this->hasMany(Customer::class, 'user_id', 'id');
}
}
Модель клиента
class Customer extends Model
{
protected $connection = 'second_db';
protected $table = 'customers';
public function order()
{
return $this->hasMany(Order::class, 'customer_id', 'id');
}
}
Я могу получить данные о заказах во второй базе данных, используя этот простой запрос.
$customer->order
Но это дает пустой результат при запросе из первой базы данных с использованием
$user->customer->order
or
$user->customer()->order
Как получить данные о взаимосвязях во втором дБ, запросив данные из первого дБ?
Я могу запросить его, используя это отношение в модели клиента. но это не то, что я ищу. Мне нужно что-то более надежное и эффективное. public function order($id) { return DB::connection('second_db')->table('orders')->where('customer_id', $id)->get(); }
и запросите ```` $customer->order($customer->id)->toArray();````
Я понял. Мне просто нужно определить все необходимые модели, связанные со вторым дБ, и тогда я смогу эффективно создавать любые длинные отношения, которые захочу.
вам может понадобиться HasManyThrough
, чтобы пользователь -> заказ проходил через клиента. Вы можете попробовать это, просмотрев документацию: laravel.com/docs/11.x/eloquent-relationships#has-many-through
Я только что прочитал документацию. это также работает для Laravel 8 и 9. спасибо!
Возможно, вам придется указать соединение внутри базового объекта Illuminate\Database\Query\Builder
при быстрой загрузке.
$customers = Customer::query()
->with([
'order' => function (HasMany $relation) {
$eloquentBuilder = $relation->getQuery();
$baseBuilder = $eloquentBuilder->getQuery();
$baseBuilder->connection = DB::connection('mysql');
},
])
->get();
Применяя это к вложенным отношениям:
$user = User::query()
->with(['customers' => function (HasMany $customers_relation) {
$customers_relation
->getQuery()
->getQuery()
->connection = DB::connection('second_db');
$customers_relation->with(['orders' => function (HasMany $orders_relation) {
$orders_relation
->getQuery()
->getQuery()
->connection = DB::connection('mysql');
}]);
}])
...
->first();
Мне кажется, ты все слишком усложняешь :D
Остается вопрос: работает ли это? Я тестировал его только на предмет локальных связей между mysql и sqlite.
Основываясь на требованиях ОП и ознакомившись с описанием в документации, вы можете попробовать HasManyThrough
метод:
class User extends Model
{
/**
* Get all of the orders for the user.
*/
public function orders(): HasManyThrough
{
return $this->hasManyThrough(Orders::class, Customer::class);
}
}
// String based syntax...
return $user->through('customers')->has('orders');
// Dynamic syntax...
return $user->throughCustomers()->hasOrders();
Просто для уточнения. он использует имена отношений, а не имена таблиц.
Вероятно, вам придется удалить
()
из запроса и разделить нагрузку на отдельные операторы. Когда вы объединяете такие операторы в цепочку, будут создаваться дочерние запросы, использующие то же соединение.