Relationship between two tables in Eloquent (Laravel) based on a secondary table - php

Maybe I don't know the terminology for this, but I'm trying to create a HasMany relationship between Person and Car object.
Person:
id | user_name | created_at ....
Car:
id | make | model | year ...
Person_Car:
car_id | person_id
So obivously the relationship is defined by linking through the Person_Car relationship. Maybe I'm brain farting but I've forgotten what that this relationship is called and how to define Person as hasMany Cars
What's the name of the relationship and how can I define it in a Laravel Eloquent object?

Car class:
public function persons()
{
return $this->belongsToMany(Person::class);
}
Person class:
public function cars()
{
return $this->belongsToMany(Cars::class);
}
https://laravel.com/docs/5.6/eloquent-relationships#many-to-many

Use many to many relationship https://laravel.com/docs/5.6/eloquent-relationships#many-to-many
Car.php
public function persons()
{
return $this->belongsToMany('App\Car', 'Person_Car');
}

Related

Laravel Relationship with integer[] type of postgresql column

I have categories table and products table. in products table have category_id column type of integer[].
ex: {1,2,3}
.
And I need products list with category relation which categories.id exist products.category_id
I tried in model Product:
public function category()
{
return $this->belongsTo(Category::class, \DB::raw("ANY(category_id)"), 'id');
}
no get category is null.
you should use belongs to many relation.
because integer[] type is for saving arrays of ints.
try to set it in your model like this:
in your Product(model) you will get this relation method:
public function categories(): BelongsToMany
{
return $this->belongsToMany(Category::class);
}
And in your Category(model):
public function products(): BelongsToMany
{
return $this->belongsToMany(Product::class);
}
Refrence
You can try this using laravel query builder
public function category()
{
return DB::table('products')
->join('categories', 'products.category_id', '=', 'categories.id')
->get();
}
First of all, I dont think it's possible to do this with the Laravel Relationship Methods.
Second of all, if you are using Postgres, which is a relational Database, you should definitely read up on the fundamentals of database normalization.
I would recommend you have a so called pivot table, that links your products to your categories, which could look something like this:
Disclaimer: You dont need to create a Model for this. Just make a migration with php artisan make:migration create_categories_products_table
categories_products
| id | category_id | product_id |
|---------------------|------------------|---------------------|
| 55 | 1 | 5 |
| 56 | 2 | 5 |
| 57 | 3 | 5 |
| 58 | 1 | 6 |
This table links your tables and this is much more easy to handle than some arrays stored as json.. maybe think about it, it is not that much work to do. You can read upon it on the Laravel Documentation or try searching on google for pivot tables and normalization.
When you have done that:
Now you can just use the Laravel belongsToMany Relationship like so:
// Product.php
public function categories()
{
return $this->belongsToMany(Category::class, 'categories_products');
}
// Category.php
public function products()
{
return $this->belongsToMany(Product::class, 'categories_products');
}
I can't relation but with attribute i can get categories
firstly cast category_id to array and
public function getCategoriesAttribute()
{
return Category::whereIn('id',$this->category_id)->get();
}
and it works

Attaching extra model to BelongstoMany relations

I have two tables (users and drinks) with a pivot table, the user has a hasOne relation with profiles table, is there a way to attach the profile table to the pivot table and get all data.
Table user
id | name | email
Table profile
id | user_id | picture
Table drinks
id | name | price
Pivot Table user_drinks
id | user_id | drink_id | quantity | price | status
Drink Model
public function users()
{
return $this->belongsToMany('App\User', 'user_drinks', 'drink_id', 'user_id')->withPivot('price', 'quantity')->withTimestamps();
}
User Model
public function drinks()
{
return $this->belongsToMany('App\Drink', 'user_drinks', 'drink_id', 'user_id')->withPivot('price', 'quantity')->withTimestamps();
}
public function profile() {
return $this->hasOne('App\Profile');
}
PS: I don't wanna write this with raw sql query, it's driving me nuts.
I wouldn't change the tables relation.
I'd use the ->with() function to get the profile information within the existing relations.
So $user->drinks()->where('drink_id', $drink_id)->with('profile')->get(); would be my guess.

Make conditional Eloquent relationship in Laravel

Laravel 5.7. I have an Eloquent model Theme, with two fields, id and name.
Another model, Filter, has three fields: id, name, theme_id.
Filter:
class Filter extends Model
{
public function theme()
{
return $this->belongsTo('App\Theme');
}
}
I can attach these filters to an arbitrary number of other models, e.g. the model Foo has two fields, id and name. I attach the filter to it using a Filterables table:
Filterables:
id | filter_id | filterable_id | filterable_type
------------------------------------------------
1 | 1 | 3 | App\Foo
The above example shows that the Filter of id 1 is attached to the Foo of id 3.
Now to get all the filters of Foo, I have this relationship in my Foo model:
Foo:
class Foo extends Model
{
public function filters()
{
return $this->morphToMany('App\Filter', 'filterable');
}
}
This all works fine. But now I want to get the Foo model, and only the filters where the filter's theme_id is (for example) 1.
How can I add this condition to the filters relationship?
Just add a where clause directly to your relationship
class Foo extends Model
{
public function filters()
{
return $this->morphToMany('App\Filter', 'filterable')->where('theme_id', 1);
}
}

Laravel 5.6 Model HasManyThrough Relationships of 3 Tables

How to make a relationship between 3 tables of Laravel
+---------------+ +---------------+ +-------------------+
| venue_images | | transactions | | image_transaction |
+---------------+ +---------------+ +-------------------+
| id | | id | | venue_image_id |
| user_id | | user_id | | transaction_id |
+---------------+ +---------------+ +-------------------+
Here's my code but it's not working.
class Transaction extends Model
{
public function images(){
return $this->hasManyThrough(ImageTransaction::class ,VenueImage::class, 'transaction_id', 'id');
}
}
I want to join the three tables using transaction id and venue image id
on my controller
$transactions = transaction::where('user_id', Auth::id())->with('images')->get();
If I don't misunderstood your question you have a pivot table image_transaction which is many-to-many relationship. Eloquent automatically arrange pivot table's name alphabetically like transactions_venue_image so you need to pass your custom name image_transaction in the parameter. [docs]
In your VenueImage Model
public function transactions()
{
return $this->belongsToMany('App\Transaction','image_transaction');
}
In your Transaction Model
public function venue_images()
{
return $this->belongsToMany('App\VenueImage','image_transaction');
}
There are also 3rd and 4th parameters which are foreign keys of the related model which are explained better in the docs.
In your Controller
$transactions = transaction::where('user_id', Auth::id())->with('venue_images')->get();
The order of the parameters to the hasManyThrough function looks wrong. According to the Laravel documentation
The first argument passed to the hasManyThrough method is the name of the final model we wish to access, while the second argument is the name of the intermediate model.
So in your case it should be like this (without defining the foreign keys)
class Transaction extends Model
{
public function images() {
return $this->hasManyThrough(VenueImage::class, ImageTransaction::class);
}
}
If this does not work try to include the keys as described in the documentation:
Typical Eloquent foreign key conventions will be used when performing the relationship's queries. If you would like to customize the keys of the relationship, you may pass them as the third and fourth arguments to the hasManyThrough method. The third argument is the name of the foreign key on the intermediate model. The fourth argument is the name of the foreign key on the final model. The fifth argument is the local key, while the sixth argument is the local key of the intermediate model.
You should try this:
class Transaction extends Model
{
public function images(){
return $this->belongsToMany(ImageTransaction::class ,VenueImage::class, 'transaction_id', 'id');
}
}

Laravel variable model polymorphic

I have a table as follows in my database:
table area_blocks;
id
owner_type
owner_id
created_at
updated_at
in the owner_type field it has the Eloquent Model name and the owner_id is the id of that model in the database. Example:
db: area_blocks
id | owner_type | owner_id
1 | App\Models\Title | 3
2 | App\Models\Title | 4
3 | App\Models\Textarea | 1
So I'm expecting when I fetch all of these to also eager load the relevant field from the eloquent model stored in owner_type.
Is there an eloquent relationship that can bring back that record from the owner_type field using eager loading? I've tried $this->morphTo(), e.g.
public function block()
{
return $this->morphTo();
}
but that is returned as null. Any ideas how this can be done?
Example code;
<?php
namespace App\Models;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\Model;
class AreaBlocks extends Model
{
protected $with = ['block'];
public function block()
{
return $this->morphTo();
}
}
Route::get('/', function(){
return App\Models\AreaBlocks::all();
});
You have to specify the column name/prefix:
public function block()
{
return $this->morphTo('owner');
}
Or rename the relationship:
public function owner()
{
return $this->morphTo();
}

Categories