How to synchronise child table data on hasMany relationship? - laravel

I have 2 table products and variants, with a hasMany relationship, the structure is below :
Product Model :
public function variants()
{
return $this->hasMany(Variant::class);
}
Variant Model :
public function product()
{
return $this->belongsTo(Product::class);
}
Product Table :
| id name image manufacturer
| 1 T-Shirt t-s.jpg docomo
| 2 Short Skirt s-skirt.jpg docomo
Variant Table :
| id product_id name price sku quantity
| 1 1 S 30 ts-s 100
| 2 1 M 32 ts-m 100
| 3 1 XL 35 ts-xl 100
| 4 2 S 23 sk-s 100
| 5 2 M 25 sk-m 100
| 6 2 XL 28 sk-xl 100
I can save data on Variant model (child table) from Product model as :
public function store(Request $request)
{
$q = new Product;
$q->name = $request->name;
$q->save();
// Below child table
$q->variants()->createMany($request->variant);
}
I can store data, but the problem is that, how can I update child table? [It can be create, update or delete]
I tried with sync() method, but didn't work. Its for manyToMany relationship.
public function update(Request $request)
{
$q = Product::findOrFail($request->id);
$q->name = $request->name;
$q->save();
// Below child table update
// $q->variants()->sync($request->variant); // not worked
}
sync() works in manyToMany relationship. I need the same for hasMany relationship.
How can I do that?

Unfortunately there is no sync method for hasMany relations. It's pretty simple to do it by yourself. You can simple delete the rows and insert them all again.
public function update(Request $request, Product $product)
{
$product->update(['name' => $request->name]);
// Below child table update
$product->variants()->delete();
$product->variants()->sync($request->variant);
}

Related

How to merge categories table with items table and returtn array of each category with items

I have three tables and after each table is the defined eloquent relationship of each entity.
categories
id
name
1
cars
2
bikes
public function items()
{
return $this->belongsToMany(AccountItem::class, "category_item", "category_id", "item_id");
}
category_items
id
category_id
item_id
1
1
1
2
1
2
items
id
name
1
volks
2
bmw
public function categories()
{
return $this->belongsToMany(Category::class, "category_items", "item_id", "category_id");
}
I am stuck on how to get a function that will return an array of the data with each category and the corresponding items. Incase the category has null items it returns a empty array of the category.
I assume your relationship is correct. If so, you can do this to load.
$categories = Category::with('items')->get();
foreach ($categories as $category) {
$categoryArray = [
'id' => $category->id,
'name' => $category->name,
'items' => $category->items->toArray()
];
}

How to establish a dynamic model relationship in Laravel?

I need to establish a dynamic relationship but I can't.
The table design is as follows.
Page Table
id
title
1
Hello world
2
Contact
Category Table
id
title
1
Electronics
2
Sports
Blog Table
id
title
1
First blog
Links Type
id
name
1
Page
2
Category
3
Blog
Links Table
id
type_id
relation_id
slug
1
1
1
page/hello-world
2
1
2
page/contact
3
2
1
category/electronics
3
2
2
category/sports
3
3
1
blog/first-blog
CODE
Controller:
$links = Links::with('title')->get();
return response()->json($links);
// I need to get the "title" key.
Links Model:
public function title() {
switch($this->type_id) {
case '1':
return $this->hasOne(Page::class, 'id', 'relation_id');
break;
case '2':
return $this->hasOne(Category::class, 'id', 'relation_id');
break;
case '3':
return $this->hasOne(Blog::class, 'id', 'relation_id');
break;
}
}
This state does not work because the model has not yet been formed.
Error Output
Call to a member function addEagerConstraints() on null
How should I go about it?
Thanks.
What you are doing can be achieved by using polymorphic relationships.
pages
id - integer
name - string
categories
id - integer
title - string
blogs
id - integer
title - string
link_types
id - integer
name - string
links
id - integer
link_type_id - integer
linkable_id - integer
linkable_type - string
Page, Category and Blog model should define these relationships
public function link_types()
{
return $this->morphToMany(LinkType::class, 'linkable', 'links')->using(Link::class);
}
public function links()
{
return $this->morphMany(Link::class, 'linkable')
}
LinkType model should define these relationships
public function pages()
{
return $this->morphedByMany(Page::class, 'linkable', 'links')->using(Link::class);
}
public function categories()
{
return $this->morphedByMany(Category::class, 'linkable', 'links')->using(Link::class);
}
public function blogs()
{
return $this->morphedByMany(Blog::class, 'linkable', 'links')->using(Link::class);
}
Link model should define these relationships
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\MorphPivot;
class Link extends MorphPivot
{
/**
* Get the parent linkable model (blog, category, page).
*/
public function linkable()
{
return $this->morphTo();
}
public function link_type()
{
return $this->belongsTo(LinkType::class, 'link_type_id');
}
}
Eloquent Relationships - One To Many Polymorphic Relations
Eloquent Relationships - Many To Many Polymorphic Relations
$link = Link::with('linkable')->first();
$link->linkable->title;

Getting data from pivot table using eloquent

I have two tables with a pivot table
Table user
id | name | email
Table drinks
id | name
Pivot Table user_drinks
id | user_id | drink_id | quantity | price | status
I want to get all users and drinks with status set to 1 and their latest details from the pivot table, that is use the user_Id to get the username and drink_Id to get the drink name then the price and quantity from the pivot table.
In your User Model put this //App\User.php
public function drinks()
{
return $this->belongsToMany(Drink::class)->where('status',1);
}
In your DrinkModel put this //App\Drink.php
public function users()
{
return $this->belongsToMany(Drink::class)->where('status',1);
}
Then in your controller you can use this like
$users = User::has('drinks')->get(); //to get all the user that has drinks column status set to 1
foreach ($users as $user) {
//you rest of code
}

How to query a table based on criteria of another table in Laravel?

In my laravel project I have an inventory and a medicine table which the formats are as the following:
Inventory Table
id | medicine_id | expiry_date
-------|-----------------|-------------
1 | 1 | 13-11-2021
2 | 2 | 01-01-2020
3 | 2 | 23-05-2024
Medicine Table
id | name | category
-------|-----------------|-------------
1 | Hemophine | Syringe
2 | andrenalin | Tablet
3 | aspirin | Capsule
The models are set as below:
Inventory Model
class Inventory extends Model
{
public $incrementing = false;
public function medicine(){
return $this->belongsTo('App\Medicine', 'medicine_id');
}
}
Medicine Model
class Medicine extends Model
{
public $incrementing = false;
public function inventory(){
return $this->hasMany('App\Inventory', 'medicine_id');
}
}
For retrieving all the inventories with a specific category such as Syringe, I tried eager loading, but couldn't figure out the flaws. Here is what I did to get all the inventories with a Syringe category, but it didn't work.
public function index()
{
$medicines = Inventory::where('medicine_id'->category, "Syringe")->get();
foreach($medicines as $medicine){
echo $medicine->medicine->name ." ".$medicine->expiry_date;
echo "<br>";
}
}
Now, Is there anyway to get all the inventory items based on their categories they are in? in this case in "Syringe" category?
Your syntax is a bit wrong, in order to load the medicine for each inventory you need to use with and the where function is where('column', value)
So change it to this:
$medicines = Inventory::with([
'medicine' => function($query) {
$query->where('category', "Syringe");
}
])->get();
or even better the other way around:
$medicines = Medicine::with('inventory')->where('category', 'Syringe')->get();

Laravel - Eloquent - Polymorphic relationships with namespaces

I have 2 tables related by a polimorphic relationship:
The Store table:
id | name | ...
15 | my_store | ...
And the Tag table, that is connected to the Store table through the related_id key and the type.
id | related_id | tag | created | type
1 | 15 | test | 00:00:00 | store
2 | 15 | dummy | 00:00:00 | product
So, in that example, the Store "my_store" only has the tag "test" ("dummy" is a tag for a product, not a Store, besides it has the same related_id).
I have the Store model defined in my code as follows:
class Store extends Model {
protected $table = 'store';
public function tags()
{
return $this->morphMany('App\Tag', 'related', 'type');
}
}
And the tag model:
class Tag extends Model {
protected $table = 'tags';
public function related()
{
return $this->morphTo();
}
}
But when I try to run
$store->tags;
I saw that the query that Laravel is trying to run is:
SQL: select * from `mwp_tags` where `mwp_tags`.`related_id` = 46
and `mwp_tags`.`related_id` is not null
and `mwp_tags`.`type` = App\Store)
The query is looking for App\Store instead of store
I cannot change the value in DB and I wouldn't like to use the
protected $morphClass = 'store';
inside the Store model as I don't know if a would have to create another morphMany relationship, probably with another type name.
Somebody knows how to skip this issue? Thanks!
You could try something like this:
public function tags()
{
$default_morph_class = $this->morphClass ?: null;
$this->morphClass = 'store';
$morph_many_query = $this->morphMany('App\Tag', 'related', 'type');
$this->morphClass = $default_morph_class;
return $morph_many_query;
}
The idea being you change the morphClass on the fly and set it back. That allows you to use a different morphClass for a different relationship.

Resources