Laravel — Loop all data from multiple tables - laravel-5

Good day. I have researched about it, but nothings matched with my problem. Here's the scenario. I have courses table, and 3 more tables, assignments, quizzes, and reports. Now, what I want is, to get all of the records from the table assignments, quizzes, and reports and loop through all the records below a specific course.
Example Output: The order should be according to the first created item.
Course1
Assignment1
Quiz1
Quiz2
Assignment2
Report1
How can I do that with three different tables? I know how to use the basic many to many relationship, but for this. I really got stacked. Need help guys.
Note: I'm using Laravel5.1
Update1 — Course.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
{
protected $fillable = [];
public function assignments(){
return $this->belongsToMany('Assignment');
}
public function quizzes(){
return $this->belongsToMany('Quiz');
}
public function reports(){
return $this->belongsToMany('Report');
}
}
UPDATE2 as per request
<div class="table">
<table class="tabled">
<thead>
<tr>
<th>x</th>
</tr>
</thead>
<tbody>
#foreach($course_items as $course_item)
<tr>
<td>
{{ $table_name }} {{ $course_item->name }}
</td>
</tr>
#endforeach
</tbody>
</table>
</div>

Based on the limited information available from your question, you will need to merge your relations into a single collection.
Using unions would be a better solution, if feasible, to improve efficiency, but hey-ho.
// Prepare not deleted scope
// I would suggest using Laravel's SoftDeletes, as it'll be better than writing your own implementation. But if not, you would be better to create this as a reusable scope on your model
$notDeletedScope = function ($query) {
return $query->where('deleted', 0);
};
// Find course with non-deleted relations
$course = Course::with([
'assignments' => $notDeletedScope,
'reports' => $notDeletedScope,
'quizzes' => $notDeletedScope,
])
->findOrFail($id);
// Combine relations into single collection
$merged = collect($course->assignments);
$merged = $merged->merge(collect($course->quizzes));
$merged = $merged->merge(collect($course->reports));
// Sort merged relations by created_at
$merged = $merged->sortBy('created_at');
#foreach ($merged as $relation)
#if ($relation->type === 'assignment')
// ...
#elseif ($relation->type === 'quiz')
// ...
#elseif ($relation->type === 'report')
// ...
#endif
#endforeach
Add to each model:
public function getTypeAttribute()
{
return snake_case(substr(strrchr(get_class($this), '\\'), 1));
}

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);
}

How I car write Controller function on many to many with relation attributes

I am working on applying many to many relations on table Accident, Car where the relations are as follows:
In the Accident model:
public function car()
{
return $this->belongsToMany(Car::class,'accident_participateds',
'reportNo','vehicleId');
}
In-car Model
public function accidents()
{
return $this->belongsToMany(Accident::class,'accident_participateds',
'vehicleId','reportNo')->withPivot(['damageAmount', 'IBAN']);
}
I want to display the data from all 3 Models (Car, Accident,accident_participateds)My question is whether these statements are correct in the controller
public function AdminClaims()
{
$claim = Accident::with('car')->get();
$details = Car::with('accidentsr')->get();
return view('admin.AdminClaims',compact('claim','details'));
}
Because when I try to display like this:
<tbody>
#foreach($claim as $claims)
<tr>
<td>{{$claims->ReportNumber}}</td>
#foreach($details as $AP)
<td>{{$AP->vehicleId}}</td>
<td>{{$AP->Location}}</td>
<td>{{$AP->Date}}</td>
<td>{{$AP->damageAmount}}</td>
<td>{{$AP->IBAN}}</td>
#endforeach
</tr>
#endforeach
it print only ReportNumber
kindly tell me where I made a mistake?
From what I understand, you want to display the details of Accident(claim), associated Car and data from the pivot table.
To do so you can try
public function AdminClaims()
{
$claims = Car::with('accidents')->get();
return view('admin.AdminClaims',compact('claims'));
}
And in view
#foreach($claims as $claim)
<tr>
<td>{{$claim->ReportNumber}}</td>
<td>{{$claim->vehicleId}}</td>
<td>{{$claim->Location}}</td>
<td>{{$claim->Date}}</td>
<td>{{$claim->pivot->damageAmount}}</td>
<td>{{$claim->pivot->IBAN}}</td>
</tr>
#endforeach

get access to collection laravel

I am a new learner of the laravel framework working on 3 models
customer,
accidents,
License
where the relations are as follows:
public function License()
{
return $this->hasOne(license::class,'driver_id');
}
public function cars()
{
return $this->hasMany(car::class);
}
In the controller I do like this:
public function AdminCustomers()
{
$customers = Customer::with('cars')->with('License')->get();
return view('admin.AdminCustomers',compact('customers'));
}
now I want to display all 3 models' data on view.blade page
<tbody>
#foreach($customers as $customer)
<tr>
<td>{{$customer->id}}</td>
<td>{{$customer->name}}</td>
<td>{{$customer->adderss}}</td>
<td>{{$customer->mobileNo}}</td>
<th>{{$customer->License->id}}</th>
<th>{{$customer->License->Exp}}</th>
<td>{{$customer->cars->id}}</td>
<td>{{$customer->cars->color}}</td>
<td>{{$customer->cars->model_no}}</td>
<td>{{$customer->cars->company}}</td>
</tr>
#endforeach
</tbody>
But it doesn't work and I didn't know where is the problem
the error Exception
Property [id] does not exist on this collection instance.
$customer->cars will return a collection as the relationship is hasMany so you need to loop over the collection in the view
#foreach($customers as $customer)
<tr>
<td>{{$customer->id}}</td>
<td>{{$customer->name}}</td>
<td>{{$customer->adderss}}</td>
<td>{{$customer->mobileNo}}</td>
<th>{{$customer->License->id}}</th>
<th>{{$customer->License->Exp}}</th>
#foreach($customer->cars as $car)
<td>{{$car->id}}</td>
<td>{{$car->color}}</td>
<td>{{$car->model_no}}</td>
<td>{{$car->company}}</td>
#endforeach
</tr>
#endforeach
check the name in the corrisponding table on db, and if its different from "id" specify it into the model, as
protected $primaryKey = 'xxx';

Laravel Eloquent get data where comparison is true

I am creating a mini inventory stock for a fashion store. I am using Laravel/Voyager with BREAD and everything fine. I have 2 tables Sizes and Products with a column in common product_code.
I would like to get the results from Sizes where column product_code = Product 'product_code'.
I have this query in the controller:
$product_code = Product::all();
$allSizes = Size::where('product_code', ($product_code->product_code));
and in browse.blade.php I have:
#foreach ($allSizes as $size)
<tr>
<td align="right">{{$size->size_name}}</td>
<td align="right">{{$size->stock}}</td>
</tr>
#endforeach
I guess the where statement is not working as supposed to.
I want to get the corresponding stock based on product_code for each size from table Sizes
Try This
$product_code = Product::pluck('product_code')->toArray();
$allSizes = Size::whereIn('product_code', $product_code)->get();
and in browse.blade.php:
#foreach ($allSizes as $size)
<tr>
<td align="right">{{$size->size_name}}</td>
<td align="right">{{$size->stock}}</td>
</tr>
#endforeach
I think you're going about this the wrong way. Your tables are related in some way and you need to define a relationship to access the data Eloquently.
If I were building such a database, I think that the relationship between Product and Size is a many to many. I.e. a Product can have many Sizes, and you can also shop for many Products in a certain Size. Thus, your models should have a belongsToMany() relationship to each other.
// Product.php
protected $with = ['sizes']; // eager load product sizes
public function sizes() {
return $this->belongsToMany(Size::class);
}
// Size.php
public function products() {
return $this->belongsToMany(Product::class);
}
Then you can do
// ProductsController.php
public function show(Product $product) {
return $product;
}
You missed to run the query
$product_code = Product::all();
# ::all() will return collection, and you can't access a property of it directly
$allSizes = Size::where('product_code', ($product_code->first()->product_code))->get();
Notice the ->get();

Pagination in laravel 5 with realtion on where condition

Model smsHeader
protected $fillable = [
'type',
'imei',
'login',
'ver'
];
public function detail()
{
return $this->hasMany('App\Model\smsDetail', 'id_header');
}
Controller
$smsheader = smsHeader::orderBy('id', 'desc')->where('login', $user->email)->paginate(20);
return view('app.inbox')->with('smsheader', $smsheader);
Views
#foreach($smsheader as $header)
#foreach($header->detail->where('type', '1') as $detail)
<tr>
<td>{{$detail->number}}</td>
<td>{{$detail->name}}</td>
<td>{{$detail->text}}</td>
<td>{{$detail->date}}</td>
</tr>
#endforeach
#endforeach
but the result of pagination it was error, how i can set paginition in where smsdetail condition....??
sorry for my bad english
The error is showing for this line $header->detail->where('type', '1')
you can access $header->detail within foreach if you want to use where condition then you need to use get() at the end,like below
#foreach($smsheader as $header)
#foreach($header->detail->where('type', '1')->get() as $detail)
<tr>
<td>{{$detail->number}}</td>
<td>{{$detail->name}}</td>
<td>{{$detail->text}}</td>
<td>{{$detail->date}}</td>
</tr>
#endforeach
#endforeach
Laravel Queries within Blade views do not automatically execute. They simply prepare another QueryBuilder instance. You still need to run one of the "execute" methods (that will run PDOStatement::execute() underneath). These methods are:
first() (returns first result from result set as single object)
get() (which returns a Collection (ArrayObject with some added extra functionality))
paginate($numberPerPage) (which returns a Collection with extra meta information to pass to a $links property accessible via $collection->links())
In your example:
#foreach($smsheader as $header)
#foreach($header->detail->where('type', '1')->get() as $detail)
<tr>
<td>{{$detail->number}}</td>
<td>{{$detail->name}}</td>
<td>{{$detail->text}}</td>
<td>{{$detail->date}}</td>
</tr>
#endforeach
#endforeach

Resources