I have a controller which has a query such as this one:
$post = Post::find($id);
$comments = $post->comments;
Where a post has many comments and a comment belongs to one post. The comments model has an id,comment,tag field.
What I want to do is that for any query such as this one, the model returns the fields id, comment, tag and tag_translated, where the latter is just a translation of the tag using the Lang facade.
I could solve this by using a for on the controller which iterates over the $comments and adds the field, however Ill have to do that for every controller that requires the tag_translared field. Is there a way to ask the model to include such a field?
Add this in your Comment Model:
protected $appends = ['tag_translated'];
public function getTagTranslatedAttribute()
{
return 'the translated tag';
}
Hope this helps.
Yes there is? just add this to your Comment model
public function getTagTranslatedAttribute()
{
return Lang::methodYouWish($this->tag);
}
then you can access this property from comment instance
$comment->tag_translated;
EDIT
You can modify your toArray method, just add it to Comment class
protected $appends = ['tag_translated'];
and then
$comment->toArray();
I was facing the same issue, and you just need to add two things:
The first one is the appends field:
protected $appends = ['field'];
The second one is the "getter":
public function getFieldAttribute()
At the end of the method name you need to add the "Attribute" suffix, and that's it.
Related
i'm using laravel 7.30, I have a post model linked to user model with belongsTo relationship, I want to retrieve all posts with user property that contains only the name of the user for api purposes.
what i've tried so far.
public function index()
{
return Post::with('user:id,name')->get();
}
but the result of this code is a nested object 'user' which has 2 fields id and name on each post, I only want a single field with posts fields called user which has the name only and not a nested object for api purposes.
I've made it using database query builder, but i'm looking for a way using Eloquent
Thanks in advance
You can add this to your Post Model:
protected $appends = [
"author_name"
];
public function getAuthorNameAttribute()
{
return $this->user->name;
}
This will make sure the user's name is appended to the Post object every time it is being called.
Then from your controller, you can easily do this:
public function index()
{
return Post::get();
}
I have a make table and post table. Make table saves make names as make_code and make_name.
Post table has a column make. While saving a post, it will save make in make_code.
While displaying in blade, I want it to display as make_name. How can I do it?
Currently {{$post->make}} gives me make_code. I need it to show make_name.
I think its a one-to-one relationship that's needed. I tried putting it in model but did not work. How can I achieve it?
MAKE MODEL
class Make extends Model
{
public function make()
{
return $this->belongsTo(App\Post::class);
}
}
POST MODEL:
class Post extends Model
{
protected $table = 'posts';
}
Update
As Tim Lewis noticed:
the relationships can't be named make, as that's a conflict.
Assuming that the your relationship work like this:
a Make has many Post
a Post belongs to a Make object.
| Note: Correct me if I'm wrong.
So, if this is correct, you should define your relationships like this:
Post.php
public function make_rel()
{
return $this->belongsTo(Make::class, 'make', 'make_code');
}
Make.php
public function posts()
{
return $this->hasMany(Post::class, 'make', 'make_code');
}
Check the One-to-Many and One-to-Many (Inverse) relationship sections of the documentation.
So, you could do in your controller (or wherever you want):
$post = Post::find(1);
dd($post->make_rel->make_name); // 'Harley Davidson'
Additionally, you could create a computed property as a shorcout to access this related property in your Post model:
Post.php
// ...
public function getMakeNameAttribute()
{
return $this->make_rel->make_name;
}
Now, you can access it like this:
$post = Post::find(1);
dd($post->make_name); // 'Harley Davidson'
Suggestion
As a suggestion, I strongly advice you to change your foreign key column from make to make_id (in your 'posts' table) to avoid conflicts. Also, you could relate the post to the make primmary key instead of a custom key given the fact that this link is almost invisible and it is handled by Laravel. This would speed up the execution of the query because primmary id's are indexed by default.
I have a newsletter and block model that has a many to many relation. When I attach a block to a newsletter I want the id of the row that was insterted in the pivot table.
This is what I tried but results in "null"
$newsletter = Newsletter::findOrFail($newsletterId);
$newsletterBlock = $newsletter->blocks()->attach($blockId);
dd($newsletterBlock);
Although this question is old, however nobody gave the right answer. If you are in a situation that your pivot table has a primary key.
Using withPivot method is useful when you want get the id when you load the related model. However when you attach something you can not get the pivot_id;
In these situations best thing to do is to use a model that is connected to the pivot table, then only thing you need to do is inserting into pivot table using its model instead of attaching two models together.
in this example, first create a model called BlockNewsLetter if it is necessary fill the $table and $fillable attributes of the model and then you are good to go.
$newsletter = Newsletter::findOrFail($newsletterId);
$blockNewsLetterPivot = BlockNewsLetter::updateOrCreate([
'block_id' => $block_id ,
'newsLetter_id' => $newsletter->id
]);
$inserted_pivot_id = $blockNewsLetterPivot->id;
Try this, haven't test it but this should work:
/** Newsletter.php */
public function blocks()
{
return $this->belongsToMany('App\Block')
->withPivot('id');
}
Then in your controller:
$newsletter = Newsletter::findOrFail($newsletterId);
$newsletter->blocks()->attach($blockId);
// then you could:
foreach($newsletter->blocks as $block)
{
dd($block->pivot->id);
}
Check this section of the docs.
I have some problem with laravel and protected $attributes and mutators.
I have user ranking with points. I want add to User Model another attribution with ranking Position.
In user model I have public function like this:
public function getRankPositionAttribute(){
$userPoints= Ranking::where('user_id','=',$this->id)->first();
$userPosition = Ranking::where('points','>',$userPoints->points)->count()+1;
return $userPosition;
}
I also set:
protected $attributes = array('RankPosition'='');
But it's not working (I don't see value like RankPosition in attributes). Strange thing is that when I add (for example) value like this:
protected $attributes =array('test'=>'yes');
Laravel also don't see test...
But when I add this:
protected $appends = array('RankPosition');
and in my controller I find all user and get response to json then in json response i see value like RankPosition with the correct value... :(
What Im doing wrong? Why "my laravel" skips protected $attributes?
Please help me.
This is because if you provide protected $attributes in your class then Laravel doesn't override it when the source of attributes are the table . Here the source of $attributes is database column.
But when you do something like this:
$user = new User;
then you will see a test attribute.
So to dynamically adding the attributes you should use appends property on the model.
So I have the tables tags, posts and a link table for these
Now I want to get all the tags from the current post.
Now I want to get all the tags related to this post.
I made a model "Tag" (with no functions yet, just extending Eloquent)
How can I use this model to get all the tag names/titles based on the current post id, or do I need a seperate model for the Linking table(Which seems incorrect to me)?
I'm kinda lost in it right now, probably due to too much searching.
Anyone can help me out here?
SOLVED
$post = Post::where('id', $id)->first();
$tags= $post->tags;
Tags function in the Post model:
public function tags()
{
return $this->belongsToMany('Tag');
}
Add the following function to your Post model
public function tags()
{
return $this->belongsToMany('Tag');
}
Now you can call $post->tags()->getResults() to get all tags of a post.
Corresponding docs: http://laravel.com/docs/4.2/eloquent#many-to-many