Cross database many to many relationships in Laravel with Sqlite - laravel

In Laravel Framework 8.20.1 I have two models, User and Item, in two different SQLITE databases, with a many to many relationship.
The intermediate table, called item_user, in the same database as model Item.
I've setup the belongsToMany relatinoship like this in model Item
class Item extends Model
{
...
protected $connection = 'connection2-name';
public function users()
{
return $this->belongsToMany(User::class);
// I have done several tryouts
// OR return $this->belongsToMany(User::class, 'item_user', 'user_id', 'item_id');
// OR return $this->belongsToMany(User::class, 'sqlite-db2.item_user', 'user_id', 'item_id');
// OR return $this->belongsToMany(User::class, '/path/to/sqlite-db2.item_user', 'user_id', 'item_id');
// OR return $this->belongsToMany(User::class, 'connection2-name.item_user', 'user_id', 'item_id');
}
}
When I try to access Item with Users:
$item = Item::find($id)->with('users')->get();
I get an error that my intermediate table "item_user" doesn't exist.
General error: 1 no such table: item_user
As far as I have found in my search of the solution, the problem should be that Laravel assumes the intermediate table to exist in the same database as the target relation, so they suggest to add the db name in the belongsToMany, but even that did not solve my issue.
Do you have any hint to come out of this problem?

First of all you need to create a table item_users with fields user_id and item_id
Then use relation:
public function users()
{
return $this->belongsToMany(User::class, 'item_users');
}

Related

How can I paginate Laravel's Eloquent's relationships' relationships?

I have two tables, users and profiles. A user has one profile. Also a user has referrals. The referrals are referenced by the column referrer_id in the users' table. So a user has a referrer, and a user can have many referrals.
Define a one-to-one relationship on the User's Model:
public function profile()
{
return $this->hasOne(Profile::class);
}
Define an inverse one-to-one relationship on the User's Model:
public function referrer()
{
return $this->belongsTo(User::class);
}
Define a one-to-many relationship on the User's Model:
public function referrals()
{
return $this->hasMany(User::class, 'referrer_id');
}
Define an inverse one-to-one or many relationship on the Profile's Model:
public function user()
{
return $this->belongsTo(User::class);
}
I wish to retrieve the user's profile, the user's referrals along with their profiles, and the referrals' referrals along with a count of each of the referrals' referrals.
The following Eloquent query works, but doesn't paginate:
namespace App\Http\Controllers;
class ReferralsController extends Controller
{
public function index(Request $request)
{
return $request->user()->loadMissing(['profile', 'referrals' => function ($query) {
$query->with(['profile', 'referrals'])->withCount('referrals');
}]);
}
}
I've tried to add ->paginate() to the query (on both as show below and also one or the other) but it doesn't work:
return $request->user()->loadMissing(['profile', 'referrals' => function ($query) {
$query->with(['profile', 'referrals'])->withCount('referrals')->paginate(2);
}])->paginate(2);
Adding it to the inner function doesn't do anything, and adding it to the main query just retrieves the entire users table.
EDIT
I've realized that adding ->paginate() to the inner function actually does limit the number of rows in the collection, but there is no Paginator instance anywhere, so I don't have access to any of the links to move pages.
Got it to work by doing it separately:
$profile = $request->user()->profile()
->firstOrFail();
$referralsPaginator = $request->user()->referrals()
->with('profile')
->withCount('referrals')
->paginate(2);

Retrieve related models using hasManyThrough on a pivot table - Laravel 5.7

I'm trying to retrieve related models of the same type on from a pivot table.
I have 2 models, App\Models\User and App\Models\Group and a pivot model App\Pivots\GroupUser
My tables are have the following structure
users
id
groups
id
group_user
id
user_id
group_id
I have currently defined relationships as
In app/Models/User.php
public function groups()
{
return $this->belongsToMany(Group::class)->using(GroupUser::class);
}
In app/Models/Group.php
public function users()
{
return $this->belongsToMany(User::class)->using(GroupUser::class);
}
In app/Pivots/GroupUser.php
public function user()
{
return $this->belongsTo(User::class);
}
public function group()
{
return $this->belongsTo(Group::class);
}
I'm trying to define a relationship in my User class to access all other users that are related by being in the same group. Calling it friends. So far I've tried this:
app/Models/User.php
public function friends()
{
return $this->hasManyThrough(
User::class,
GroupUser::class,
'user_id',
'id'
);
}
But it just ends up returning a collection with only the user I called the relationship from. (same as running collect($this);
I have a solution that does work but is not ideal.
app/Models/User.php
public function friends()
{
$friends = collect();
foreach($this->groups as $group) {
foreach($group->users as $user) {
if($friends->where('id', $user->id)->count() === 0) {
$friends->push($user);
}
}
}
return $friends;
}
Is there a way I can accomplish this using hasManyThrough or some other Eloquent function?
Thanks.
You can't do that using hasManyThrough because there is no foreign key on the users table to relate it to the id of the group_user table. You could try going from the user to their groups to their friends using the existing belongsToMany relations:
app/Models/User.php:
// create a custom attribute accessor
public function getFriendsAttribute()
{
$friends = $this->groups() // query to groups
->with(['users' => function($query) { // eager-load users from groups
$query->where('users.id', '!=', $this->id); // filter out current user, specify users.id to prevent ambiguity
}])->get()
->pluck('users')->flatten(); // massage the collection to get just the users
return $friends;
}
Then when you call $user->friends you will get the collection of users who are in the same groups as the current user.

A department can belongsToMany, but a user can only belongTo department? How to pivot this correctly?

So im trying to figure out how to use pivot tables in Laravel. And I have tried to read and understand the documentation. And I cannot understand why a user just can't balongTo a "department". I don't want a user to belongToMany "departments".
Departments model
public function users()
{
return $this->belongsToMany(User::class, 'department_user', 'user_id', 'department_id');
}
And for the user model, I want something like
public function department()
{
return $this->belongsTo(Department::class);
}
But Laravel reports null. Because department_id doesn't exist in the users row? How can I reverse this pivot table lookup, with belongsToMany and belongsTo?
I think you're getting confused with your relationship types. If I understand you correctly:
A Department hasMany Users.
A User belongsTo a Department.
This one-to-many relationship type does not need a pivot table and can be written as such:
class Department extend Eloquent
{
public function users()
{
return $this->hasMany(User::class);
}
}
class User extend Eloquent
{
public function department()
{
return $this->belongsTo(Department::class);
}
}
This would require that the users table have a department_id foreign key.

laravel 5 pivot table

I'm trying to implement a friendlist for a user
so a user can have many friends
but for calling the friends I'm having trouble getting my relation right:
user
id
friends
user_id
friend_user_id
Class user:
public function Friends(){
return $this->hasMany('App\User', 'friends');
}
So Auth::User()->Friends should return a list of User models
You actually don't have a "one to many" relationship but rather "many to many" with friends being your joining table
Try this:
public function Friends(){
return $this->belongsToMany('App\User', 'friends', 'user_id', 'friend_user_id');
}
When creating a relation to the same model, you would do something like this:
Models/User.cs
public function Friends()
{
return $this->hasMany('User', 'user_friend_of', 'id'); // assuming user_friend_of is the FK on user-table
}
public function User()
{
return $this->belongsTo('User');
}
This would mean you have only 1 table, which has a foreign key to another row in the same table, for instance: (id - name - user_friend_of )
In your user class, define the function as follows:
public function Friends(){
return $this->hasMany('friends');
}
Calling $user->Friends()->get() should return you everything you need. Note that 'friends' should be the name of the table.

Laravel Eloquent all with relationship

How can I get all data from my tables with relationship in Laravel?
So, I have table like:
*users*
id
username
password
...
*address*
id
address
user_id
...
If I call my eloquent model with Address::all() I get response with user_id, and I want to make relationships for getting username.
I try to add:
public function users(){
return $this->belongsTo('Users', 'user_id');
}
And call with Address::with('users')->get(), but response is empty.
Is your user class called Users or User? Unless you override it, the default way that Eloquent deals with names can be found in the docs (source):
Note that we did not tell Eloquent which table to use for our User model. The lower-case, plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the User model stores records in the users table. You may specify a custom table by defining a table property on your model
So I believe if you change your code in the Address model to:
public function users(){
return $this->belongsTo('User', 'user_id');
}
it will work since we have changed Users to User
You need to change
public function users(){
return $this->belongsTo('Users', 'user_id');
}
to
public function users(){
return $this->hasOne(Users::class, 'user_id');
}
or
public function users(){
return $this->hasMany(Users::class, 'user_id');
}
Alternative way!
class Users extends Model {
//override table
protected $table = 'users';
protected $primaryKey = 'id';
//Your other code here
}
and in Address Model add like this
public function users(){
return $this->belongsTo('App\Users', 'user_id');
}

Resources