Laravel relationship storing to pivot null - php

I have 3 tables called games, products, game_product. And game_product is my pivot table
This is the structure.
id
game_id
product_id
1
1
1
1
1
2
30 Minutes ago I can attach the game_id and product_id correctly, then i changed nothing. And after I tried to create a new data, its give me this error message
Call to a member function games() on null
This is my model relationship
App\Models\Game.php :
public function products()
{
return $this->belongsToMany('App\Models\Product', 'game_product', 'product_id', 'game_id');
}
App\Models\Product.php :
public function games()
{
return $this->belongsToMany('App\Models\Game', 'game_product', 'game_id', 'product_id' );
And this is my create controller
public function productsNew(Request $request, $id)
{
$products = Product::find($id);
$new = Product::create([
'product_sku' => $request->product_sku,
'name' => $request->name,
'seller_price' => $request->seller_price,
'price' => $request->price,
'profit' => $request->price - $request->seller_price,
]);
$products->games()->attach($id);
$new->save();
notify("Product added successfully!", "", "success");
return redirect('admin/products/'.$id);
}
}
I try to post the id of game and product to pivot table game_id and product_id. What should I do to store the ID only without any other of value?

Just change the order of
$products->games()->attach($id);
$new->save();
to be
$new->save();
$products->games()->attach($id);
As a side note, you are creating a product. Just 1 product. So the variable name mustn't be pluralized as it is singular. $product
One final thing, if this function is just part of the CRUD, please follow the convention of naming functions to be: create/store/show/edit/update/destroy, makes your and everyone else's lives easier when asking questions.

Related

Saving relations in Laravel

I've got table Competitions and Competition_categories. Their relationship is
competitions.id = competition_categories.competition_id. I can create new competition with no problem but the Competition_categories is not saving any related records. My models:
Competition Model:
public function competition_category()
{
return $this->hasMany(CompetitionCategory::class, 'competition_id', 'id');
}
CompetitionCategory Model
public function competition()
{
return $this->belongsTo( Competition::class, 'competition_id' );
}
My Controller code - store method:
$request->validate([
'name' => 'required',
'frequency' => 'required|integer',
]);
$competition = Competition::create($request->all());
$competition_category = CompetitionCategory::create($request->all());
$competition_category->competition()->associate($competition);
$competition_category->save();
I've checked the documentation and other related questions but did not manage to get it working can you help me?
I'm expecting when I create new competitions new records to be saved in both tables. (New competitions are created successfully but no records in the category table. Also, one competition can have more than one category)
i can see a problem in your controller class, Laravel would advice not to create a class for pivot table, first you will need to update your question for better clarification, however here is a senerio and how to approach this.
Tables
Competition,
Categories,
Category_competition (pivot table)
reference for you
Competition Model:
public function category()
{
return $this->belongsToMany(Category::class, 'Category_competition','competition_id', 'category_id')->withPivot(['pivot attributes here']);
}
Category Model:
public function compitition()
{
return $this->belongsToMany(Compitition::class, 'Category_competition', 'category_id;'competition_id', 'id');
}
Then
$request->validate([
'name' => 'required',
'frequency' => 'required|integer',
]);
$competition = Competition::create($request->all());
$competition->category()->attach($category_attributes = []);

Laravel eloquent multiple belongsTo seeding

I have three models, User, Category and Article.
Article belongs to both a User and a Category where the foreign keys user_id and category_id are not null.
Am lost trying to seed the database with fake data via factories accordingly, here's the seeding code...
// 2 categories and 12 articles, 6 per category
// TODO: A user should have 6 articles with mixed categories
// 3 from each category
// So we will have 2 users
factory(Category::class, 2)->create()->each(function($category) {
factory(User::class)->create()->each(function($user) use ($category) {
// How to assign an Article to $category or $user while creating?
$user->articles()->createMany(
factory(Article::class, 3)->make()->toArray()
); // category_id can't be null
// OR
$category->articles()->createMany(
factory(Article::class, 3)->make()->toArray()
); // user_id can't be null
});
});
I'll get one of two errors, either
Column user_id doesn't have a default value
Or
Column category_id doesn't have a default value
Which is logical due to the Article table migration
$table->increments('id');
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
How can I pass the category_id or user_id to the factory call?
Is there a better way to acheive this?
Thanks in advance
You can override attributes for your factory by passing an array with the desired attributes to the make() method:
Change
$user->articles()->createMany(
factory(Article::class, 3)->make()->toArray()
);
to
$user->articles()->createMany(
factory(Article::class, 3)->make([
'category_id' => $category->id
])->toArray()
);
to override the category_id attribute.
https://laravel.com/docs/6.x/database-testing#using-factories
Seed the categories separately.
Then seed the users and inside it seed the articles.
In the article factory file ArticleFactory:
$factory->define(App\Article::class, function (Faker $faker) {
return [
'category_id' => App\Category::inRandomOrder()->value('id'),
....
'created_at' => time(),
'updated_at' => time(),
];
});
This may help you
First
make users create when you make a new article from factory
$factory->define(App\Article::class, function ($faker) use ($factory) {
return [
'user_id' => $factory->create(App\User::class)->id,
'title' => $faker->sentence,
'body' => $faker->paragraph
];
});
Second
from your seeder
in this example i will make 3 categories * 6 Articles
factory('App\Category', 3)->create()->each(function($u) {
$u->posts()->save(factory('App\Article', 6)->create());
});

Laravel attach manytomany with extra field

There are 3 tables. Products, Users and product_user. There are 3 fields in product_user table. product_id, user_id and price.
product_id and user_id will be attached and filled automatically. But I want a textfield named price which user fill it to be inserted in price field in database.
I mean I want to insert a textfield when attaching.
To insert an extra field in your pivot table first of all, you need to specify this extra field in your models.
For Example this:
In Product model
public function users()
{
return $this->belongsToMany('App\User', 'product_user')
->withPivot('price');
}
In User model
public function products()
{
return $this->belongsToMany('App\Product', 'product_user')
->withPivot('price');
}
Furthermore, in you Controller you can attach this extra field like this:
$product->users()->attach($user_id, ['price'=> $price ]);
I hope this will help you !!!
A best practice example to pass one array to attach is this example:
$extra = array(
'expense_type_id' => $request->expenseType,
'quantity' => $request->quantity,
'price' => $request->price
);
//dd($extra);
$logisticCost->expenses()->attach($logisticCost->id,$extra);
Cheers!

Insert in many to many relation laravel 5

I have 2 models:
class Order extends Model
{
protected $fillable = ['user_id','name','surname','fathers_name','phone_number','city','post_office','comment'];
public function user()
{
return $this->belongsTo('App\User');
}
public function products()
{
return $this->belongsToMany('App\Product', 'order_product');
}
}
class Product extends Model
{
public function order()
{
return $this->belongsToMany('App\Order', 'order_product');
}
public function category()
{
return $this->belongsTo('App\Category');
}
}
3 tables:
product:
id
name
...
order_product:
id
order_id
prod_id
qty
...
order
id
city
phone
...
and 2 arrays of data:
$data = $request->except('_token','submit'); - information about client
$order_content - array with info about products in cart
So, the question is how to insert all this data in DB? I tried to read about many to many insertion: sync, attach, etc.. but understood nothing :c
Imagine you have a product with id 1. And an order with id 1. The product is part of the order, so you have to attach them. You do
$product = Product::find(1);
$order = Order::find(1);
$order->products()->attach($order->id);
However, in your case, your pivot table has more data, like 'qty'. Then you do,
$order->product()->attach($order->id, ['qty' => 2]);
So far, we were only attaching a single product to an order. If you want to attach many products simultaneously, you do:
$order->products()->sync([
$product->id => ['qty' => 1],
$product2->id => ['qty' => 3]
]);
I hope this helps understand better. I recommend you read the doc again and again until it makes sense.

How to get data from related table in Laravel (one to many)?

I have two tables: users, orders. I try to get all orders for current user.
Users Orders
_____ ______
id | name id | user_id
User model:
public function orders(){
return $this->hasMany("App\Order");
}
Order model:
public function user(){
return $this->hasOne("App\User", 'user_id', 'id');
}
Query in controller:
public function index()
{
$orders = Order::where('user_id', Auth::guard('api')->id())->get();
return response()->json(
$orders->user
);
}
I get NULL result, I do something wrong, because there are related rows in both tables.
If you want to retrieve all the Orders belonging to the current user, try using the following function.
public function index()
{
$orders = Auth::user()->with('Orders')->get()->toArray();//To get the output in array
/* ^ ^
This will get the user | This will get all the Orders related to the user*/
return response()->json($orders);
}
As pointed out by #Martin Heralecký, you would also need to change the hasOne() to belongsTo() in Order Model. See following (copied from #Martin Heralecký answer)
public function user(){
return $this->belongsTo("App\User");// second and third arguments are unnecessary.
}
Why belongsTo():
has_one and belongs_to generally are the same in the sense that they point to the other related model. belongs_to make sure that this model has the foreign_key defined. has_one makes sure that the other model has_foreign key defined.
Your $orders array will look something like this:
User => [
id => 'user id',
name => 'user name'
orders => [
0 => [
//order data
]
1 => [
//order data
]
.
.
.
.
]
]
In Order model you need to use the belongsTo relationship:
public function user()
{
return $this->belongsTo("App\User"); // second and third arguments are unnecessary.
}
In User model you can use hasMany relationship, for example in:
App/User.php
Add
public function orders()
{
return $this->hasMany("App\Order", "user_id", "id");
}
Now you can use this:
return User::find(1)->orders;

Categories