Laravel one-to-many update failure problem - php

class Video extends Model
{
public function categories(): BelongsToMany
{
return $this->belongsToMany(Category::class, CategoryVideo::class, 'video_id','category_id');
}
}
DB::beginTransaction();
$video = Video::find($id);
$video->update($data);
// update categorie count
$items = $video->categories()->get(['category_id', 'video_count']);
foreach ($items as $item){
$item->video_count = Category::where('category_id',$item->category_id)->count();
$item->save();
//$item->update(['video_count' => Category::where('category_id',$item->category_id)->count()]);
}
DB::commit();
save and update have no effect
Ask for help
I want to find out the associated classification through the video, and update the number of videos under the classification

the second parameter in many to many relation is the pivot table model name, not the the pivot model name, so your relation should be like this:
public function categories(): BelongsToMany
{
return $this->belongsToMany(Category::class, 'category_video', 'video_id','category_id');
}
please replace the second parameter 'category_video' by the name of your pivot table.
you also have to select the primary key in categories when you get Category model instance:
$items = $video->categories()->get(['id','category_id', 'video_count']);

Related

Laravel Eloquent getting data from relations

I have Task model. My Task model has some relationships and it currently looks like this:
class Task extends Model
{
use HasFactory;
public $timestamps = false;
public function city()
{
return $this->hasOne(City::class, 'id', 'city_id');
}
public function type()
{
return $this->hasOne(Type::class, 'id', 'type_id');
}
public function note()
{
return $this->hasOne(Note::class, 'id', 'note_id');
}
public function operator()
{
return $this->hasOne(User::class, 'id', 'operator_id');
}
}
Now, in my TasksController I need to get Tasks that match certain criteria, like this:
$tasks = Task::whereCityId($city->id)->whereTypeId($type->id)->get()->toArray();
The problem is that fields named city_id type_id note_id operator_id will get my integer values that they have.
Instead I would like to get certain value from a related Model.
For example:
operator_id should be replaced with username from User table that corresponds to the user id.
An obvious solution to this would be to simply use foreach loop, go through my results and get the data I need and simply create another array with the information replaced, but I am not sure if this is the best idea and perhaps there is something better.
You have to change in your code:
$this->hasOne(ClassName::class, 'id', 'foreign_key');
To
$this->belongsTo(ClassName::class, 'foreign_key', 'id');
because Task's id does not available as foreign key in these tables. These table's id present in task table as foreign key so you have to use belongsTo() relationship to tell script from where these id belongs.
Then access properties like this:
$tasks = Task::with("type", "city", "operator")
->whereCityId($city->id)->whereTypeId($type->id)->get();
foreach($tasks as $task){
echo $task->city->name;
}
first you should fix your relation:
public function city()
{
return $this->hasOne(City::class,'city_id','id');
}
and so one the same error, foreign key in argument order comes before the primary key.
after that you can use addSelect:
$tasks = Task::whereCityId($city->id)->whereTypeId($type->id)
->addSelect(['userName' => User::select('name')
->whereColumn('users.id', 'tasks.operator_id')
->limit(1)])->get()->toArray();
i think this will help better than what you ask.
$tasks = Task::whereCityId($city->id)
->whereTypeId($type->id)
->with('operator')
->get()->toArray();
with('operator') is ORM feature that make you collection to include its relation as collection property. In this case it will convert to array property.
you could access it from your foreach function as
#foreach($task as $key)
$key['operator']['username']
#endforeach
Have a nice day

how to get desired column from other table

there are two tables products and categories, that I created by PHPMyAdmin.
In the products table, it has a column name prd_category that has the foreign key of table categories named cat_id(primary key of categories table).
i am quite new in laravel
i want return all data from product table with category name(cat_name) from another table
//here is my controller
use App\Models\product;
class items extends Controller
{
public function sample(){
return product::all();
}
}
//route
Route::get('/',[items::class,'sample']);
//model for products table
class product extends Model
{
use HasFactory;
function category(){
return $this->hasOne('App\Models\category','cat_id','prd_id');
}
}
//model for category
class category extends Model
{
protected $table='categories';
use HasFactory;
}
pls help and thanks in advance..
you can use this code:
$products = product::whereHas('category',function($q)use($cat_name){
$q->where('name',$cat_name)
})->get();
or :
$categories = Category::where('name',$cat_name)->get()->pluck('id')->toArray()
$products = product::whereIn('category_id',$categories)->get();
Are you sure that one-to-many relation is correct? If a product can belong to many categories, you need to use many-to-many relations. Furthermore, if something else belongs to categories you should use many-to-many polymorphic relations. But let's go with one-to-many.
First, the relation function in Product.php looks incorrect. I think products should belong to a category.
function category(){
return $this->belongsTo('App\Models\Category','cust_name','name');
}
Then you need to define reverse relation in Category.php
function products(){
return $this->hasMany('App\Models\Product','cust_name','name');
}
When you define the relations properly, all you need yo do is to fetch data in controller:
use App\Models\Category
...
Category::with('products')->get();
you can use relationship with forign key like pro_id
function category(){
return $this->belongsTo('App\Models\Category','pro_id');
}
function products(){
return $this->hasMany('App\Models\Product','id');
}
$cat = Category::with('products')->all();
in Blade :
{{ $cat->products->cat_name; }}

Laravel - Eloquent 3 Table Query

I know there are several questions out there on 3 table joins, but the examples are simpler than my set up.
I have three tables: Items, Attributes, Categories.
`item.item_code = attributes.item_code`
`attributes.category_id = category.id`
Using eloquent, I can access attributes no problem with:
$items = Item::with('attributes')->paginate(15);
But I can't seem to get the relationship set correctly to retrieve the category name.
With a standard MySql query I'd use something like:
SELECT category_name FROM items
JOIN attributes on items.item_code = attributes.item_code
JOIN categories on attributes.pg3_id = categories.id
WHERE items.item_code = 40992264
How do I achieve this using eloquent?
Edit - My bad - Totally messed up the SQL. Updated to reflect the correct table names and include the second join
Update
My models currently look like this:
class Attributes extends Model
{
public function category(){
return $this->belongsTo(Category::class);
}
}
class Product extends Model
{
public function item()
{
return $this->belongsTo(Item::class);
}
}
class Category extends Model
{
public function attributes()
{
return $this->belongsTo(Attributes::class);
}
}
But this still isn't returning a result. I've tried using
$items = Item::with('attributes.category')->get();
as suggested, but this still throws an error. If I update the Product model to:
class Product extends Model
{
public function item()
{
return $this->belongsTo(Item::class);
}
public function category(){
return $this->belongsTo(Category::class);
}
}
I don't get an error, but the relationship returns null.
You can do
$items = Item::with('attributes.category')->get();
So you access the category relationship inside the attributes relationship.
For example:
foreach ($items as $item) {
foreach ($item->attributes as $attribute) {
echo $attribute->category->id; // Will print the category id.
}
}

Method items cannot be found - Many to Many Relationship

I have a products and items table with a many to many relationship and a pivot table (item_product).
This is how my model looks like. When i try to retrieve items belonging to a product(category) $selectedItems= $products->items()->get(); i get an error "Method items cannot be found" . I can't seem to find where my error is. Please help
Product
public function items()
{
return $this->belongsToMany('App\Item','item_product','product_id','item_id')
->withTimestamps();
}
Item
public function products()
{
return $this->belongsToMany('App\Product','item_product','item_id','product_id')
->withTimestamps();
}
Controller
$products = Product::all()->where('id',1);
$myItems= $products->items()->get();
return view('products',compact('myItems','products'));
$products not an instance of Product
Try this:
$product = Product::findOrFail(1);
$myItems = $product->items;
return view('products',compact('myItems','product'));
Explanation:
$product = Product::findOrFail(1);
This will fetch a single product model by ID, or throw an exception if that product does not exist.
$myItems = $product->items;
This will set $myItems to a collection of items. This is equivalent to:
$myItems = $product->items()->get();
I recommend you read the documentation on relationships.

Laravel 4 Eloquent/Model Relationships

I am setting up several Models an want to know the correct approach to table structure and Model relationships.
Let's assume we have a shop containing products, each with properties size and color.
Table products
id
size_id
color_id
price
Table sizes
id
name
Table colors
id
name
Models
class Product extends Eloquent {
public function size() {
return $this->hasOne('Size', 'id');
}
public function color() {
return $this->hasOne('Color', 'id');
}
}
class Size extends Eloquent {
public function products() {
return $this->belongsTo('Product', 'size_id');
}
}
class Color extends Eloquent {
public function products() {
return $this->belongsTo('Product', 'color_id');
}
}
This way I can easily echo the color/size of a product using {{ Product->size['name'] }}. Also, I want to pass Eloquent the size's foreign key size.id like Product::where('size_id', '5') rather than its name size.name.
Problem: Doing $products = Product::has('size', '=', '5')->get() does not give me any results, yet doing $products = Product::where('size_id', '5')->get() does.
I am pretty confused, what went wrong?
I think that the problem is that your ::has() method is looking for products with exactly 5 different sizes on each specific product, which would assume that you would be using $this->hasMany('Size') in your Product model. Where as the ::where() method is returning results where the size of the product is 5.
In the documentation they use an example of comments. A post will have a list of comments. You can find posts that have at least one comment (ie. Post::has('comments')->get()) or you can find posts that have more than 3 comments (ie. Post::has('comments', '>=', '3')->get()).
http://laravel.com/docs/eloquent#querying-relations

Categories