I have the following tables:
Customer
id
Order
id
customer_id
Order_notes
order_id
note_id
Notes
id
If I want to get all order notes for a customer so I can do the following, how can I do it? Is there way to define a relationship in my model that goes through multiple pivot tables to join a customer to order notes?
#if($customer->order_notes->count() > 0)
#foreach($customer->order_notes as $note)
// output note
#endforeach
#endif
Create these relationships on your models.
class Customer extends Model
{
public function orders()
{
return $this->hasMany(Order::class);
}
public function order_notes()
{
// have not tried this yet
// but I believe this is what you wanted
return $this->hasManyThrough(Note::class, Order::class, 'customer_id', 'id');
}
}
class Order extends Model
{
public function notes()
{
return $this->belongsToMany(Note::class, 'order_notes', 'order_id', 'note_id');
}
}
class Note extends Model
{
}
You can get the relationships using this query:
$customer = Customer::with('orders.notes')->find(1);
What about 'belongsToMany' ?
E.g. something like
$customer->belongsToMany('OrderNote', 'orders', 'customer_id', 'id');
Of course, it'll not work directly, if you want to get order object also (but maybe you can use withPivot)
In the end I just did the following:
class Customer extends Model
{
public function order_notes()
{
return $this->hasManyThrough('App\Order_note', 'App\Order');
}
}
class Order_note extends Model
{
public function order()
{
return $this->belongsTo('App\Order');
}
public function note()
{
return $this->belongsTo('App\Note')->orderBy('notes.id','desc');
}
}
Then access the notes like so:
#foreach($customer->order_notes as $note)
echo $note->note->text;
#endforeach
Related
I have a problem with a many to many relationship and the translations of the terms.
I have 4 tables:
products
- id, price, whatever
products_lang
- id, product_id, lang, product_name
accessori
- id, active
accessori_lang
- id, accessori_id, lang, accessori_name
I'm trying to assign accessories to products with an intermediate table named:
accessori_products
this is the model for Product:
class Product extends Model {
protected $table = 'products';
public function productsLang () {
return $this->hasMany('App\ProductLng', 'products_id')->where('lang','=',App::getLocale());
}
public function productsLangAll() {
return $this->hasMany('App\ProductLng', 'products_id');
}
public function accessori() {
return $this->belongsToMany('App\Accessori', 'accessori_products');
}
}
this is the model for productLng:
class ProductLng extends Model {
protected $table = 'products_lng';
public function products() {
return $this->belongsTo('App\Product', 'products_id', 'id');
}
}
Then I have the model for Accessori:
class Accessori extends Model {
protected $table = 'accessori';
public function accessoriLang() {
return $this->hasMany('App\AccessoriLng')->where('lang','=',App::getLocale());
}
public function accessoriLangAll() {
return $this->hasMany('App\AccessoriLng');
}
public function accessoriProducts() {
return $this->belongsToMany('App\Products', 'accessori_products', 'accessori_id', 'products_id');
}
}
And the model for AccessoriLng:
class accessoriLng extends Model {
protected $table = 'accessori_lng';
public function accessori() {
return $this->belongsTo('App\Accessori', 'accessori_id', 'id');
}
}
I get the results by this:
$products = Product::has('accessori')->with([
'productsLang ',
'accessori' => function ($accessori){
$accessori->with([
'accessoriLang'
]);
}
])->get();
return $products;
but I want to get only the active accessories something like where accessori.active = 1 but I really don't know where to put it. I've tried in different way but I'm stuck on it by 2 days.
IIRC you don't need a model for the intermediate table on your many to many relationships.
If you want to return Products where Accessori is active you can use whereHas on the Product model.
$prod = Product::whereHas('accessori', function($query) {
$query->where('active', 1);
})->get();
Where the $query param will be running on the Accessori model.
You can do the inverse as well with Accessori to Product.
$acessoris = Accessori::where('active', 1)->whereHas('accessoriProduct')->with(['accessoriLang', 'accessoriProducts.productsLang'])->get();
Consider I'm a hotel owner, and I have to know the bookings related to my hotel.
I need all bookings that which associated with my hotel.
Is there any eloquent functions to join? How?
How to get bookings of a hotel with owner(userid) with using eloquent relationship functions?
Hotel.php
class Hotel extends Model
{
public function userId(){
return $this->belongsTo(User::class,'user_id');
}
public function rooms(){
return $this->hasMany(Room::class,'hotel_id','id');
}
}
Room.php
class Room extends Model
{
public function hotelId(){
return $this->belongsTo(Hotel::class,'hotel_id');
}
public function bookings(){
return $this->hasMany(Booking::class,'room_id','id');
}
}
User.php
class User extends Model
{
public function hotels(){
return $this->hasMany(Hotel::class,'user_id','id');
}
}
Below code add in your respective controller.
$user = \App\User::find(Auth::id());
$hotels = $user->hotels;
foreach ($hotels as $hotel) {
$rooms = $hotel->rooms;
foreach ($rooms as $room) {
print_r($room->bookings);
}
}
Define the relationship with user in model
class Booking extends Model{
/**
* Get the user that owns the booking.
*/
public function owner()
{
return $this->belongsTo(App\User::class,'user_id,'id');
}
}
Then in your controller
$bookings = Booking::with('owner')->all(); // or get() or whatever to get
the booking list
foreach($bookings as $booking){
echo $booking->user->name; // you have access to owner fields
}
Finally i found this.
Booking model
public function room( )
{ return $this->belongsTo('App\room');
}
public function hotel( )
{
return $this->room()->with(['hotel'=> function($query){
$query->with('user');
}]);
}
BookingController
public function owner(Booking $booking ) {
return $booking->with('hotel')->get()
Next thing is Filter with owner
I'm new to Laravel and I'd like to know how to use eloquent model to join a max(date) record...
App\SchemasGroup::find(7)->schemas()->get()->max('schemasVersion')->get();
I find a group of schemas (schemas_groups table) based on ID, then get the schemas from that group (schemas table), and I want to join the 'date' and 'version' field from schemas_versions table with the last version (so, max date or version field) ...
Relations are defined as:
class SchemasGroup extends Model
{
public function schemas() { return $this->hasMany('App\Schema'); }
}
class Schema extends Model
{
public function group() { return $this->belongsTo('App\SchemasGroup'); }
public function versions() { return $this->hasMany('App\SchemasVersion'); }
}
class SchemasVersion extends Model
{
public function schema() { return $this->belongsTo('App\Schema'); }
public function updatedBy() { return $this->belongsTo('App\User','updated_by'); }
}
Getting the user name who updated that last version would also be lovely...
Apparently it was easy with defining chaining models.
class Schema extends Model
{
public function group() { return $this->belongsTo('App\SchemasGroup'); }
public function versions() { return $this->hasMany('App\SchemasVersion'); }
public function latestVersion() { return $this->hasOne('App\SchemasVersion')->latest(); }
}
and then fetching the data with:
App\SchemasGroup::with('schemas.latestVersion.updatedBy')->find($schemaGroupId);
In my project I have orders which have many products and customers who have many orders. I am confused because I want to get all orders that a certain customer has and the products of each order. I messed up something somewhere and I am not sure if I set my relationships correctly. Here is my products table:
Here is my customers table:
And here is my orders table:
Here are my models:
Product:
class Product extends Model
{
public function orders()
{
return $this->belongsToMany('App\Order');
}
}
Order:
class Order extends Model
{
public function products()
{
return $this->hasMany('App\Product', 'id');
}
public function customer()
{
return $this->belongsTo('App\Customer');
}
}
Customer:
class Customer extends Model
{
public function orders()
{
return $this->hasMany('App\Order', 'id');
}
}
I get all customers from my database with App\Customer::all() in my CustomersController and pass the data in my customers.blade.php.
<h1>Customers:</h1>
#foreach($customers as $customer)
<h3>{{$customer->name}}</h3>
#foreach($customer->orders as $order)
<p>Order ID: {{$order->id}}</p>
#foreach($order->products as $product)
<p>Product title: {{$product->title}}</p>
#endforeach
#endforeach
<hr>
#endforeach
Here is the output:
If someone could explain why it doesn't output everything and give some advice if this is the way to go with the relationships, I would be very thankful.
Your products should belong to an order, rather than have a many-to-many relationship.
class Product extends Model
{
public function orders()
{
return $this->belongsTo('App\Order');
}
}
I found a solution by making a pivot table for products and orders called products_orders which holds the product_id and the order_id and making a many to many relationship between Product and Order. That is because an order may have multiple products and products may exist in multiple orders.
My pivot table products_orders:
class Product extends Model
{
public function orders()
{
return $this->belongsToMany('App\Order');
}
}
class Order extends Model
{
public function products()
{
return $this->belongsToMany('App\Product', 'products_orders');
}
public function customer()
{
return $this->belongsTo('App\Customer');
}
}
I made a one to many relationship (customer_id in orders table) for Customer and Order and now everything works fine.
class Customer extends Model
{
public function orders()
{
return $this->hasMany('App\Order');
}
}
I have a database with the following tables and relationships:
Advert 1-1 Car m-1 Model m-1 Brand
If I want to retrieve an Advert, I can simply use:
Advert::find(1);
If I want the details of the car, I could use:
Advert::find(1)->with('Car');
However, if I also want the detail of the Model (following the relationship with Car), what would the syntax be, the following doesn't work:
Advert::find(1)->with('Car')->with('Model');
Many thanks
It's in the official documentation under "Eager Loading"
Multiple relationships:
$books = Book::with('author', 'publisher')->get();
Nested relationships:
$books = Book::with('author.contacts')->get();
So for you:
Advert::with('Car.Model')->find(1);
First you need to create your relations,
<?php
class Advert extends Eloquent {
public function car()
{
return $this->belongsTo('Car');
}
}
class Car extends Eloquent {
public function model()
{
return $this->belongsTo('Model');
}
}
class Model extends Eloquent {
public function brand()
{
return $this->belongsTo('Brand');
}
public function cars()
{
return $this->hasMany('Car');
}
}
class Brand extends Eloquent {
public function models()
{
return $this->hasMany('Model');
}
}
Then you just have to access this way:
echo Advert::find(1)->car->model->brand->name;
But your table fields shoud be, because Laravel guess them that way:
id (for all tables)
car_id
model_id
brand_id
Or you'll have to specify them in the relationship.
Suppose you have 3 models region,city,hotels and to get all hotels with city and region then
Define relationship in them as follows:-
Hotel.php
class Hotel extends Model {
public function cities(){
return $this->hasMany(City::class);
}
public function city(){
return $this->belongsTo('App\City','city_id');
}
}
City.php
class City extends Model {
public function hotels(){
return $this->hasMany(Hotel::class);
}
public function regions(){
return $this->belongsTo('App\Region','region_id');
}
}
Region.php
class Region extends Model
{
public function cities(){
return $this->hasMany('App\City');
}
public function country(){
return $this->belongsTo('App\Country','country_id');
}
}
HotelController.php
public function getAllHotels(){
// get all hotes with city and region
$hotels = Hotel::with('city.regions')->get()->toArray();
}
will adding the relation function just ask for the relation needed
public function Car()
{
return $this->belongsTo(Car::class, 'car_id')->with('Model');
}
but if you want a nested relation just use the period in the with
Advert::with('Car.Model')->find(1);
but for multi-relation use the array
Advert::with('Car','Model')->find(1);