I am writing a nested query with Laravel.
Namely First, the Truck information is drawn, then I list the data of the vehicle with "truck_history", there is no problem until here, but I want to show the information of the invoice belonging to the "invoice_id" in truck_history. but I couldn't understand how to query, I want to do it in the model, is this possible? If possible, how will it be done?
"ID" COLUMN IN INVOICE TABLE AND "invoice_id" in "InvoiceDetail" match.
TruckController
public function getTruck($id)
{
$truck = Truck::with(['truckHistory'])->find($id);
return $truck;
}
Truck Model
protected $appends = ['company_name'];
public function companys()
{
return $this->belongsTo(Contact::class, 'company_id', 'id');
}
public function getCompanyNameAttribute()
{
return $this->companys()->first()->name;
}
public function truckHistory(){
return $this->hasMany(InvoiceDetail::class,'plate_no','plate');
}
So you can add another relationship in the InvoiceDetail::class and add in the truck history.
try something like this:
public function truckHistory(){
return $this->hasMany(InvoiceDetail::class,'plate_no','plate')->with('Invoice');
}
Simply add the following relations (if you don't already have them):
Invoice model :
public function truckHistory()
{
return $this->hasOne(InvoiceDetail::class);
}
InvoiceDetail model :
public function invoice()
{
return $this->belongsTo(Invoice::class);
}
And you can get the relation invoice of the relation truckHistory adding a point as separator :
public function getTruck($id)
{
$truck = Truck::with(['truckHistory.invoice'])->find($id);
return $truck;
}
Related
I would like to retrieve all products of chosen parent category.Product model have hasmany relation to product_category_mapping table.
If product have subcategory result like,
"MAinCatergory":[
{
id="",
name:"Drinks",
"ChildCategory":[
{
"id":1,
"name":"Juce",
"Products":[{
name:"apple juce",
price:10,
....
}]
}
]
}
]
}
If product under main category only return array like,
"MAinCatergory":[
{
id="",
name:"Drinks",
"Products":[{
name:"apple juce",
price:10,
....
}]
}
}
]
}
category table fields - id,name,parent_id
product table fields - id,name,price,..,
product-category-mapping table fields - id,category_id,product_id
category model
public function children()
{
return $this->hasMany('App\Models\Category', 'parent_id');
}
public function parent()
{
return $this->belongsTo('App\Models\Category', 'parent_id');
}
public function product_category()
{
return $this->hasMany('App\Models\ProductCategoryMapping', 'category_id');
}
product model
public function product_category()
{
return $this->hasMany('App\Models\ProductCategoryMapping','product_id');
}
product-category_mapping
public function product()
{
return $this->belongsTo(Product::class,'product_id','id');
}
public function category()
{
return $this->belongsTo(Category::class,'category_id','id');
}
Something like this might suffice.
App\Models\Category::with('children', 'product_category.product')->get()
Suggestion, try implement pivot many to many relation instead this product_category_mapping, then model relation would change a bit.
For pivot relation, you need to modify the Category model
public function products()
{
return $this->belongsToMany('App\Models\Product', 'product-category-mapping');
}
and in product Model
public function categories()
{
return $this->belongsToMany('App\Models\Category','product-category-mapping');
}
Note:This is not the complete integration, but to give you an idea, for full logic see https://laravel.com/docs/9.x/eloquent-relationships#many-to-many
in your product model add like this:
public function product_categorys(){
return $this->hasMany('App\Models\ProductCategoryMapping','product_id');
}
and in controller you can get inside your function like this Product::with('product_categorys')->get();
The tables category, category_description and descriptions are related:
public function descriptions(): BelongsToMany
{
return $this->belongsToMany(Description::class);
}
public function categories(): BelongsTo {
return $this->belongsTo(Category::class);
}
public function descriptions(): BelongsTo {
return $this->belongsTo(Description::class);
}
public function descriptions(): BelongsToMany
{
return $this->belongsToMany(Category::class);
}
in Model respectively. When saving or updating:
public function createOrUpdate(Category $category, Request $request)
{
$category->fill($request->get('category'))->save();
$category->descriptions()->syncWithoutDetaching(
$request->input('category.descriptions', [])
);
}
An error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'description' in 'field list' (SQL: insert into `category_description` (`category_id`, `description`, `description_id`, `is_active`, `meta-description`, `meta-h1`, `meta-keyword`, `meta-title`, `name`, `slug`) values (1, 41231231, 0, 1, 23, 124, 12, 12, 12333312, 74))
Perhaps I missed something somewhere, since there is not so much experience.
UPDATE:
a category can have multiple entries, but the description has only one parent. Rewrote — One To Many (Polymorphic):
public function descriptions()
{
return $this->morphMany(Description::class, 'descriptable');
}
public function descriptable()
{
return $this->morphTo();
}
There are no problems with saving 1 record, but how to update several records at the same time?
How about?
// Category Model.
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function descriptions()
{
return $this->belongsToMany(Description::class)
->using(CategoryDescription::class);
}
}
// Description Model.
use Illuminate\Database\Eloquent\Model;
class Description extends Model
{
protected $fillable = [
"name",
"description",
"meta-title",
"meta-description",
"meta-keyword",
"meta-h1",
"slug",
"is_active",
];
public function categories()
{
return $this->belongsToMany(Category::class)
->using(CategoryDescription::class);
}
}
// Intermediate Model.
use Illuminate\Database\Eloquent\Relations\Pivot;
class CategoryDescription extends Pivot
{
protected $table = "category_description";
public $incrementing = true;
public function category()
{
return $this->belongsTo(Category::class, "category_id", "id");
}
public function description()
{
return $this->belongsTo(Description::class, "description_id", "id");
}
}
// createOrUpdate method.
public function createOrUpdate(Category $category, Request $request)
{
$category->fill($request->get('category'))->save();
$description = Description::create(
Arr::collapse($request->input('category.descriptions', []))
);
$category->descriptions()->syncWithoutDetaching(
$description->id
);
}
Notes:
Much as this may work for you, I personally think that you don't have a many-to-many relationship here. I believe a one-to-many relationship is sufficient.
The problem is you send data to be inserted in columns that are not found
You should send only the data that you need to insert in the table
so in your case, you should write your function as
$category->descriptions()->syncWithoutDetaching($description_id); // the id of the description you want to attach with this category
If you still don't have the description yet in the database and you are creating it with the same request you can do something like this
Description::create(['columnName'=>$request->get('columnName'),'columnName2'=>$request->get('columnName2')])->id
How could I set relationships to use just one table (model_types) in Laravel to store types for cars and bikes?
Car model
public function carTypes()
{
return $this->hasMany(CarType::class);
}
CarType model (inverse relationship):
public function car()
{
return $this->belongsTo(Car::class);
}
Bike model
public function bikeTypes()
{
return $this->hasMany(BikeType::class);
}
BikeType model (inverse relationship):
public function bike()
{
return $this->belongsTo(Bike::class);
}
There are 2 options I can think of to solve this problem, the first being a simple table using a type column and the other is using polymorphic relations which is a little overkill.
The first option is to have a type column on your model_types table which you could use to determine the type and adding constants in your ModelType class like this:
const TYPE_CAR = 1;
const TYPE_BIKE = 2;
Then you can easily access the data like so, so from the Car model it's
public function modelType()
{
return $this->belongsTo(ModelType::class)->where('type', ModelType::TYPE_CAR);
}
If you wanted to access it from the model_types table it would look like this:
public function cars()
{
return $this->hasMany(Car::class)
}
public function bikes()
{
return $this->hasMany(Bike::class)
}
You have it reversed.
A car can belong to one car type, but one car type can apply to many cars.
The same goes for bikes.
You don't need a polymorphic relationship.
Car model
public function carType()
{
return $this->belongsTo(ModelType::class);
}
Bike model
public function bikeType()
{
return $this->belongsTo(ModelType::class);
}
ModelType model
public function cars()
{
return $this->hasMany(Car::class);
}
public function bikes()
{
return $this->hasMany(Bike::class);
}
Not sure about inverse relationship, but in your Car model you should use
public function carTypes()
{
return $this->hasMany(ModelType::class, 'foreign_key', 'local_key');
}
Car Model:
public function carTypes() {
return $this->hasMany(ModelType::class);
}
Bike Model:
public function bikeTypes() {
return $this->hasMany(ModelType::class);
}
ModelType Model:
public function car() {
return $this->belongsTo(Car::class, 'modeltype_car_id');
}
public function bike() {
return $this->belongsTo(Bike::class, 'modeltype_bike_id');
}
I have two data tables related to each other by the belongstomany relationship. And when I am fetching data from its api controllers with selecting only two column keys ['id','title'] yet it returns some extra data in the response object.
modelcode:
public function place(){
return $this->belongsToMany(Place::class,'city_place')->select(array('id', 'title'));
}
controller code:
public function ofcity($id)
{
$city=City::findOrFail($id);
return new CityResource( $city->place()->get());
}
enter image description here
You must indicate the name of the table in front of the fields.
model Place code:
protected $columns = ['places.id', 'places.title']; //all column for select
public function scopeExclude($query, $value = [])
{
return $query->select(\array_diff($this->columns, (array) $value));
}
model City code:
public function place()
{
return $this->belongsToMany(Place::class,'city_place', 'city_id', 'place_id');
}
controller code:
public function ofcity($id)
{
$cities = City::findOrFail($id)->place()->exclude(['featured_image'])->get()->toArray();
return response()->json(['cities' => $cities], 200);
}
In exclude skip all the fields that need not to be shown.
Thanks everyone here helping me out but none of the above solution worked..I figured it out after trying different functions and spending hours on this.
model Place code:
public function place(){
return $this->belongsToMany(Place::class,'city_place','city_id','place_id')->select(array('places.id', 'places.title'));
}
controller code:
public function ofcity($id)
{
$city=City::findOrFail($id);
return new CityResource( $city->place()->get()->map(function ($item,$key) {
return ['id' => $item['id'],'title'=>$item['title']];
})
);
I'm building a small application on laravel 5.4 where I'm having following models and relationship:
Interaction Model:
public function contactsAssociation()
{
return $this->belongsToMany('App\Contact', 'contact_interaction', 'interaction_id', 'contact_id')->withPivot('company_id')->withTimestamps();
}
Contact Model:
public function company()
{
return $this
->belongsToMany('App\Company', 'company_contact','contact_id', 'company_id')->withTimestamps();
}
and Company Model:
public function contacts()
{
return $this->belongsToMany('App\Contact', 'company_contact', 'company_id','contact_id');
}
Now I'm fetching some data something like this:
$tempData['contacts'] = $interaction->contactsAssociation()->with('company')->get();
I want to extract company data from the pivot table which is mentioned in the relationship. Currently I can't find solution so I have to do:
$tempData['contacts'] = $interaction->contactsAssociation()->get();
$companies = [];
foreach($tempData['contacts'] as $contact)
{
$companies[] = Company::find($contact->pivot->company_id);
}
$tempData['company'] = $companies;
Guide me on this, thanks,
You can pass an array to the withPivot() function with every field you want to retrieve:
public function contactsAssociation()
{
return $this->belongsToMany('App\Contact', 'contact_interaction', 'interaction_id', 'contact_id')
->withPivot(['company_id', 'other_field'])
->withTimestamps();
}
Hope this helps you.