Laravel Pivot Relationship not unique table/alias - laravel

I have three Tables & corresponding models:
Table ------ Model
papers ------ Paper
paper_stocks ------ PaperStock
paper_stock_amounts ------ PaperStockAmount
Paper contains diff. types of paper.
PaperStock contains different places where these papers can be stored
PaperStockAmount contains the paper id, the stock id and the amount, to determine how many of paper A are in stock B.
Now I want to check outgoing from the paper how manyy are in each stock. Therefore Im doing this in my view:
#foreach($papers as $paper)
#foreach($paper->paperStockAmount as $ps)
<tr>
<td>{{ $ps->stock->name }}</td>
<td>{{ $ps->amount }}</td>
</tr>
#endforeach
#endforeach
This should show every type of paper and in which stocks along with the amount they are in.
However this is the error:
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'paper_stock_amounts' (SQL: select `paper_stock_amounts`.*, `paper_stock_amounts`.`id` as `pivot_id`, `paper_stock_amounts`.`amount` as `pivot_amount` from `paper_stock_amounts` inner join `paper_stock_amounts` on `paper_stock_amounts`.`id` = `paper_stock_amounts`.`id` where `paper_stock_amounts`.`id` in (1, 2))
The relationships are defined like this:
Paper
class Paper extends Model
{
public function paperStockAmount()
{
return $this->belongsToMany('App\PaperStockAmount', 'paper_stock_amounts')->withPivot('amount');
}
}
PaperStockAmount
class PaperStockAmount extends Model
{
public function paper()
{
return $this->hasOne('App\Paper', 'id', 'paper_id');
}
public function stock()
{
return $this->hasOne('App\PaperStock', 'id', 'stock_id');
}
}
Why doesn't this work?

You've defined M-M Relationship between paper & paper_stock.
i.e. If you are fetching paperStockAmount from $paper, then you would get paper_stock results with the pivot column amount.
You should do it like this:
#foreach($papers as $paper)
#foreach($paper->paperStockAmount as $paper_stock)
<tr>
<td>{{ $paper_stock->name }}</td>
<td>{{ $paper_stock->pivot->amount }}</td>
</tr>
#endforeach
#endforeach
Use pivot to fetch the pivot column named - amount
Hope this helps!

I am not sure but it looks your relation from Paper to PaperStockAmount is has-many, so your relation should be as:
Paper
class Paper extends Model
{
public function paperStockAmount()
{
return $this->belongsToMany('App\PaperStockAmount');
}
}
Then your view code will work.
OR
If the relation between from Paper and PaperStock is many-to-many then your relation should be as:
Paper
class Paper extends Model
{
public function paperStockAmount()
{
return $this->hasMany('App\PaperStock', 'paper_stock_amounts')->withPivot('amount');
}
}
Then in your view, it can be accessed as: (taking from #saumya answer)
#foreach($papers as $paper)
#foreach($paper->paperStockAmount as $paper_stock)
<tr>
<td>{{ $paper_stock->name }}</td>
<td>{{ $paper_stock->pivot->amount }}</td>
</tr>
#endforeach
#endforeach

Related

How to get the counts of Student for each Teachers in a single collection by Eloquent

A Teacher has many Students. When I am showing the Teachers list I also want to show the counts of Student for each Teachers. How can I do this by using Eloquent?
I can find the Teachers from this,
$teacher= Teacher::where('teacher_status','active')->get();
I can find the Student count from this
$student_count = Student::where('teacher_id','teachers.id')->count();
How can I conbine this two query and return the response in a single array/collection?
In your teacher model, create the relationship students:
class Teacher extends Model
{
public function students()
{
return $this->hasMany(Student::class, 'teacher_id');
}
}
In your controller you can do the following:
public function example(){
$teachers = Teacher::where('teacher_status','active')->withCount('students')->get();
return view('teacherViewExample', compact('teachers'));
}
In your view (teacherViewExample):
<table>
<thead>
<tr>
<th>Teacher Name</th>
<th>Students Count</th>
</tr>
</thead>
<tbody>
#foreach($teachers as $teacher)
<tr>
<td>{{ $teacher->name }}</td>
<td>{{ $teacher->students_count }}</td>
</tr>
#endforeach
</tbody>
</table>
Full documentation on how to use withCount() here: https://laravel.com/docs/9.x/eloquent-relationships#counting-related-models
Sometimes you may want to count the number of related models for a
given relationship without actually loading the models. To accomplish
this, you may use the withCount method. The withCount method will
place a {relation}_count attribute on the resulting models:
If you want to count the number of students related to teacher without actually loading them you may use the withCount method and this add new propery named by a {relation}_count column on your resulting models. For example:
Teacher::where('teacher_status','active')->withCount('students')->get();
Also you need and to your Teacher model hasMany relation method to Students
In case frontend and backend are separated, i.e Laravel for backend, Angular for frontend, below are examples for Laravel:
In api.php,
Route::get('teacher-with-students-count', 'TeacherController#getTeacherWithStudentsCount');
In Teacher.php (model)
class Teacher extends Model
{
public function students()
{
return $this->hasMany(Student::class, 'teacher_id', 'id');
}
}
In TeacherController.php
public function getTeacherWithStudentsCount()
{
$teachers = Teacher::where('teacher_status','active')->withCount('students')->get();
return $this->giveSuccessResponse($teachers);
}

Laravel what relation to use in order to see data from another model and column

I have two models
Item:
protected $fillable = [
'code',
'name',
'uom'
];
public function recipe()
{
return $this->belongsTo('App\Recipe');
}
Recipe:
protected $fillable = [
'recipecode',
'itemcode',
'qty'
];
public function item()
{
return $this->hasMany('App\Item');
}
In migration I have:
public function up()
{
Schema::table('recipes', function (Blueprint $table) {
$table->foreign('itemcode')->references('code')->on('items');
});
}
In RecipesController I have:
public function index()
{
$recipes = Recipe::all()->sortBy('recipecode');
$items = Item::all();
return view ('recipe.index', compact('recipes', 'items'));
}
I want to see in the view recipecode, itemcode and ItemName, ItemQty etc.
#foreach($recipes as $recipe)
<tr>
<td>{{ $recipe->recipecode }}</td> // this works
<td>{{ $recipe->itemcode }}</td> // this works
<td>{{ $recipe->item->name }}</td> // this doesn't work
<td>{{ $recipe->item->uom }}</td> // this doesn't work
<td>{{ $recipe->item->qty }}</td> // this doesn't work
</tr>
#endforeach
What should I do in order to see 'name' and 'uom' columns from Items table? I think there is a problem with relations...
First, $recipe->item->name does not work as you expected because $recipe->item is a collection of App\Item, not an App\Item model instance. That's because you have set the relationship to be "hasMany"
Second, please read more about eager loading. What you're doing now are multiple queries. That's the N+1, for each recipe you are querying the database to get the items. You do not need to do that, as it's not performant at all. Use Recipe::with('item')->sortBy('recipecode')->get().
Now, keep in mind that $recipe->item is not a single item, but a collection of items that belong to that Recipe. You'll probably have to work a bit on your table to display multiple items for one Recipe.
Since you are using hasMany you must follow naming convention in naming function
public function items()
{
return $this->hasMany('App\Item');
}
In RecipesController you can eager load.
$recipes = Recipe::with('items')->sortBy('recipecode')->get();
Read documentation here: https://laravel.com/docs/master/eloquent-relationships
Also to show it in your blade
#foreach($recipes as $recipe)
<tr>
<td>{{ $recipe->recipecode }}</td> // this works
<td>{{ $recipe->itemcode }}</td> // this works
#foreach($recipe->items as $item)
<td>{{ $item->name }}</td>
#endforeach
</tr>
#endforeach
Other answers share why you can't directly use $recipe->item. However, I think there is a bigger mistake in database design.
The database that you have designed have a one to many relation. Like, one recipe has a lot of items. However, the reverse one that one item has only one recipe seems wrong. You can cook many recipes with one items. I.E. you can make chicken fry and chicken curry with chicken.
The database design should be something like this,
recipes: code, name, uom
items: code, name
item_recipe: item_code, recipe_code, qty

Laravel 5.4: One to Many with One to One

I created one to one relationship where user belongs to town, so in User model I have:
public function town()
{
return $this->belongsTo('App\Town');
}
and in users table I have town_id column. So, when user post something it says that user is from that town. That works.
Now, I created Settlement model which in same way belongs to App\Town (many users can come with one town), so again when settlement is created with some user it displays town of user and settlement which also contain town_id as that user table. (I hope I'm not confusing)
Question: When user is logged in, how to display settlements from his town only?
This is my code until now:
AdminSettlementsController:
public function index()
{
$settlements = Settlement::paginate(10);
$towns = Auth::user()->town->id;
$town[$towns] = Auth::user()->town->name;
$reon = Reon::pluck('name', 'id')->all();
return view('admin.settlements.index', compact('settlements', 'town', 'reon'));
}
User model has this:
public function town()
{
return $this->belongsTo('App\Town');
}
and index.blade.php in settlements folder has this table:
#if ($settlements)
#foreach ($settlements as $settlement)
<tr>
<td>{{ $settlement->id }}</td>
<td>{{ $settlement->town->name }}</td>
<td>{{ $settlement->reon->name }}</td>
<td>{{ $settlement->name }}</td>
</tr>
#endforeach
#endif
I presume that in Town model I need to have settlements() method where that method hasMany App\Settlement but I don't know how to go from there.
I hope my english is not too bad. Thanks

Unable to display relations data from eloquent relationship

I'm trying to display in my view data from an eloquent relationship but i seem to be doing a tiny bit wrong. dd shows the relation in the collection but i just can't call the data correctly in my view. Below is what i have done
Employee model
public function task()
{
return $this->hasMany(Task::class);
}
Task model
public function employee()
{
return $this->belongsTo(Employee::class);
}
TaskController
public function index()
{
$alltask = Task::with('employee')->get();
dd($alltask);
/*return view('task.task', compact('alltask', 'empwithtask'));*/
}
task view
#foreach ($alltask as $task)
<tr>
<td>{{ $task->priority }}</td>
<td>{{ $task->firstname }}</td>
/* this is meant to be the employee.firstname */
<td>{{ $task->title }}</td>
<td>{{ $task->begin }}</td>
</tr>
#endforeach
I'm not able to display $task->firstname, firstname is from the employees table. Below is a snapshot of the result of dd
How do I show the employee firstname?
$task->employee->firstname

Join 2 tables to a Pivot table LARAVEL 4.2

How can i show the classes only for student who is enrolled in a class and i have 2 tables and a pivot table?
Table 1: Home_Students : home_id , home_studid ....
Table 2: Hw_Classes :class_id , class_desc , class_date ....
Pivot table:Hw_StudentClasses :Stclass_id, Stclass_classid, Stclass_studid
So i made a model MySeminarClasses to communicate with the table Hw_StudentClasses and a Controller MySeminarClassesController
I made relations in the model of the other tables belongsToMany
public function Users(){
return $this->belongsToMany('User','home_id');
}
public function SeminarClass(){
return $this->belongsToMany('SeminarClass','class_id');
}
Also in the Controller i did this which im not so sure if its right but i did this from the instructions of the laravel 4.2 documentation
$myclasses = DB::table('Hw_StudentClasses')
->join('Hw_Classes','Hw_StudentClasses.Stclass_classid','=','Hw_Classes.Class_id')
->join('Home_Students','Hw_StudentClasses.Stclass_studid','=','Home_Students.home_studid')
->orderBy('class_date',strtotime('-4 month'))
->get();
Finally in the blade
<tbody>
#foreach($myclasses as $i=>$myclass)
<tr>
<td>{{ $i+1 }}</td>
**<td>{{ link_to_route('class.show',$myclass->Class_desc,$myclass->Class_id) }}</td>**
<td class="text-center">{{ date('j-n-Y G:i',strtotime($myclass->class_date)) }}</td>
<td class="text-center">{{ UserEnroll::where('Stclass_classid',$myclass->Class_id)->count() }}</td>
</tr>
#endforeach
</tbody>
After a 16 hours of struggle ......i aswered my own question ! This query with Auth::user helped me. Show the classes only for every user who is logged in
$id = Auth::user()->home_studid;
$date = date('m-d-Y', strtotime('-4 month'));
$seminars = Seminar::where('Package_Display', 1)
->orWhere('Package_Display', 2)
->orderBy('Package_Name', 'asc')
->get();
$myclasses = DB::table('Hw_StudentClasses')
->join('Hw_Classes','Hw_StudentClasses.Stclass_classid','=','Hw_Classes.Class_id')
->join('Home_Students','Hw_StudentClasses.Stclass_studid','=','Home_Students.home_studid')
->where('Home_Students.home_studid','=',$id)
->orderBy('class_date',strtotime('-4 month'))
->get();
HOPE THIS HELPS SOMEONE ! ^_^

Resources