Laravel HasManyThrough, accesing Primary/Secondary user referrals - mysql

I have an app where I need to track a user's primary and secondary referrals. My user table looks like:
users table
name, varchar
email, varchar
referral_id, varchar
referrer_id, varchar
I currently access the primary referrals/referrer using the following:
public function referrer()
{
return $this->belongsTo(User::class, 'referrer_id', 'referral_id');
}
public function primaryReferrals()
{
return $this->hasMany(User::class, 'referrer_id', 'referral_id');
}
I'm trying to figure out how I can access the "secondary" referrals...for example.
User A invites User B. User B then invites Users D, E, F. From the User A model I want to be able to call something like $user->secondaryReferrals and get users D, E, F.
I'm guessing I need to use something like:
public function secondaryReferrals()
{
return $this->hasManyThrough(
User::class,
User::class,
'referrer_id',
'referrer_id',
'referral_id',
'referral_id'
);
}
However I'm not clear on what keys/ids I should be supplying...or if this is even the right bit to use. I tried a mix but I keep getting ambiguous column name errors when using sqlite and other errors when using the mysql driver.
UserA: {
referer_id: null,
referral_id: 'abc'
}
UserB: {
referrer_id: 'abc',
referral_id: 'def'
}
UserC: {
referrer_id: 'def',
referral_id: 'ghi'
}
I want to be able to access User C from User A through User B's referral code.

You can't use a HasManyThrough relationship here because there is no way to specify a table alias.
You can use the primaryReferrals relationship twice:
public function getSecondaryReferralsAttribute()
{
$this->load('primaryReferrals.primaryReferrals');
return $this->primaryReferrals->pluck('primaryReferrals')->flatten();
}
// $user->secondaryReferrals

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

Eloquent retrieve data from another model on runtime

I have two tables;
Data
id
name
Custom_data
id
data_id (references id on Data)
customer_id (references id on Customers)
name
When I retrieve all items from the database (via for example Data::all()) as Customer X then I want to retrieve values from 'Custom_data' in favor of the data in table 'Data' where the customer_id matches X
Example:
Data contains name 'John Doe' with id 1
Custom_data contains a record with data_id 1 and name 'Jane Doe' and customer_id X
When retrieving the models I want to see Jane Doe instead of John Doe. Can this be done on a Model level in Eloquent? This is just a simple example, in our application we have multiple columns that need to be retrieved (firstname, lastname, street, etc. etc.)
How I am currently retrieving the fields is like this:
public function getNameAttribute($name) {
$customData = CustomData::where('customer_id', $this->customer_id)->where('data_id', $this->id)->first();
if(null != $customData) {
return $customData->name;
} else {
return $name;
}
}
Here' how you can do it:
In your Data.php modal file you need to add relationship:
public function CustomData(){
return $this->hasOne(CustomData::class);
}
Now, you can use CustomData function on eloquent record anywhere in Controller or View at runtime to get related data.
Another approach is to get data on condition basis:
$users = User::select('users.id', 'users.username', 'users.active', 'users.parent_id', 'parent.username as parent_username')
->selectRaw("CASE WHEN GROUP_CONCAT(roles.name) = 'student' THEN user_profiles.secondary_email ELSE users.email END as email");
I've used this type of solution for another purpose where I needed to use email on condition basis.
first you need to define relation in model
class DataModel extends Model{
...
public function customData()
{
return $this->hasMany(CustomDataModel::class,"data_id");
}
}
now you have access to this data.
$data = DataModel::with("customData")->first();
$data->name; // John Doe
$data->customData->name; // Jane Doe
Allright, I think I nailed this one.
I made a hasOne relation in my Data model:
public function custom_data() {
return $this->hasOne('App\Models\CustomData', 'data_id')->where('customer_id', $customer_id);
}
After that, I could fairly easily add the correct accessors like so:
public function getNameAttribute($name) {
return null != $this->custom_data ? $this->custom_data->name : $name;
}
If the custom data attribute has been set, we'll return that. If not, we'll return the original attribute.

Laravel Join Query returning empty column

I have a member table with some entries. Each member can create a user account in laravel's users table.
They each have a field called "person_id" and that's how the connection is made.
I have a search that returns a list with all of them. I have a checkbox "Search only registered" that means it returns only members that have users account, otherwise if the check doesn't check, return a mix with all of them.
The thing is, no matter if the checkbox is checked or not, the person_id must be pulled for each one.
if($reg == 'on') {
$Members = $Members->rightJoin('users', 'users.person_id', '=', 'members.person_id');
}
else {
$Members = $Members->leftJoin('users', 'users.person_id', '=', 'members.person_id');
}
I tried with leftJoin but person_id comes empty
at first look if you are using Eloquent i can tell you are missing the "->get();" at the end of each query.
Hope this helps.
Use relation in member model:
public function user()
{
return $this->belongsTo('App\User', 'person_id', 'person_id' );
}
public function getMemberWithUser()
{
return $this->select('*')->with('user')->get()->toArray();
}
and use (new Member)->getMemberWithUser(); in controller. That will return you member detail with user.
Neverming guys I found it out.
Most members don't have yet a user account, only 2. And the select wasn't specifying which table to take the person_id from. And with most members missing an user account, it was trying to get it from users.
I did this:
$Participants = Member::select(
'members.first_name',
'members.last_name',
'members.person_id',
'members.email'
);

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');
}

How Eloquent work with Relationship?

I'm new to laravel relationship so many apologizes if it's just dumb question. I'm using a pivot table named users_email on the project to get Emails of users. Pivot table contains the foreign key Uid and Email_id. Uid references users table
primary key and the same as Email_id. I can get the result while joining them using QueryBuilder.
$recent_inbox_email=DB::table('users_email')->
join('email','users_email.email_id','=','email.Id')->
join('users','users_email.Uid','=','users.Id')->
where('users_email.Uid','=',$Uid)->
where('email.draft','<>','true')->
where('email.trash','<>','true')->
where('email.status','=','unread')->count();
here's how I define the relationship in my models
public function getUid()//User Model
{
return $this->hasMany("User_Email",'Uid');
}
public function getEmId()//Email Model
{
return $this->hasMany("User_Email",'email_id');
}
//User_Email Model
public function email()
{
return $this->belongsTo('Email','Id','email_id');
}
public function user()
{
return $this->belongsTo('User','Id','Uid');
}
Now I want to query something like this using Eloquent
$query= select * from users_email inner join
email on users_email.email_id=email.Id
inner join users on users_email.Uid=users.Id
where users.Id=users_email.Uid limit 0,10
foreach($query as $emails)
{
echo $emails->f_name;
echo $emails->Message
}
DB designer Pic
Link to image
Thanks
There are no dumb questions. I'll try to give you an explanation! I'm not a pro, but maybe I can help.
Laravel uses some conventions that are not mandatory, but if you use them, things work like a charm.
For example, as a general recommendation, tables should be named in plural (your table users is ok. Your "email" table should be "emails"). The model, should be named in singular. This is User.php for table users, Email.php for table emails.
"The pivot table is derived from the alphabetical order of the related model names...", in this case "email_user". I repeat, you are not obliged to name them like this, as you can specify the table for the model setting the $table property in the model.
Once you have set up things like this, you only have to add this to your User model:
public function emails()
{
return $this->belongsToMany('Email');
}
And in your Email model:
public function users()
{
return $this->belongsToMany('User');
}
The "User" and "Email" between parentheses is the name of the related model.
And that's it. You can now do this:
$user = User::find(1);
foreach($user->emails as $email) {
echo $email->subject . '<br>';
echo $email->message . '<br>';
}
If you decide not to follow conventions, you can still use Eloquent relationships. You have to set up the relationship like this:
public function nameOfRelation()
{
return $this->belongsToMany('NameOfRelatedModel', 'name_of_table', 'foreign_key', 'other_key');
}
In the case of the User model for example:
public function emails()
{
return $this->belongsToMany('Email', 'users_email', 'Uid', 'email_id');
}
And in the email model, the other way round.
The answer got long! I didn't test the code, but this should give you an idea!
You can always check the official Laravel documentation, it is really helpful!
http://laravel.com/docs/4.2/eloquent
Hope I helped