Laravel Eloquent join 2 tables together - php

I want to join 2 tables together using laravel eloquent. I could easily do this in mysql but have no idea using this.
I have a model called device.php this contains the following method:
public function wifi_client_connection(){
return $this->hasMany('UserFrosting\WifiClientConnection');
}
but I need to link the WifiClientConnection.php model using a column called mac_address but WifiClientConnection doesnt have that column it has a column called device_uuid. The mac_address is converted into the device_uuid using the following method:
public function getDeviceUUID(){
return hex2bin(md5($this->mac_address . $this->number));
}
In MySQL I join the 2 tables together like this:
LEFT OUTER JOIN device ON wifi_client_connection.device_uuid = UNHEX(MD5(CONCAT(device.mac_address, device.number)))
how can I do something like that using Laravel Eloquent.
I also need the relationship the other way round so in the WifiClientConnection.php model I have this method:
public function device(){
return $this->belongsTo('UserFrosting\WifiClientConnection');
}
but again I would need to convert the device_uuid to mac_address for this relationship to work
Thanks for any help

I would add a column with the converted value, then you can create the relationship.
public function device(){
return $this->belongsTo('UserFrosting\WifiClientConnection', 'device_uuid', 'new_column_with_converted_value');
}

Related

Laravel Many-to-many relationship using pivot table

I'm creating an application wherein users can be assigned to multiple organisations, and organisations can have many users - many-to-many relationships.
I want to be able to do something like this:
$user->organisations()->get() as well as $organisation->users()->get()
I have a users table...
I have an organisations table...
Uh! users-organisations, organisations-users!
and I have a user_orgs pivot/mapping/etc. table
Note
The user_orgs table has an org_id field, and a user_id field.
Eloquent assumes and expects organisation_user - but that is not what I have named my table, nor do I want to rename.
I set up the following
App/Organisation.php
public function users(){
return $this->belongsToMany("App\User");
}
and on user:
App/User.php
public function organisations(){
return $this->belongsToMany("App\Organisation");
}
And then I test this:
Route::get('/test-route', function(){
$u = App\User::first();
return $u->organisations()->get();
});
and get the following error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db.organisation_user' doesn't exist (SQL: select organisations.*, organisation_user.user_id as pivot_user_id, organisation_user.organisation_id as pivot_organisation_id from organisations inner join organisation_user on organisations.id = organisation_user.organisation_id where organisation_user.user_id = 1)
The two questions in my mind are, one; how do I specify to Eloquent, to use user_orgs instead of assuming organisation_user, the same way I can override the tableName or primaryKey on a model? Two: how can I specify the foreignKey column, such that it uses user_orgs.org_id and not user_orgs.organisation_id?
But please do suggest alternatives.
Thanks all, in advance.
You can set the name of the pivot table by passing it as the second argument to the belongsToMany() relationship, like below:
public function users(){
return $this->belongsToMany("App\User", "user_orgs");
}
public function organisations(){
return $this->belongsToMany("App\Organisation", "user_orgs");
}
Documentation:
https://laravel.com/docs/5.8/eloquent-relationships#many-to-many
As mentioned previously, to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method.

Laravel Eloquent relationship fetching third table/relation value

I have 3 tables in a database
Transaction {'id','bill_id','remark'}
Bills {'id','third_party','amount'}
ThirdParty {'id','company_name',remark}
The 'transaction' table has column bill_id coming from 'Bills' and Bills table has 'third_party' column which connected to ThirdParty table column -> 'id'
So here I am trying to fetch company_name using laravel eloquent relation
My Transaction model:
public function Bills()
{
return $this->hasOne('App\Bills','id','bill_id');
}
Bills:
public function third_party()
{
return $this->belongsTo('App\ThirdParty','third_party','id');
}
I am getting null value for company_name
Here is the query i am using
Transaction::with('Bills.third_party')->get();
And i have corrected in question (third_party_name) to company_name column name i wrote here was my old join query name which is visible in screenshot, basically i am trying to fetch company name.
Are you able to show all of your code? How does company_name get set to third_party_name?
You could probably also gain a lot by sticking to the laravel "conventions" or "suggested naming", this will give you a lot of functionality for free, and make your code easier to read, write and debug.
eg. Your relationship method names (Bills(), third_party()), but more importantly if you name your table fields in the "laravel way", you will get easier eloquent relationships as there will be no need to define the foreign keys etc.
I would be setting this up similar to:
Transaction {'id','bill_id','remark'}
Bills {'id','third_party_id','amount'} <- note the third_party_id
ThirdParty {'id','company_name',remark}
class Transaction extends Model
{
public function Bills()
{
return $this->hasOne('App\Bills');
}
}
class Bills extends Model
{
public function ThirdParty()
{
return $this->belongsTo('App\ThirdParty);
}
}
You should also define the inverse relationships.
It would be very beneficial to see the full code to see where the issue is.

ID lost despite left join

I am using a left join to combine two tables based on a common column but I seem to lose the primary key id in my left table. Every other column is returned
My controller:
$prod_manu = $request->prod_manu;
return $data = Product::leftJoin('manufacturers','products.Manufacturer_id','=','manufacturers.id')
->where('products.Manufacturer_id',$prod_manu)
->get();
Product Model:
class Product extends Model{
public function types(){
return $this->belongsTo('App\types','Type_id');
}
public function manufacturers(){
return $this->belongsTo('App\manufacturers','Manufacturer_id');
}
}
This is probably because both Product and manufacturers have an id column, so one of them gets overwritten.
Instead of using the left join, you can use eloquent's with method.
If you have your relationships and class structure setup properly you should be able to access the Manufacturer's products like this:
$manufacturer = Manufacturer::where('id', $prod_manu)->with('products')->get();
return $manufacturer->products;
Also note that class names should always be singular and start with a capital letter in laravel. App\manufacturers Shouldn't be valid. Please read the article I linked above about setting up your eloquent relationships.

Search in Related Model using GridView Filter Field

Question:
Let's Say i have two tables,
Table1 Table2
-authorId -username
As of now my sql query on search model looks like this,
->andFilterWhere(['"Table1"."authorId"' => $this->authorName]);
It only helps to search and filter using the authorID.
Expected Result
I would like to search based on the authorname instead of authorId.
I faced similar difficulty in reflecting data in view but i was able to fix it with following getter function in base model.
public function getAuthorName() {
return $this->author->username;
}
Thanks in Advance,
First, add a custom attribute to your search model
public $username
define a relation to your author table inside the model
public function getAuthor() {
return $this->hasOne(Author::className(),['id'=>'authorId']);
}
in your gridview replace the authorId column with
`author.username`
and use the following to compare
$query->andFilterWhere(['like', '{{%Table2}}.username',$this->username]);
and yes make sure you join you searchmodel query with the author table in the start of search function
->joinWith('author')
Assuming authorId is a FK to table2, and you have previoulsy joined table2 to table1, you can do the following:
->andFilterWhere(['table2.username' => $this->authorName]);

Laravel eager loading, loaded table fields

how can I choose which fields I want to get from the with ORM eloquent. For example
$tourTeams = Tournament::with('teams')->where('id', $tourId)->first();
From the teams relation I want only to get the name (without the id and timestamps).
I didn't it in the documentation. For the Tournament eloquent I can do it via the get function while passing it an array of fields names, like this: get(array('name', 'id')). But how do I do this on the Team eloquent?
Note: here is how Team related to Tournament, this code taken from the Tournament eloquent file:
public function teams()
{
return $this->belongsToMany('Team', 'Tournament_Team');
}
You can get specific columns from the relation like this:
$tourTeams = Tournament::with(['teams'=>function($q){
$q->select('id','name');
}])->where('id', $tourId)->first();

Categories