When to use getXXAttribute vs a relationship in Laravel - php

I am putting together a model of mine and I am wondering what is the most relevent method to use for something like "author".
I have:
public function images() {
return $this->morphMany('App\Models\Image', 'imageable');
}
public function ratings() {
return $this->hasMany('App\Models\Rating');
}
public function favorited() {
return $this->hasMany('App\Models\Favorite');
}
public function author() {
return $this->hasOne('User');
}
public function getMyFavoriteAttribute() {
return $this->favorited->where('user_id', Auth::user()->id)->count();
}
public function getFavoritesAttribute() {
return $this->favorited->count();
}
public function getRatingAttribute() {
return $this->ratings->sum('rating');
}
I have created a relationship called author as seen above. When would it be preferred to create this as a getAuthorAttribute?

get__Attribute is only necessary if you want to manipulate the original value of the stored attribute. Due to the fact that Author is already accessible through your relation it's not necessary to add an additional getter.

Related

Laravel many to many relation not working as expected

this might be a silly question, but I am trying to connect 1 table to 2 related tables.
Inside the values array component_id 1 shows up when requesting data for component with id 2.
The relation inside Component::class
public function fields()
{
return $this->hasManyThrough(Field::class, FieldValue::class, 'component_id', 'id', 'id', 'field_id');
}
Maybe you make mistake, try determine relationships like that:
public function fields()
{
return $this->hasManyThrough(Field::class, FieldValue::class);
}
OR
public function fields()
{
return $this->hasManyThrough(Field::class, FieldValue::class, 'component_id', 'field_id', 'id', 'id');
}
And of course, check correct your code reading official documentation how to use this relationship.
Component::
public function fields()
{
return $this->hasMany(Field::class);
}
public function values()
{
return $this->hasManyThrough(Field::class, FieldValue::class);
}
Field:: (table) id,component_id
public function component()
{
return $this->belongsTo(Component::class);
}
public function values()
{
return $this->hasMany(FieldValue::class);
}
FieldValue:: (table)id,field_id
public function field()
{
return $this->belongsTo(Field::class);
}

How to paginate for hasMany relationship in laravel (App\News::user must return a relationship instance)

I am not able to paginate in laravel in this situation
return $this->hasMany('App\News','category_id')->orderBy('id','desc')->paginate(20);
but says error. in controller I have also tried
$byCategories=Category::findOrFail($id)->paginate(20);`
it also says error.
help me.
My Model is
class Category extends Model
{
public function news()
{
return $this->hasMany('App\News','category_id')->orderBy('id','desc');
}
public function newsMany()
{
return $this->belongsToMany('App\News')->paginate(20);
}
public function user()
{
return $this->belongsTo('App\User');
}
public function getRouteKeyName()
{
return 'slug';
}
}
another model one is
class News extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
public function category()
{
return $this->belongsTo('App\Category');
}
}
my controller code is
public function byCategory($id)
{
$byCategories=Category::findOrFail($id);
return view('back-end/news/byCategory', compact('byCategories'));
}
Thank you so much.
Pagination is not done in the Model
it is to be done in the controller, For example remove (->paginate(20);) from here
public function newsMany()
{
return $this->belongsToMany('App\News')->paginate(20);
}
keep it only as
public function newsMany()
{
return $this->belongsToMany('App\News');
}
and call the pagination in controller when returning the view
$news=Category::findOrFail($id)->newsMany()->paginate(20);
return view('view name', compact('news'));

2 foreign keys on one column in laravel 5.2

here's my database schema
and I have these models:
Admin
User
Bet
Match
Team
I'm confused how to define the relationShip between matches and teams in models
here Is what I did till now...
User.php
public function bets()
{
return $this->hasMany('\App\Bet');
}
Bet.php
public function user()
{
return $this->belongsTo('\App\User');
}
public function match()
{
return $this->belongsTo('\App\Match');
}
Match.php
public function bets()
{
return $this->hasMany('\App\Bet');
}
//?????????????
Team.php
//?????????????
actually what I need Is the code that should be placed instead of //???... in both Team.php and Match.php so that I can easily do such things...
$team->matches();
$match->team1();
$match->team2();
thanks
It should be something like this:
Match.php
public function team1()
{
return $this->belongsTo('\App\Team', 'team1_id');
}
public function team2()
{
return $this->belongsTo('\App\Team', 'team2_id');
}
Team.php
public function matches()
{
return $this->hasMany('\App\Match', 'team1_id')
->orWhere('team2_id', $this->id);
}
You can specify which column should be targeted for each relationship:
public function team1() {
return $this->belongsTo('\App\Match', 'team1_id');
}
public function team2() {
return $this->belongsTo('\App\Match', 'team2_id');
}
Let me know if this helps.
It would be something like this. Give it a try.
Match.php
public function team1(){
return $this->belongsTo('App\Team', 'team1_id');
}
public function team2(){
return $this->belongsTo('App\Team', 'team2_id');
}
Team.php
public function matches1(){
return $this->hasMany('App\Match', 'team1_id', 'id');
}
public function matches2(){
return $this->hasMany('App\Match', 'team2_id', 'id');
}

Laravel Eloquent Relationship hasMany hasOne

I am trying to get my head around Laravel's relationships but having difficulty with the last part of what I'm trying to achieve.
My tables are like so:
pagetemplates
id
pages
id
pagetemplate_id
pagetemplate_blocks
id
pagetemplate_id
pagetemplateblocks_content
id
page_id
page_template_block_id
So when loading a page out of the DB I need to get it with pagetemplates, with it's blocks and with the content.
Here's my code so far:
Page.php
public function pageTemplate()
{
return $this->belongsTo('PageTemplate', 'pagetemplate_id')->with('blocks');
}
public function pagetemplateblockcontent()
{
return $this->belongsToMany('PageTemplateBlockContent', 'pagetemplateblocks_content', 'page_id', 'page_template_block_id')->withTimestamps();
}
public function pagecontent()
{
return $this->hasMany('PageTemplateBlockContent', 'page_id')->with('pagetemplateblock');
}
PageTemplate.php
public function page()
{
return $this->hasMany('Page', 'pagetemplate_id');
}
public function blocks() {
return $this->hasMany('PageTemplateBlock', 'pagetemplate_id')->orderBy('sort_order', 'asc')->with('blockcontent');
}
PageTemplateBlock.php
public function pagetemplate() {
return $this->belongsTo('PageTemplate', 'pagetemplate_id');
}
public function blockcontent() {
return return $this->hasOne('PageTemplateBlockContent');
}
PageTemplateBlockContent.php
public function pagetemplateblock()
{
return $this->belongsTo('PageTemplateBlock', 'page_template_block_id');
}
However, the issue is with the content, if I try this it returns one instance of PageTemplateBlockContent, which is the same for all of the pages. Although there should be a different PageTemplateBlockContent for each Page. I'm not sure how to get around this, so any ideas would be greatly appreciated.
UPDATED
My Controller calls
$this->pageRepo->where('id', $id)->with('pageTemplate');
"pageTemplate" returns the following:
return $this->belongsTo('PageTemplate', 'pagetemplate_id')->with('blocks');
"blocks" returns the following:
return $this->hasMany('PageTemplateBlock', 'pagetemplate_id')->orderBy('sort_order', 'asc')->with('blockcontent');
"blockcontent" returns the following:
return $this->hasOne('PageTemplateBlockContent');
So this means it's never hitting the "pagetemplateblockcontent" which Joost suggested creating.
Change
public function pagetemplateblockcontent()
{
return $this->belongsToMany('PageTemplateBlockContent', 'pagetemplateblocks_content', 'page_id', 'page_template_block_id')->withTimestamps();
}
to
public function pagetemplateblockcontent()
{
return $this->belongsToMany('PageTemplateBlockContent', 'pagetemplateblockscontent_page', 'page_id', 'page_template_block_id')->withTimestamps();
}
and create an table page_pagetemplateblockcontent with two primary keys like so.
$table->integer("page_id")->unsigned();
$table->integer("page_template_block_id")->unsigned();
$table->primary(['page_id', 'page_template_block_id']);

Eager loading on polymorphic relations

class Admin {
public function user()
{
return $this->morphOne('App\Models\User', 'humanable');
}
public function master()
{
return $this->hasOne('App\Models\Master');
}
}
class Master {
public function admin()
{
return $this->hasOne('App\Models\Admin');
}
}
class User {
public function humanable()
{
return $this->morphTo();
}
public function images()
{
return $this->hasOne('\App\Models\Image');
}
}
class Image {
public function user()
{
return $this->belongsTo('\App\Models\User');
}
}
Now if I dump this:
return \App\Models\Admin::where('id',1)->with(array('user.images','master'))->first();
I get the perfect result one master, one user and one image record.
But if I do this
return $user = \App\Models\User::where('id',1)->with(array('humanable','humanable.master'))->first();
I only get one Admin record, the query get * from masters doesn't even run.
Any idea what I'm doing wrong, I'm sure this is possible.
If I remember correctly Laravel has lots of pitfall. You can try to use the protected $with var in Admin model instead of query builder with function.
class Admin {
protected $with = ['master'];
public function user() {
return $this->morphOne('App\Models\User', 'humanable');
}
public function master() {
return $this->hasOne('App\Models\Master');
}
}
In query builder, only need to include humanable. Now you should see master inside the humanable object.
return $user = \App\Models\User::where('id',1)->with('humanable')->first();
Hope this help.

Categories