Laravel join query confusion - laravel-5

Very new to laravel and trying to do something simple but keep getting stuck. I have 3 tables
countries:
id
country
regions:
id
region
country_id
wineries:
id
winery
country_id
region_id
joined together as follows:
public function index()
{
$wineries = Country::join('wineries', 'countries.id', '=', 'wineries.country_id')
->join('regions', 'regions.id', '=', 'wineries.region_id')
->select('countries.*')
->orderBy('countries.country', 'asc')
->get()
->unique();
return view('winery.index', compact('wineries'));
}
I'm trying to return a table organized by country with each winery listed along with it's region. Countries without wineries are not to be displayed. My Index page, looks like this:
<tbody>
#foreach ($wineries as $country)
<tr>
<td colspan="2">{{ $country->country }}</td>
</tr>
#foreach ($country->wineries as $winery)
<tr>
<td>{{ $winery->winery }}</td>
<td>{{ $winery->region }}</td>
</tr>
#endforeach
#endforeach
</tbody>
All works well except I can't get the associated region for each winery since the region is not a part of the $winery array. Any advice on how to make it a part of array or how to accomplish this using a different query?

In laravel you can define relationships for Models. Models represent a Model of data (normally related to a DB table, but not always)
Laravel uses Eloquent for database defining relational tables within PHP.
http://laravel.com/docs/4.2/eloquent#relationships
For your case it sounds like you have three Models
Countries
Region
Wineries
Your counties will have many regions, but a region will only have one country.
Your regions will have many wineries, but a winery will only have one region.
To spec your relationships within Eloquent you want to write the following functions within each
(Country)
public function regions()
{
return $this->hasMany('Region');
}
(Region)
public function country()
{
return $this->hasOne('Country');
}
public function winery()
{
return $this->hasMany('Region');
}
etc..
From there you can then relate the data via the models. So if you have a Country object and wanted to get the regions you would do
$country->regions
You might want to wrap this in a loop to print all of the regions
foreach($country->regions as $region) {
echo $region->name;
}
Hope this helps

Define relationships using model. Laravel has Eloquent model in built. It's very easy to query database using that. Learning curve is well worth it.

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

Trying to get property 'department' of non-object in laravel with one to many relationship

Actually I want to relationship with two tables one is the student table where some data of a student. another table has department notice. I want to access the department notice according to the student department. The student has login id, password, dept & much other information of an individual student on the student table. The screenshot is given below
Now I want to try to access according to the dept. Another Table dept. the screenshot is given below.
Here given the CseDepartment model
public function administration()
{
return $this->belongsTo('App\Administration','dept');
}
Administration model
public function department()
{
return $this->hasMany('App\CseDepartment','dept');
}
function is given below
public function individualdepartment(){
$this->AdminAuthCheck();
$id=Session::get('id');
$student=Administration::find($id);
return view('Student.department',compact('student'));
}
view page department
#foreach ($student as $students)
{{-- expr --}}
<tr>
<td>{{$students->department->name}}</td>
<td>{{$students->department->message}}</td>
<td></td>
<td></td>
<td></td>
</tr>
#endforeach
In your controller, you are calling the find() method, which gives you one object, a student.
$student=Administration::find($id);
In your blade page, you are then asking to loop on that single object and produce a collection:
#foreach ($student as $students) // There is only ONE student, this will not loop.
If you want the above to work, you can grab a collection from your controller:
// Note the plural naming convention to make it a little more clear
$students=Administration::all();
return view('Student.department',compact('students'));
Then in your blade file, you can loop like this:
#foreach ($students as $student) // note the name plural --> singluar
<tr>
<td>{{$student->department->name}}</td> // Now you have a single student
<td>{{$student->department->message}}</td>
This will resolve the non-object error.

Laravel - Populating view with info from single row (with pivot data)

I currently have a form/view that allows a User to save an Order. This also updates a pivot table with the respective Products and qtys. What I am trying to do, is after this information is inputted and saved into the database, I want to send the user to a checkout page that shows all the information they inputted for that Order.
Relationships
User hasMany Order
Order belongsToMany Product
Product belongsToMany Order
checkout.blade.php
#foreach ($orders as $order)
#foreach ($order->products as $product)
<tr>
<td>{{ $product->name }}</td>
<td>{{ $product->pivot->qty }}</td>
</tr>
#endforeach
#endforeach
OrderController.php
public function checkout($id)
{
$user = Auth::user();
$user->load("orders.products"); //eager load pivot table
$orders = $user->orders->where('order_id', $id);
return view('orders.checkout', compact('orders', 'user'));
}
I know I am calling the order incorrectly, because if I change
$orders = $user->orders->where('order_id', $id);
to
$orders = $user->orders;
It displays correctly, except of course, it populates with every Order's detail.
Or is there some elegant way for me to pass the data from the checkout function without this additional query? (I understand about moving data in Sessions, but I am working with a pivot table, and that complicates things.
If on the checkout page, you want to use just the latest order that the user has made, then you can just load that order using route model binding
Route::get('checkout/{order}', 'OrdersController#checkout');
Then in your controller:
public function checkout(Order $order)
so from here, you can pass this order to the view, and list all the products from this order, and also in your Order model you should have a reference to the user that this order belongs to:
public function user()
{
return $this->belongsTo(User::class);
}
Accessing columns from the pivot table will be:
#foreach($order->products as $product)
<div> {{ $product->pivot->column }} </div>
#endforeach

How to easily define relationships of a pivot table where the third column is a foreign key to another table in laravel

I am new to laravel 5. I have been working on a client app where I have setup a relationship like so:
Many to Many relationship between Application and Cart giving me an application_cart table with columns
application_id
cart_id
Sample Model
class Application extends Eloquent
{
public function carts()
{
return $this->belongsToMany('App\Cart');
}
}
class Cart extends Eloquent
{
public function applications()
{
return $this->belongsToMany('App\Application');
}
}
Using the model above, I have been able to display records beautifully in views like below:
#foreach($cart->applications as $application)
<td>{{ $application->student->last_name }}</td>
<td>{{ $application->student->first_name }}</td>
#endforeach
Recently, the client has changed specification so that I have the addition of a third column supervisor_id on the pivot
resulting to a pivot table structure like so:
application_cart table
application_id
cart_id
supervisor_id (Foreign key to the supervisors table. A Supervisor Model exist already)
The goal is so that I can now be able to display an output like below:
#foreach($cart->applications as $application)
<td>{{ $application->student->last_name }}</td>
<td>{{ $application->student->first_name }}</td>
<td>
{{ $application->supervisor->user->name }} <!-- Display the "supervisor name" assign to the application (How can I beautifully display the supervisor name)-->
</td>
#endforeach
How can I easily integrate this new spec in my code?
Edit
Sketchy diagram of how the relationship might look like:
Application.php needs a supervisor() relationship
public function supervisor() {
return $this->hasOne(App\Supervisor::class);
}
Your Supervisor.php model needs a user() relationship
public function user() {
return $this->belongsTo(App\User::class);
}
For this to work, your supervisor table must have a user_id column, and your supervisor table must have a application_id column.
You don't put a third foreign key in a pivot table. Keep application_cart as it is, referencing an application and a cart. While the supervisor foreign key can be defined per application, as I'm assuming you want one supervisor per application.

Resources