How to setup Eloquent Models ManyToMany for self-joins - php

I have two tables, products and pack_product
`product` table: product_id, model, price;
`pack_product` table: product_id, pack_id;
`product` table data:
product_id model price
1 model1 100
2 model2 150
3 model3 200
4 Pack1 300
5 Pack2 400
`pack_product` table data:
product_id pack_id
1 4
2 4
3 5
I registered all relationships in the Products model class and I would like to fetch all product data from the pivot table, but I getting empty array.
Products model:
/**
* Products can belong to many packs
*/
public function packs(){
return $this->belongsToMany(static::class, 'pack_product', 'products_id', 'pack_id');
}
/**
* Pack can have many products
*/
public function products(){
return $this->belongsToMany(static::class, 'pack_product', 'pack_id', 'products_id');
}
Controller
$products = new Products;
$products->products()->get();
// or
$product = Products::find(1);
$product->packs;
// getting [] output
UPDATE
The relations are connected right, but I cannot to print them.

Related

Laravel filament, is there any way to mutate TextColumn value in table?

How to get only one value in the filament table for with hasMany relationship?
I have two DB tables:
products
id
sku
1
SKU_1
2
SKU_2
product_descriptions
id
product_id
translation_id
name
1
1
1
Opel
2
1
2
Vauxhall
In my Product model I have hasMany relationship
public function productDescriptions(): HasMany
{
return $this->hasMany(ProductDescription::class);
}
When I do Tables\Columns\TextColumn::make('productDescriptions.name') it return all values separated by comma. In my example "Opel, Vauxhall"
Is there any way to manipulate/mutate return value using callback? Let say, return only first value "Opel"?
You can use calculated states.
Tables\Columns\TextColumn::make('productDescriptions.name')
->getStateUsing( function (Model $record){
return $record->productDescriptions()->first()?->name;
});

Get products count of all nested categories in parent category

categories
id
name
parent_id ?
products
id
name
category_id
In the category there can be both children and products
i need the count of products within the categories even it has children . Let's say categories have 2 products and 2 subcategories. both categories have 2 products each without subcategories. per category parent the count of products will be 6.categories can be parent->sub->sub 3 max.
class Category extends Model
{
public function activeChildren(): HasMany
{
return $this->hasMany(self::class, 'parent_id')
->active()
->with('activeChildren');
}
public function activeProducts(): HasMany
{
return $this->hasMany(Product::class)->where('is_active', true);
}

Laravel joining table relationship

I'm wanting to do a joining table but I'm not sure how to set up the relationship in laravel.
I have 3 tables, products, categories, and product_categories. product_categories will consist of the product ID and the category ID. How would I join theses up in a relationship in laravel so I can just call $product->categories() like a normal relationship?
Your relationship will be belongsToMany.
Your products table would be
id | name
Your categories table would be
id | name
your product_categories table would be
id | product_id | category_id
As per relationship in Laravel
Product Model
class Product extends Model
{
protected $table = 'products';
public function categories()
{
return $this->belongsToMany('App\Category','product_categories','product_id','category_id');
}
}
Category Model
class Category extends Model
{
protected $table = 'categories';
public function products()
{
return $this->belongsToMany('App\Product','product_categories','category_id','product_id');
}
}
In controller now
Product::with('categories')->get();
This is a many-to-many relationship.
You can use belongsToMany on both products and categories and it would work. However you also should rename product_categories to follow the rule
use singular table names in alphabetical order
this would be category_product

belongsToMany with parent-child relationship in Laravel 5

I have two models that are related to each other with a belongsToMany relationship. The models are Game and Category. Of course, the tables for both are games and categories. The Category model, has its own parent-child relationship.
Basically this is my "simplified" structure:
Table game:
id unsigned integer
name string
Table categories:
id unsigned integer
name string
parent_id unsigned integer nullable
The parent_id column is null when the category has no parent, but it has an existing id referencing a row in the same table if it is a children of some other category.
Table category_game
category_id unsigned integer
game_id unsigned integer
The category_id column, references id on categories table. It should reference only the top category that a game belongs to. A game can belong to many different categories, but in the pivot table, there should only be a reference to the parents categories. For example if I had this structure of categories:
Category 1
Category 2
Category 4
Category 3
Category 9
Category 5
Category 6
Category 7
Category 8
I would like to have the following information for my games 1 and 2:
category_id game_id
3 1
5 1
1 2
And that should mean that my game 1 has categories: 3, 9, 5, 6, 7 and 8.
While my game 2 has categories: 1, 2, 4, 3 and 9
I understand that my Laravel models should have this:
class Game {
public function categories(){
return $this->belongsToMany( Category::class );
}
}
class Category{
public function games(){
return $this->belongsToMany( Game::class );
}
}
But I don't know how to retrieve the children categories using Eloquent. I know the belongsToMany method has more parameters that might help with my problem, but I don't know how to use them.
Model categoryGame for table category_game
class CategoryGame{
public function childCategories() {
return $this->hasMany(Category::class, 'parent_id','category_id');
}
}
You can access
$games = App\CategoryGame::all();
foreach ($games as $game ) {
foreach ($game->childCategories as $category) {
echo $category->name;
}
}
Let me know if not works
Extend your models:
class Category {
public function children() {
return $this->hasMany(Category::class, 'parent_id');
}
}
class Game {
public function getAllCategoriesAttribute() {
$result = collect();
$children = function($categories) use(&$result, &$children) {
if($categories->isEmpty()) return;
$result = $result->merge($categories);
$children($categories->pluck('children')->collapse());
};
$children($this->categories);
return $result;
}
}
Then you can access the categories like this:
Game::find($id)->allCategories;

Laravel Eloquent relationships - user country regions

I am using Laravel 5.5. I have a MySQL table implementation that contains
Table: regions
id name
1 NA
2 SA
3 AP
3 ASEAN
The user can create regions and allocate countries to them.
Pivot table: region_countries
id region_id country_id
1 1 1
2 1 2 ....
210 5 1
A country can belong to many regions, as the user can create a custom region, by grouping countries.
Table: countries
id name ....
1 Argentina....
A user belongs to a country, and thus to many regions
Table: Users
id name country_id
1 John Smith 32
My Country class contains:
/**
* Countries have many Regions
*/
public function regions()
{
return $this->hasManyThrough(Region::class, RegionCountry::class);
}
My Region class contains:
/**
* Regions have many Countries
*/
public function countries()
{
return $this->hasManyThrough(Country::class, RegionCountry::class);
}
So for the User class relationships, Is this the correct way to do this?
/**
* A User has a Country
*/
public function country()
{
return $this->belongsTo(Country::class, 'country_id');
}
/**
* A User has many Regions
*/
public function regions()
{
return $this->country()->hasMany(Region::class, 'region_id');
}
And the reverse, Region class has many Users
/**
* Regions have many Countries
*/
public function countries()
{
return $this->hasMany(Country::class, 'country_id');
}
/**
* Regions have many Users
*/
public function users()
{
return $this->countries()->hasMany(User::class, 'country_id');
}

Categories