Query multiple table relationships using Laravel Eloquent Models - mysql

I'm trying to query multiple tables using Laravel Eloquent Models with one to one, one to many and many to many relationships.
I have a forms table, a brands table a users table and a brand_groups pivot table.
Each form has one brand and one user:
forms
ID
user_id
brand_id
Brands do not have any foreign keys:
brands
ID
Users do not have any foreign keys:
users
ID
And there is a pivot table to create a many to many relationship for creating brand groups that have many users like brand members:
brand_groups
brand_id
user_id
I'm trying to get all the forms that belong to a user either by a direct ownership (forms.user_id) or by brand membership, all the forms from all the brands that the user is a member through brand_groups many to many pivot table.
For example, we have 2 brands, 2 users and 1 user is a member of 1 brand:
brand(ID: 1)
brand(ID: 2)
user(ID: 1)
user(ID: 2)
brand_group(brand_id: 1, user_id: 1)
form(ID: 1, user_id: 1, brand_id: null)
form(ID: 2, user_id: null, brand_id: 1)
form(ID: 3, user_id: 2, brand_id: 1)
form(ID: 4, user_id: 1, brand_id: 2)
Using Laravel Eloquent Models (not direct DB facade calls), I'd like to retrieve all the forms that belong to a user. For the user(ID:1) there are 3 forms:
form(ID:1) direct user ownership
form(ID:2) user is a member of brand(ID:1) group which is the brand of form(ID:2)
form(ID:3) user is a member of brand(ID:1) group which is the brand of form(ID:3)
I gave it a shot using Eloquent: Relationships - Has Many Through:
Has Many Through
The "has-many-through" relationship provides a convenient way to access distant relations via an intermediate relation.
I have tried it like this:
class User extends Model
{
public function forms()
{
return Forms::hasManyThrough(
Form::class,
BrandGroups::class,
'brand_id',
'brand_id',
'id',
'form_id',
)->where('id', $this->id);
}
}
But I get errors like:
BadMethodCallException with message 'Call to undefined method App\Models\Form::brand_groups()'
EDIT
After some digging, I have managed to come up with the working MySQL code that will return all the forms for a user:
SELECT * FROM `forms`
WHERE EXISTS (
SELECT `brand_id`, `user_id`
FROM `brand_groups`
WHERE `forms`.`brand_id` = `brand_groups`.`brand_id`
AND `brand_groups`.`user_id` = 1
) OR `forms`.`user_id` = 1
Now I just need to convert that query to an eloquent model relation.
Eloquent Models
User.php
class User extends Authenticatable implements MustVerifyEmail
{
public function brands()
{
return $this
->belongsToMany(Brand::class, 'brand_groups')
->using(BrandGroups::class)
->as('member');
}
public function forms()
{
return $this->hasMany(Form::class, 'user_id');
}
}
Brand.php
class Brand extends Model
{
protected $table = 'brands';
public function forms()
{
return $this->hasMany(Form::class);
}
public function members()
{
return $this
->belongsToMany(User::class, 'brand_groups')
->using(BrandGroups::class)
->as('member');
}
}
Form.php
class Form extends Model
{
protected $table = 'forms';
public function owner()
{
return $this->belongsTo(User::class);
}
public function brand()
{
return $this->belongsTo(Brand::class);
}
}
UPDATE
I manage to find a query to get all forms related to a user like this:
class User extends Authenticatable implements MustVerifyEmail
{
...
public function allForms()
{
return Form::where(function ($q) {
$q->whereExists(function ($q) {
$q->from('brand_groups')
->where('forms.brand_id', DB::raw('brand_groups.brand_id'))
->where('brand_groups.user_id', $this->id);
})->orWhere('owner_id', $this->id);
});
}
}
How this can be converted to a direct User model eloquent relationship?

Have you tried to Eager Load the User model relationships?
Edit
Firstly: the pivot table name should be the singular -snake_case- name of both tables and should be in alphabetical order (brand_user)
Next, try the following:
return User::where(‘id’, $this->id)->with([‘forms’,‘brands.forms’)->get();
This should return the Forms with direct ownership plus the user Brands and their associated Forms

Related

How to join two table in laravel 8 with no duplicate

I have two tables. Customer and address. The relationship of the table is that a CUSTOMER can have many ADDRESSES. So what I want as a result to my query is to get the list of customer and only one latest address
ADDRESS TABLE
id : 1
city:"cebu"
zip_code:"600"
cus_id:1
id:2
city:"mandaue"
zip_code:"6001"
cus_id:1
CUSTOMER TABLE
id: 1
name:"JOHN DOE"
What I want to get the customer "JOHN DOE" and the address with ID "2"
I'm using laravel query builder
If you want to get only one latest address, you can use hasOne same as :
// Customer model relation
public function lastestAddress()
{
return $this->hasOne(Address::class, 'customer_id')->orderBy('id', 'desc');
}
And
$model = Customer::with('lastestAddress')
you can use Eloquent ORM in laravel.
Eloquent :
You must setting in your customer model
Class Customer(){
public function address()
{
return $this->hasMany(Address::class, 'cuss_id', 'id')->latest();
}
in your Adress model :
Class Address(){
public function customer()
{
return $this->belongsTo(Customer::class, 'id', 'cuss_id')
}
Then in your controller you can call the model :
$data = Customer::with('address')->get();
So you have two tables: customers and addresses, with a "one customer can have many addresses" relationship.
In Laravel, we normally use Eloquent models to query the database. So to get a customer and all its addresses, we must first model the database; each table with its own Eloquent model. (See details in the docs.)
class Address extends Model
{
// although empty for now, this class definition is still important
}
class Customer extends Model
{
/**
* Get the latest address.
*/
public function currentAddress()
{
return $this->hasOne(Address::class, 'cus_id')->latestOfMany();
}
}
In the Customer model, our currentAddress() method defines how a Customer instance related to the Address instances.
It's like we're saying,
"A customer may have many Addresses. Just get one which is the latestOfMany. That's how we'll get the customer's currentAddress.
Now that we have the necessary Eloquent models setup, we can lookup John Doe and his current address.
$johnDoeId = 1;
// query the database for customer 1, including its current address
$johnDoe = Customer::with('currentAddress')->find($johnDoeId);
$johnDoe->currentAddress; // 👈 John's latest address, at Mandaue

Laravel 5: User follow another user (like twitter) - how to setup relationship

I have user table .
Relation:
One user can follow more than one user.
How to setup data structure and how to declare relationship in laravel 5.2
Output:
show who are my followers
show my following list ( I follow another user )
create a table followers with these columns: id, user_id, follower_id
2.Create Model like
User Model
public function following(){
return $this->hasMany('App\Follower', 'user_id', 'id');
}
Follower Model
public function following(){
return $this->belongsToMany(User::class, 'followers', 'follower_id', 'user_id');
}

Relationships between tables in laravel using backpack package

I am using backpack CRUD package to create my website project in laravel 5.2
I want to establish a relationship between two tables. First table is called customer and second table is called transaction. Each customer has many transaction(1:N relationship).
Customer table record:
ID Name
123456 xyz
Transaction table record:
ID CustomerID
101010 123456
I know that I have to specify the relation in the customer model. But, how can I display the result of the relationship in CRUD ?
You should have relationships on both the Transaction and the Customer models, so you can do $customer->transactions and $transaction->customer:
class Customer extends Model
{
/**
* Get the comments for the blog post.
*/
public function transactions()
{
return $this->hasMany('App\Transactions', 'CustomerID', 'ID');
}
}
and
class Transaction extends Model
{
/**
* Get the comments for the blog post.
*/
public function customer()
{
return $this->belongsTo('App\Customer', 'CustomerID', 'ID');
}
}
Spend some time in the Eloquent Relationships Documentation. It's really important to understand them if you want to be a Laravel developer.
In order to display the relationship in the CRUD, you can then use Backpack's select column type to display it in the table view and select or select2 field types to display it in the add/edit views. Read the CRUD Example Entity to better understand how that works.
First of all when you are creating migrations for both tables, table which contain Foreign Key (FK) must have field like this:
public function up(){
$table->increments('id');
$table->integer('customerID')->unsigned();
}
After that you are need to call next command into console
php artisan migrate
Next is going next commands:
php arisan backpack:crud customers
php arisan backpack:crud transactions
After that you need to define functions in models which returns values from other tables. Customer models need to have next function
public function transactions(){
return $this->hasMany('Transaction');
}
Transaction model must have next function
public function customer() {
return $this->belongsTo('Customer');
}
Next you must add CRUD field in Customer controller to display
transactions in select box.
$this->crud->addField([
'label' => 'Transactions', // Label for HTML form field
'type' => 'select2', // HTML element which displaying transactions
'name' => 'customerID', // Table column which is FK for Customer table
'entity'=> 'customer', // Function (method) in Customer model which return transactions
'attribute' => 'ID', // Column which user see in select box
'model' => 'Transaction' // Model which contain FK
]);
Hope this helps :)
After you built onetomany relationship with transaction, you can get the results.
$customer=Customer::where(['id'=>'123456'])->with('transaction')
->first();
print_r($customer->Name); // gives the customer name
foreach($customer->transaction as $cid)
{
print_r($cid->CustomerID); // gives the customer id
}
Laravel Relationships Documentation is always helpful. Go through it.

Laravel 5.2 How to get values from two or more table from a relationship

I have a default authentication table user and another table user_profiles
user(id,email,password)
user_profiles(id,first_name,last_name,mobile)
i am connecting these two table using a many-to-many relationship
for this, i added relationship in the both model class- User and UserProfile
// User Model
public function userProfiles()
{
return $this->belongsToMany('App\Models\UserProfile', 'user_user_profile',
'user_profile_id', 'user_id');
}
//UserProfile Model
public function users()
{
return $this->belongsToMany('App\User', 'user_user_profile',
'user_profile_id', 'user_id');
}
and i tried to access the UserProfle details via user table using
$user=\App\User::find(1)->userProfiles()->get();
but not working and also tried
/$user = \App\User::findOrFail(1)->with('userProfiles')->get();
that is also not working , please help to
Get the user_profile table details along with user table
How to access the Pivot table(user_id,user_profile_id) value
How to display these data from multiple tables into a view form?
You have defined the relationship wrong in your User Model: swap user_id and user_profile_id
// User Model
public function userProfiles()
{
return $this->belongsToMany('App\Models\UserProfile', 'user_user_profile',
'user_id' , 'user_profile_id');
}

Using relationships in Laravel Eloquent with bridge table

I have an app that handles user info, and one of the pieces of data we collect is what school(s) they're attending. We have a User object, School object, and a UserSchool object.
This is the user_schools table:
user_id (int),school_id (int)
With the following records for instance:
100, 20
200, 500
200, 10
300, 10
I'm trying to get all schools for the current user (say user 200). This is my UserSchool object:
class UserSchool extends Model
{
var $table = 'user_schools';
function user() {
return $this->belongsTo('User');
}
function school() {
return$this->belongsTo('School');
}
}
In User I have the following relations defined:
public function schools()
{
return $this->hasManyThrough('School', 'UserSchool');
}
public function userSchools()
{
return $this->hasMany('UserSchool');
}
When I var_dump($user->schools) I get no results, even though I know it should be returning multiple Schools. What am I doing wrong? I'm sure this must have been asked before but I don't know what the actual term for this intermediate type of relationship is (bridge table? pivot table?).
Edit: Either way, most of the examples I've looked at haven't worked. I've also tried:
public function schools()
{
return $this->hasManyThrough('School', 'UserSchool', 'school_id');
}
In fact you don't need to have UserSchool object here for this relationship
For User model you can use create the following relationship:
public function schools()
{
return $this->belongsToMany(School::class, 'user_schools');
}
And now you can get schools of user using something like this:
$user = User::find(1);
foreach ($user->schools as $school)
{
echo $school->name;
}
This is standard many to many relationship