Get the collection instead of the ID - php

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

Related

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.

Load All posts with their tags into an array Laravel eloquent polymorphic relationship

I need to fetch all posts existed in my table with all their tags into an array. As you see below, this query just gets the posts that have tags but I need all posts even they don't have any tags. In addition, I need to have a tag:[] variable in my array but I don't know how to get all posts with their tags in one query.
Thank you in advance.
public function getItemsWithTags(array $attr)
{
return self::$model::
whereNotNull('title')->
whereNotNull('content')->
whereNotNull('author')->
whereNotNull('category')->
whereNotNull('img_url')->
has('tags')->
get()->
toArray();
}
class BaseModel extends Model
{
protected $table;
protected $primaryKey;
use SoftDeletes;
}
class BlogModel extends BaseModel
{
protected $table = 'blog';
protected $primaryKey = 'id';
public function tags()
{
return $this->morphToMany(TagsModel::class,'taggable',null,null,'tag_id');
}
}
class TagsModel extends BaseModel
{
protected $table = 'tags';
protected $primaryKey = 'id';
protected $fillable = ['name'];
public function blog()
{
return $this->morphedByMany(BlogModel::class,"taggable");
}
}
the Output of this query:
{
"id": 28,
"title": "dfg",
"content": "<ul>\n<li>rdgrdgf</li>\n<li>dfg</li>\n<li>dg</li>\n<li>dgf</li>\n<li>dfg</li>\n</ul>",
"author": "gd",
"category": "Design",
"img_url": "uploads/post/Screenshot from 2020-03-27 20-34-42_7dc41dca1ebc4dabcb921fc7f4c4744a.png",
"created_at": "2020-05-03T18:47:38.000000Z",
"updated_at": "2020-05-03T18:47:38.000000Z",
"deleted_at": null,
"user_id": 1,
"category_id": 7
}
and what I need is :
{
"id": 28,
"title": "dfg",
"content": "<ul>\n<li>rdgrdgf</li>\n<li>dfg</li>\n<li>dg</li>\n<li>dgf</li>\n<li>dfg</li>\n</ul>",
"author": "gd",
"category": "Design",
"img_url": "uploads/post/Screenshot from 2020-03-27 20-34-42_7dc41dca1ebc4dabcb921fc7f4c4744a.png",
"created_at": "2020-05-03T18:47:38.000000Z",
"updated_at": "2020-05-03T18:47:38.000000Z",
"deleted_at": null,
"user_id": 1,
"category_id": 7,
"tags":['tag1','tag2']
}
return self::$model::
with('tags')->
whereNotNull('title')->
whereNotNull('content')->
whereNotNull('author')->
whereNotNull('category')->
whereNotNull('img_url')->
get()->
toArray();
You use has as the name tells, this method checks if there is a tag relationship, use with instead:
public function getItemsWithTags(array $attr)
{
return self::$model::
whereNotNull('title')->
whereNotNull('content')->
whereNotNull('author')->
whereNotNull('category')->
whereNotNull('img_url')->
with('tags')->
get()->
toArray();
}

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;

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

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%

Categories