Laravel appends only one attribute from relationship - php

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.

Related

Laravel Eloquent Convert user_id to user info

I've some relationships in my Model classes.
Consume this relationship:
We've Post() model which store our posts data. Each post in this table has a user_id column that has one to many relationship with User() Mode (the author of the post)
class User extends Model {
public function posts()
{
return $this->hasMany('App\Post');
}
}
class Post extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
}
So when i want to return my post with elequent, I'll get something like this:
{
"user_id": 1,
"title": "Foo name",
"body": "Foo body",
},
{
"user_id": 1,
"title": "Bar name",
"body": "another Bar body",
}
But i want to get something like this:
{
"user_id": 1,
"user": {
'name'=> 'John',
'last'=> 'Maco',
},
"title": "Foo name",
"body": "Foo body",
},
{
"user_id": 1,
"user": {
'name'=> 'John',
'last'=> 'Maco',
},
"title": "Bar name",
"body": "another Bar body",
}
You need to declare the relation from Post to User
Post.php
class Post extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
Then you will be able to load the user with every post like #dparoli commented
$post = Post::with('user')->get();

Laravel Relationship between 3 tables

so I am trying to get the category name and this is what I have
tablets:
categories: id,name
post_categories: id, post_id, category_id
post : id, columns
I have the models: Post, PostCategory and Category.
Post Model :
public function categories()
{
return $this->hasMany('App\PostCategory');
}
PostCategory Model :
public function category()
{
return $this->hasMany(Category::class, 'id', 'category_id');
}
and in the controller I have
return Post::with('categories.category')->orderby('id','desc')->get();
And my result is
[
{
"id": 50,
"categories": [
{
"id": 92,
"category_id": 11,
"category": [
{
"id": 11,
"name": "JXrfLHdQVNON",
"image": null
}
]
}
]
}
]
and i wanted it to be something like
[
{
"id": 50,
"categories": [
{
"id": 1,
"name": "category_name",
"image": null
}
]
}
]
Is there a way to do it? I have been playing around with this and havent manage to find a easy way to do it
inside your Post model :
public function categories()
{
return $this->belongsToMany('App\Model\Category','post_categories','post_id','category_id')->withTimestamps();
}
in your controller :
return Post::with('categories:id,name,image')->orderBy('id','desc')->get();
This is a many-to-many relationship. Make sure you have your relationship set up correctly. If you want to choose specific columns you can do:
return Post::with('categories.category:id,name')->orderby('id','desc')->get();
It will return the columns id, name from category table/ model. You must specify id doing that.
https://laravel.com/docs/5.7/eloquent-relationships#many-to-many
https://laravel.com/docs/5.7/eloquent-relationships#eager-loading

many-to one relationship Eloquoent Orm

I have a challenge with Eloquent ORM for laravel am actually a newbie into this Eloquoent orm .i have a Model Country and a Model State. The state table has a foreign_key countryId. The issue is if i fetch all the states using eager loading with relationship as follows.
$countries = State::with('country')->get();
and my State model is as follows
class State extends Model
{
protected $fillable = ['name', 'countryId'];
protected $table = 'states';
function Country(){
return $this->belongsTo('Country','id');
}
}
The result i get is as follows
[
{
"id": 1,
"name": "Lagos",
"countryId": "1",
"created_at": "2017-03-09 13:09:12.000",
"updated_at": "2017-03-09 13:09:12.000",
"country":{"id": 1, "name": "Nigeria", "created_at": "2017-03-09 10:55:46.000", "updated_at": "2017-03-09 10:55:46.000"…}
},
{
"id": 2,
"name": "Oyo",
"countryId": "1",
"created_at": "2017-03-09 13:29:12.000",
"updated_at": "2017-03-09 13:29:12.000",
"country": null
}
]
it can bbe seen from the json output that the second item country object is not loaded.
i also tried to set a relationship on the Country model but no changes
class Country extends Model
{
protected $fillable = ['name'];
protected $table = 'countries';
function State(){
return $this->hasMany('State', 'countryId');
}
}
thanks in anticipation of your response
Try to fix your relationship first and try again. Define it this way in State model
public function country(){ //lower 'c' NOT capital
return $this->belongsTo(Country::class, 'countryId'); //Pass the class AND the foreign key. You passed the primary key
}
Then try again.
The reason the second one has no country is because you set 'id' in the relationship and there is no country with 'id' 2. So simply fix your relationship and you should be good to go.

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