How to assign relationship and fetch data using array field in laravel - php

There are two models: Restaurant and Category
Restaurant{
'_id' : 12345678
'name' : "xyz",
'abstract' : "awdwadawdawdawd",
'category': [1,2,3,4] //category ids
}
Category{
'_id' : 1,
'name' : 'PQR'
}
How can I assign relationship and fetch all the categories using that array field (category) of Restaurant in laravel 5.3 and Database is mongodb?

I am not quite sure about your DB structure, but I think it would be better to create a new pivot table to store the categories of each restaurant in a different row like this:
id | restaurant_id | category_id
1 | 23 | 3
2 | 23 | 5
3 | 25 | 4
As a convention the table should be named 'category_restaurant'
This would be a many to many relationship in laravel.
class Restaurant
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
class Category
{
public function restaurants()
{
return $this->belongsToMany(Restaurant::class);
}
}
Then in your code you can get the ids of a restaurant in this way:
$restaurant = Restaurant::find(1);
$categories = $restaurant->categories;

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

How to query with nested distinct records in Laravel/Eloquent?

I have the following table structure:
Products
========
id | name
------|-------
1 | A
2 | B
Stocks
========
id | product_id | color_id | size | qty
------|------------|----------|----- |-----
1 | 1 | 1 | S | 37
2 | 1 | 1 | XL | 89
3 | 1 | 2 | S | 6
4 | 1 | 2 | L | 8
Colors
========
id | name | hex
------|-------|-------
1 | Red | #ff0000
2 | Green | #00ff00
What I want is to get the list of products with each of its available colors and sizes, so:
Product {
id: string
name: string
available_sizes: string[]
available_colors: Color[]
}
I looked up the Laravel documentation and figured that I need to use hasManyThrough (probably) to make a relation between Product <==> Color. But since my colors table doesn't have a stock_id, I am not understanding how can I connect them.
How can I achieve this?
As I understand, hasManyThrough works in a scenario that a product has many stocks and a stock has many colors. This is not the case.
You can simply eager load the relationship and present the data the way you want, using collection and higher order messages:
public function index()
{
$products = Product::with('stocks.color')->get();
return ProductResource::collection($products);
}
class ProductResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'available_sizes' => $this->stocks->map->size->unique()->toArray(),
'available_colors' => $this->stocks
->map->color
->map->name
->unique()
->toArray()
]
}
}
here you will use models
ProductModel
public function stocks()
{
return $this->belongsto(StockModel::class,'product_id');
}
StockModel
public function colors()
{
return $this->hasmany(ColorModel::class,'color_id');
}
Controller
$product=Product::with('stocks.colors')->find($id);
dd($product);
and check if the data are available.
or according to the documentation hasmanythrough
ProductModel:
public function colors(){
return $this->hasManyThrough(
Stock::class,
Color::class,
'product_id', // Foreign key on the product table...
'color_id', // Foreign key on the colors table...
'id', // Local key on the products table...
'id' // Local key on colors table...
);
}
Controller:
$product=Product::with('colors')->find($id);

Problem when getting records from database with relationship table

I'm having trouble relating photos to tags using an intermediate table.
In the example below, how can I select all photos that belong to tag 1 with an Eloquent relationship method in Laravel?
I have these tables:
-Photos Table
| id | name | description |
1 photo1.png ....
2 photo2.png ....
3 photo3.png ....
-Tags Table
| id | name |
1 Aesthetic
2 Dark
-Tags Relations
| id | tag_id | photo_id |
1 1 3
2 1 2
3 2 1
First of, you need to ensure that both Photos and Tags table have the relationship defined.
Under the Photos model you should have the following function:
public function tags() {
return $this->belongsToMany(
Tag::class,
"photos_tags", // the name of the pivot table
"photo_id",
"tag_id"
);
}
Under the Tags model you should have the following function:
public function photos() {
return $this->belongsToMany(
Photo::class,
"tags_photos", // the name of the pivot table
"tag_id",
"photo_id"
);
}
Now to access all the tags that are related to the Photo of id 1, you can call the following:
Photo::findOrFail(1)->tags()->get();
And the same you can do for a specific tag to get all it's photos.
Tag::findOrFail(1)->photos()->get();
Hope this will lead you to what you wish.

How to count items where foreign key is repeated?

How I can count items with same foreign key and still get acces to relationship data?
I'm using PHP - Laravel - Eloquent, and have three tables: User, User_items and items.
User_items has three columns: id, user_id and item_id:
ID | user_id | item_id
0 | 5 | 2
1 | 5 | 3
2 | 5 | 8
3 | 5 | 3
Let's say items also has three columns: id, name and value:
ID | Name | Value
2 | Sword | 500
3 | Pickaxe | 250
8 | Shovel | 700
I want to count items with the same user_id and return item data from the items table. In order to get all of the user items, I'm using the following relationship:
public function user_items()
{
return $this->hasMany(User_items::class, 'user_id', 'id');
}
Next, I want to get the names of these items and count them. I don't just want:
Sword
Pickaxe
Shovel
Pickaxe
I want, somehow, to get the results like this:
2 Pickaxe
1 Sword
1 Shovel
My user_items relationship, to get the data about an item looks like :
public function item_data()
{
return $this->hasOne(Items::class, 'id', 'item_id');
}
Thats how I'm getting repeatable result:
return response()->json(["DATA" => $user->user_items->load('item_data')->toArray()], 201);
Example output
"DATA":[
{
"id":1,
"item_id":5,
"created_at":"2019-06-04 08:44:08",
"updated_at":"2019-06-04 08:44:08",
"item_data":{
"id":5,
"name":"Sword",
"rarity":"good",
"value":500,
"image":"image.jpg",
"color":"#3160ed",
"created_at":null,
"updated_at":null
}
},
}
I want to add a row like "count": 5 to the above output.
I reckon what you need is a many-to-many relationship between a user and an item.
I rename the tables like this for better naming convention: users, user_item, items.
class User
{
public function items()
{
return $this->belongsToMany(Item::class)
}
}
For each user to return the items and the number of items for each. You might do something like.
$items = $user->items()->select('items.*', 'count(items.id) AS items_count')
->groupBy('items.id')
->get()
->toArray();
// From the controller, this array will be automatically converted to json.
return ['DATA' => $items];
You will have something like this. Not exactly the format you want, but I think it's better keep it this way.
[
'DATA' => [
{
"id":5,
"name":"Sword",
"rarity":"good",
"value":500,
"image":"image.jpg",
"color":"#3160ed",
"created_at":null,
"updated_at":null,
items_count: 1
}
]
]

Laravel 5.4 | Fetching data from Pivot Table

I have 4 tables in my database:
Table 1: Category
---|------
id | name
---|------
1 | Cars
In 'Category' model class I have defined the following relationship:
class Category {
public function fields() {
return $this->belongsToMany('App\Field');
}
}
Table 2: Field
id | name
---|-------
1 | Make
In 'Field' model class I have defined the following relationship:
class Field {
public function categories() {
return $this->belongsToMany('App\Category');
}
}
Table 3: Field_Options
field_id | value
---------|-------
1 | Audi
1 | BMW
In 'FieldOption' model class I have defined the following relationship:
class FieldOption extends Model
{
public function field() {
return $this->belongsTo('App\Field');
}
}
Table 4: Category_Field
category_id | field_id
------------|-------
1 | 1
Now I need to fetch all the fields and field_options for category_id=1. How can I achieve this using Laravel?
Thanks!
First define relationship between Field and FieldOptions
public function options() {
return $this->hasMany('App\FieldOption');
}
Then you can eager load all relationships like this
$category = Category::with('fields.options')->find(1);
//Get category 1, with all fields and their respectif fieldOptions

Categories