Laravel pass parameters from controller to Model using 'With' clause - php

I am new in Laravel,
I want to pass the the $id from my controller in the model using with clause
My model
class Menucategory extends Model
{
protected $fillable = ['title', 'parent_id', 'restaurant_id'];
// loads only direct children - 1 level
public function children()
{
return $this->hasMany('App\Menucategory', 'parent_id');
}
// recursive, loads all descendants
public function childrenRecursive()
{
return $this->children()->with('childrenRecursive');
}
}
My Controller
public function show($id)
{
$menucatagories = Menucategory::with('childrenRecursive')->where('restaurant_id',$id)->where('parent_id','0')->get();
return $menucatagories;
}
My current output is
[
{
"id": 1,
"title": "TestMenu Parant",
"parent_id": 0,
"restaurant_id": 12,
"children_recursive": [
{
"id": 2,
"title": "TestMenu SubCat1",
"parent_id": 1,
"restaurant_id": 12,
"children_recursive": [
{
"id": 6,
"title": "TestMenu other sub cat",
"parent_id": 2,
*******************
"restaurant_id": 13,
*******************
"children_recursive": []
},
{
"id": 7,
"title": "TestMenu other sub cat",
"parent_id": 2,
"restaurant_id": 12,
"children_recursive": []
}
]
},
{
"id": 3,
"title": "TestMenu SubCat2",
"parent_id": 1,
"restaurant_id": 12,
"children_recursive": []
}
]
}
]
I passed $id=12 , but the problem is I get the values of others restaurant_id in my child array, but if i use this it shows the correct jSON
public function childrenRecursive()
{
$id=12;
return $this->children()->with('childrenRecursive')->where('restaurant_id',$id);
}
my questions is how can i pass the $id from the controller to the model or is there any other approach?

You can pass your parameter in the controller itself using the following way.
public function show($id)
{
$menucatagories =Menucategory::with(array('childrenRecursive'=>function($query) use ($id){
$query->select()->where('restaurant_id',$id);
}))
->where('restaurant_id',$id)->where('parent_id','0')->get();
return $menucatagories;
}

Your childrenRecursive isn't wrong at all.
See here an simliar example: https://stackoverflow.com/a/18600698/2160816
So I think this should work
public function childrenRecursive($id = 12){
return $this->children()->where('restaurant_id',$id)->with('childrenRecursive');
}
Your Controller then could call
public function show($id)
{
$menucatagories = Menucategory::where('parent_id','0')->childrenRecursive(12)->get();
return $menucatagories;
}
I could not test it so may it won't work 100%

Related

Get the collection instead of the ID

I have a many-to-many relationship between three tables (Courses , Professors , Hours) I created a 4th table called course_hour_professors to make the relation and I made it one-to-many relationship between the 4 tables because I know that if I get a pivot table with more than two FKs, I have to treat it as full model. So instead of Many-to-Many relationship. I have to divide it into multiple of One-to-Many relationships. all of this is working now but Professors table is related to User table and I need to access the professor name which is located in the User table since it's related to it but I can only access the User_id from my course_hour_professors as shown below :
{
"id": 3,
"professor_id": 94,
"course_id": 132,
"hour_id": 1,
"nbr_hour_course": 9,
"course": {
"id": 132,
"created_at": "2018-07-25T16:02:19.000000Z",
"updated_at": "2018-09-07T07:38:01.000000Z",
"name": "Algèbre - 1"
},
"professor": {
"id": 94,
"created_at": "2018-09-24T08:18:30.000000Z",
"updated_at": "2019-10-23T14:32:00.000000Z",
"user_id": 810,
"grade": "Maître assistant",
"cin_delivered_at": "le 20/05/2015",
"cnrps": "********",
"cnss": "00000000",
"phone": "********"
},
"hour": {
"id": 1,
"heure_suivie": 13,
"type": "jour",
"created_at": "2021-08-19T20:02:16.000000Z",
"updated_at": "2021-08-05T20:02:16.000000Z",
"week_id": 1
}
}
Professor Model :
class professor extends Model
{
public function user()
{
return $this->belongsTo("App\User",'user_id','id');
}
public function courses()
{
return $this->belongsToMany('App\course');
}
public function hours()
{
return $this->belongsToMany('App\Hour');
}
public function courseHourProfessor()
{
return $this->hasMany('App\CourseHourProfessor', 'professor_id','id');
}
}
CourseHourProfessor Model :
class CourseHourProfessor extends Model
{
public function professor()
{
return $this->belongsTo('App\professor', 'professor_id');
}
public function course()
{
return $this->belongsTo('App\course', 'course_id');
}
public function hour()
{
return $this->belongsTo('App\Hour', 'hour_id');
}
}
Course Model
class Course extends Model
{
public function professor()
{
return $this->belongsToMany('App\professor');
}
public function hours()
{
return $this->belongsToMany('App\Hour');
}
public function courseHourProfessor()
{
return $this->hasMany('App\CourseHourProfessor', 'course_id','id');
}
}
Hour Model :
class Hour extends Model
{
//
public function week()
{
return $this->belongsTo(Week::class);
}
public function courses()
{
return $this->belongsToMany('App\course');
}
public function professors()
{
return $this->belongsToMany('App\professor');
}
public function courseHourProfessor()
{
return $this->hasMany('App\CourseHourProfessor', 'hour_id','id');
}
}
CourseHourProfessor Controller :
public function getById($id)
{
return CourseHourProfessor::with(['course','professor','hour'])->where('id', $id)->get();
}
I want to know if it's possible for the result to be like this
{
"id": 3,
"professor_id": 94,
"course_id": 132,
"hour_id": 1,
"nbr_hour_course": 9,
"course": {
"id": 132,
"created_at": "2018-07-25T16:02:19.000000Z",
"updated_at": "2018-09-07T07:38:01.000000Z",
"name": "Algèbre - 1"
},
"professor": {
"id": 94,
"created_at": "2018-09-24T08:18:30.000000Z",
"updated_at": "2019-10-23T14:32:00.000000Z",
"user_id": 810,
"grade": "Maître assistant",
"cin_delivered_at": "le 20/05/2015",
"cnrps": "********",
"cnss": "00000000",
"phone": "********"
"user": {
"id": 60,
"email": "********#gmail.com",
"name": "Aymen",
"lastname": "********",
"type": "professor",
"birthday": "2018-01-01",
"gender": "Male",
"image_id": 34,
"cin": "********",
"fullname": "********Aymen"
}
},
"hour": {
"id": 1,
"heure_suivie": 13,
"type": "jour",
"created_at": "2021-08-19T20:02:16.000000Z",
"updated_at": "2021-08-05T20:02:16.000000Z",
"week_id": 1
}
}
yes, what you want is a json :)
public function getById($id)
{
return CourseHourProfessor::with(['course','professor','hour'])->find($id)->toJson();
}

Best way to save/update data from json to Laravel model with relationships

I have two models:
Models/Arrival.php:
protected $guarded = [];
public function nomenclatures()
{
return $this->hasMany(ArrivalNomenclature::class, 'arrival_id', 'id');
}
public function warehouses()
{
return $this->belongsTo(Warehouse::class, 'warehouse_id', 'id');
}
Models/ArrivalNomenclatures.php:
protected $guarded = ['id'];
public function nomenclatures()
{
return $this->belongsTo(Nomenclature::class, 'nomenclature_id');
}
public function arrivals()
{
return $this->belongsTo(Arrival::class, 'arrival_id');
}
I need to save from json:
{
"type": "provider",
"invoice": "123yk43",
"filial_id": 10,
"warehouse_id": 6,
"provider_id": 9,
"responsible": "ttt",
"user_id": "4",
"carried_out": 0,
"nomenclatures": [
{
"confirmed": 0,
"nomenclature_id": 1,
"price": 1337,
"quantity": 10,
},
{
"confirmed": 0,
"nomenclature_id": 1,
"price": 1337,
"quantity": 10,
}
....
]}
Creation raises no questions.
How to update models correctly?
$arrival = Arrival::findOrFail($id);
$arrival->update($dataArrival);
ArrivalNomenclature::where('arrival_id', $arrival->id)->delete();
foreach ($request->nomenclatures as $nomenclature) {
$data[] = new ArrivalNomenclature($nomenclature);
}
$arrival->nomenclatures()->saveMany($data);
At the moment I find it by id and make an update. Then I delete all child records by id. I create an array of models in a loop and use the saveMany () method to save it to the database.
Is there a nicer way?

Laravel appends only one attribute from relationship

I'm trying to add an extra field to my Laravel 7 API model:
class Layer extends Model {
protected $fillable = ['name', 'filename', 'status', 'category_id'];
protected $appends = ['category_name'];
public function getCategoryNameAttribute()
{
return $this->category->name;
}
public function category()
{
return $this->belongsTo('App\LayerCategory', 'category_id');
}
}
My Controller:
.....
public function index()
{
return Layer::orderBy('name', 'asc')->paginate();
}
.....
I expect the following response:
{
"id": 1,
"category_id": 1,
"name": "My Layer",
"filename": "file_name.zip",
"status": true,
"category_name": "My category name"
}
But I receive:
{
"id": 1,
"category_id": 1,
"name": "My Layer",
"filename": "file_name.zip",
"status": true,
"category_name": "My category name",
"category": [
"id": 1,
"name": "My category name",
"status": true
]
}
How to return only the category name?
PS: I also tried with Resources.
Since you're eager loading the Category relationship to get category_name, you'll need to add logic to hide category from your JSON response. This can be done using the Hidden attribute on Serialization:
protected $hidden = ['category'];
You can read https://laravel.com/docs/7.x/eloquent-serialization#hiding-attributes-from-json for more information.

How to get records order by pivot column using laravel elquent?

I am trying to sort records order by highscore desc that I get top high scored users. I have tried a lot and still trying but could not achieve the task.
Following is working but it does sorting
$GameLog = User::with(['games' => function ($q){
$q->withPivot('highscore','level');
}])->get();
I also tried following to achieve it but this is also not working
$GameLog = User::with(['games' => function ($q){
$q->withPivot('highscore','level');
}])->groupBy(DB::raw('highscore DESC'))
->get();
I also tried sortBy() function in the loop but still I am facing issue. The first query is returning following result which should be sort by highscore
{
"status": "success",
"data": [
{
"id": 1,
"name": "fasdfsad",
"games": [
{
"id": 1,
"pivot": {
"highscore": 506,
}
}
]
},
{
"id": 8,
"name": "john",
"favorite_game_id": null,
"games": [
{
"id": 1,
"pivot": {
"highscore": 2340,
}
}
]
},
{
"id": 10,
"name": "tfyuyu",
"games": [
{
"id": 1,
"pivot": {
"highscore": 100,
}
}
]
}
]
}
Can someone kindly give me any idea how can I fix it I would appreciate. Thank you so much
Edited for Models
In Game.php
public function users()
{
return $this->belongsToMany(User::class, 'user_and_game', 'game_id', 'user_id')
->withPivot('highscore');
}
In User.php
public function games()
{
return $this->belongsToMany(Game::class, 'user_and_game', 'user_id', 'game_id');
}
I would like to appreciate if someone kindly help me about that
You need to create a new model for pivot (highscore). For example:
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class Highscore extends Pivot
{
public function user()
{
return $this->belongsTo(User::class);
}
public function game()
{
return $this->belongsTo(Game::class);
}
}
Note: from the example, we are extending from Pivot class instead of Model.
In the controller you can sort it like this example:
$highscores = Highscore::orderByDesc('score')
->with('user', 'game')
->get();
When using a custom pivot table, you need to define it from User and Games table.
public function users()
{
return $this->belongsToMany(User::class, 'user_and_game', 'game_id', 'user_id')
->using(Highscore::class)
->withPivot('highscore');
}

Laravel/Eloquent mutate model on join

I'm trying to mutate a model to display an array of strings and not an array of objects.
Current Output
{
"id": 1,
"company_name": "blah"
"language": [
{
"name": "English"
},
{
"name": "French"
}
]
},
{
"id": 2,
"company_name": "blah2"
"language": [
{
"name": "English"
},
{
"name": "French"
}
]
}
Desired Output
{
"id": 1,
"company_name": "blah"
"language": ["English","French"]
},
{
"id": 2,
"company_name": "blah2"
"language": ["English","French"]
}
Partner Model
class Partner extends Eloquent
{
protected $table = 'property_managers';
protected $visible = array('id','company_name','language');
public function language(){
return $this->belongsToMany('Language', 'property_manager_language', 'property_manager_id', 'language_id');
}
}
Language Model
class Language extends Eloquent
{
protected $table = 'languages';
protected $visible = array('name');
public function propertyManager()
{
return $this->belongsToMany('PropertyManager');
}
}
I'm accessing it via the code snippet below
$pm = Partner::with('language')->get();
I looked into mutators but it doesn't seem to hit that attribute within the partner model.
public function getLanguageAttribute(){
//run my code to flatten to array
}
So I'm curious as to if mutators don't work on joins or how you would be able to modify the return on the join. I can add a mutator to the Language model but that will only modify the attributes of that specific model. Any insight would be helpful. Thanks
In your model,
public function getLanguagesAttribute(){
return array_pluck(collect($this->language)->toArray(), 'name');
}
luego prueba con esto
$partner = Partner::find(1);
return $partner->languages;

Categories