Creating self referencing relationships - php

I want to be able to make relationships between a captain and his referrals. They both belong to the same table. I have this in my model
public function captain() {
$this->belongsTo('User', 'referral_id') ;
}
public function captain() {
$this->hasMany('User', 'referral_id') ;
}
My users table has the following columns
id name referral_id referred_by
1 xyz 1223 null
2 Abc 4525 1223
How do I create the relationship better? And I want to know if I can and how I can use this to get the referral of a referral of the captain

I'd create a second table for your referrals - then you create a relationship between your captain ID in table 1 over in table 2 where all the referers can be stored. If you setup the relationship, you then simply call something like
$captains = App\Captain::all();
foreach ($captains as $captain) {
echo $captain->referrals->name;
}
ref
using simple eager loading... or ->with using other methods (or join etc)

Related

User can hasMany Conversations through 2 foreign keys

Part of my application is private messages between 2 users.
I have a converstations table that has user1 and user2 foreign keys.
Now I wanna have an eloquent function in the User model where I can get his conversations. But a user could be user1 or user2 in any given conversation.
This function for example will only account to conversations where I happen to be user1.
public function conversations()
{
return $this->hasMany('App\Conversation', 'user1');
}
So how can I do it?
A suggestion into your approach would be to store the users of a Conversation in a pivot table. So a Conversation can have more than, in your case, two users. This will lead to easier queries and more expension options. In that case you would just have to do the following:
return $this->belongsToMany(Conversation::class);
Check the docs for more info.
Addition to comment
If you really need this table to have those two columns people would normally do the following:
return $this->hasMany(Conversation::class, 'user1')->orWhere('user2', $this->id);
However since this is an orWhere it could get you incorrect records. This query is executed:
select * from "conversations" where "conversations"."user1" = 1 and "conversations"."user1" is not null or "user2" = 1
But there I have found another way. There is a noConstraints method on the Relation abstract class , from which all relation classes extend, that allows you to modify the whole query:
use Illuminate\Database\Eloquent\Relations\HasMany;
return HasMany::noConstraints(function () {
return $this->hasMany(Conversation::class)
->where('user1', $this->id)
->orWhere('user2', $this->id);
});
This will result in the query what you are looking for:
select * from "conversations" where "user1" = 1 or "user2" = 1
I am not sure how this will effect eagerloading and such.
Still I suggest having a pivot table to keep your database/application flexible.
public function conversations()
{
if(test_for_user1_or_user2())
{
return $this->hasMany(converstations ::class,'user1_id');
}
return $this->hasMany(converstations ::class,'user2_id');
}

Laravel 5.4 relationship 2 tables 3 id

I work with laravel 5.4, and I want receive information from my relations tables.
I have 3 tables in phpmyadmin
ATHLETES
ID
FIRST_NAME
LAST_NAME
TYPES
ID
NAME
SLUG
ATHLETES_TYPES
ID
TYPE_ID
ATHLETE_ID
I have 3 models
ATHLETE
TYPE
ATHLETEBYTYPE
How do I need to make the relations models to have name and slug from my table TYPES, with my id from my table athletes?
Thank you.
For this you just need 2 model file ATHLETE and TYPE and use many to many relation.and then you can use ATHLETES_TYPES table as pivot table.
for implement this :
first add this method to ATHLETE model file :
public function types()
{
return $this->belongsToMany(TYPE::class,'ATHLETES_TYPES','ATHLETE_ID','TYPE_ID');
}
secode add this method to TYPE model :
public function athletes()
{
return $this->belongsToMany(ATHLETE::class,'ATHLETES_TYPES','TYPE_ID','ATHLETE_ID');
}
and in last remove ID filed from ATHLETES_TYPES table.
done.
now if you have variable from ATHLETE type with $ATHLETE->types you can get types of than.
read more here :
https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
Here are the relationships, buddy
In App/Athlete.php
class Athlete extends Model
{
public function types(){
return $this->belongsToMany('App\Type');
}
}
In App/Type.php
class Type extends Model
{
public function Athletes(){
return $this->belongsToMany('App\Athlete');
}
}

How to update a row in DB without overwriting the existing data with laravel 5.2

I have a table which stores the user's interested topics along with the user id and topic id. The table will look like
Topic name topic id User-id
Sports 1 1
Education 2 3
Family 3 1
What i want to do is when a new user , say user-id '3' adds his interest as topic sports , then the first row should look like this
Topic name topic id User-id
Sports 1 1,3
When i try to update it overwrites the whole column like
Topic name topic id User-id
Sports 1 3
What is the right approach to do this ?
The right approach is to use Many-To-Many relationship:
Tables:
users (id, ....);
topics (id, ....);
topic_user (topic_id, user_id);
PHP:
class User extends Model {
public function topics() {
return $this->belongsToMany('App\Topic');
}
}
and :
class Topic extends Model {
public function users() {
return $this->belongsToMany('App\User');
}
}
For more details please refer to https://laravel.com/docs/5.2/eloquent-relationships.
I hope this will help.

Yii2 join relations with 4 tables

I have 4 tables, say table A, B, C, D.
Somewhat like:
Table
A - a_id, a_name.
B - b_id, a_id, b_name.
C - c_id, b_id, d_id.
D - d_id, d_name
How can I get the table D object for a corresponding primary key value of A ie. if value of id in A is 20, I need all data from d table corresponding to that in yii2.
A -> B is one to many.
Someone please help!
First of all, it's better to give real world example for better understanding. And I think naming primary key of the same table as id (not a_id for a table) is better practice.
This can be done using relation chain. For example if we have 3 models: Test, Question and Answer (test has many questions and question has many answers), having an answer model we can access test model like so:
$answer = Answer:findOne(20); // id must exist
$test = $answer->question->test;
But it doesn't work vice versa with has many, because we need to know specific model to continue chain, so we can't write something like:
$answer = $test->question->answer
Only $test->questions and $question->answers are acceptable.
This is exactly your case. Read Working with Relational Data article in official docs for better understanding.
I got a 4 or even more relation situation same as you, table as these:
Link - id, SalesItemId.
SalesItem - id, SoId, ItemName
SalesOrder - id, SalesId, OrderNo
User - id, ManagerId, Name
User - id, Name
** the User table I have related 2 times as I need to get the manager name of the user
In Link model, I got these methods:
public function getLinkSalesitem() {
return $this->hasOne(Salesitem::className(), ['id' => 'SalesItemId']);
}
public function getLinkSalesorder() {
return $this->hasOne(Salesorder::className(), ['id' => 'SoId'])
->via('linkSalesitem');
// ->viaTable('salesitem', ['id' => 'SalesItemId']); //either this line or above are the same
}
public function getLinkSales() {
return $this->hasOne(User::className(), ['id' => 'SalesId'])
->via('linkSalesorder');
}
public function getLinkManager() {
return $this->hasOne(User::className(), ['id' => 'ManagerId'])
->via('linkSales');
}
In the view file, I just retrieve the the Manager name by
$model->linkManager->Name;
if you want to use relations then first you have to make sure that table A is Connect to table D through some table in you case table A is connected to table B with a_id,table B is connected with table C with b_id and table C and table D are connected with through d_id in table c.
Now if you want data from table D then you have to make relations
First make relations
public function getB(){
return $this->hasOne(B::className(),['a_id' => 'a_id'])
}
public function getC(){
return $this->hasOne(C::className(),['b_id' => 'b_id'])
}
Now you want data from A and D which is connected through relation C so you have to make relation like
public function getD(){
return $this->hasOne(D::className(),['d_id' => 'a_id'])->via('c')
}
First find A
$model = A::findOne(20);
echo isset($model->c)?$model->c->d_name:'';

laravel eloquent relationships queries

I have two tables 1)users
{ id, password }
2)expertise { id, expertise}
the relationship I have is
Models
Expertise.php
function User()
{
$this->hasOne('Expertise');
}
User.php
function Expertise()
{
$this->hasOne('User');
}
So how can I query using Eloquent to get the first 10 users with a certain expertise?
I want to join users.id = expertise.id and get the first 10 people with a specified expertise (Where clause).
Beginner to laravel, I've checked other sources but was not successful
Right now you are having a problem with the way that you modeled your data. If you have a one-to-one relationship the best practice to model it is to have one entity store the id of the other. The Laravel convention for this is to have a column named <model>_id:
Users
| id | password |
Expertises
| id | expertise | user_id |
Then in your models you can do this:
Models
Expertise.php
class Expertise extends Eloquent
{
public function User()
{
// because expertise has a column user_id
// expertise belongs to user
return $this->belongsTo('User');
}
}
User.php
class User extends Eloquent
{
public function Expertise()
{
// because expertise is the one with the column
// user_id, user has one expertise
return $this->hasOne('Expertise');
}
}
The Query
After you have all this set up, to be able to query the first 10 users with a certain expertise you can do this.
$users = User::whereHas('Expertise', function($q)
{
$q->where('expertise', '=', <expertise you are looking for>)
})
->take(10)
->get();
To get a further reading in querying relationships in Laravel please take a look at this:
Laravel - Querying Relationships
Keep in mind
keep in mind that the tables name must be plural, if not then you should specify the name of the table inside the model:
protected $table = 'expertise';

Categories