Laravel 6 - Accessor appends not called in relationships - laravel

I use Laravel 6 and I want access to avatar attribute from user when I use posts() relation.
User model:
/**
* #var array
*/
protected $appends = [
'avatar',
];
/**
* #return HasMany
*/
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
/**
* #return string
*/
public function getAvatarAttribute(): string
{
return sprintf('https://secure.gravatar.com/avatar/%s?s=500', md5($this->email));
}
The code of my controller:
$topic = Topic::where('slug', $slug)->firstOrFail();
foreach ($topic->posts()->get() as $post) {
dd($post->user->avatar); // return null
}
Post model:
/**
* #return BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
I get the name of user with $post->user->name but avatar attribute is not called.

Related

How to get property or method in relationship ( laravel - eloquent )

in Post Model
function user()
{
return $this->belongsTo( \App\User::class);
}
in User Model
function posts()
{
return $this->hasMany( \App\Post::class);
}
function somedata()
{
return date('i') * 1000 + date('s');
}
in Controller
$posts = Post::query()
->where('id', 10)
->with('user')
->get();
but it does not get 'somedata' in user model .
How can I drag this data with posts ?
Try making it an attribute and append it in the model
Post.php
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = ['someData'];
/**
* Get the some data for the post.
*
* #return int
*/
public function getSomeDataAttribute()
{
return date('i') * 1000 + date('s');
}
You need to set an Accessor:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the user's somedata.
*
* #return string
*/
public function getSomedataAttribute()
{
return 'somedata';
}
}
Also see: https://laravel.com/docs/5.8/eloquent-mutators

Appending Eloquent Attributes/Modified Relation Date on Query Building / Code Optimization

I'm looking for a solution to optimize my Code using Laravel Eloquent.
My issue is that I want to add Attributes conditionally, and this Attributes is basically the a transformed many-to-many relationship.
At the moment I have this in my controller (simplified):
<?php
namespace App\Http\Controller;
/**
* Class Category
*/
class Category extends Controller
{
/**
* #return Collection
*/
public function index()
{
return Category::withCount('countries')->get();
}
/**
* #param int $id
*
* #return Category
*/
public function show($id)
{
$result = Category::where('id', $id)
->with('countries')
->firstOrFail();
$result->countries_list = '';
return $result;
}
}
My Category model looks like this (simplified):
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
/**
* Class Category
*/
class Category extends Model
{
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'countries',
];
/**
* #return string
*/
public function getCountriesCountAttribute()
{
return trans_choice('labels.countries', $this->original['countries_count']);
}
/**
* #return
*/
public function getCountriesListAttribute()
{
return $this->countries->pluck('alpha_2');
}
/**
* Get the related Countries.
*/
public function countries()
{
return $this->belongsToMany(
Country::class,
'category_country',
'category_id',
'country_id'
);
}
}
The Country Model is just a list of Countries with id, name, the Alpha2 Code, etc. I can't use the protected $appends to add countries_list because than the the list would be always included.
I also can't change my Countries model because this is used in several other occurrences.
What I'm looking for is a way to optimize the code in the controller to this:
<?php
namespace App\Http\Controller;
/**
* #return Collection
*/
public function index()
{
return Category::withCount('countries')->get();
}
/**
* #param int $id
*
* #return Category
*/
public function show($id)
{
return Category::where('id', $id)
->withAttribute('countries_list') // An array of all country aplha 2 codes
->firstOrFail();
}
You can access the countries_list attribute after querying (don't include it in your query).
public function show($id)
{
$category = Category::findOrFail($id);
$list = $category->countries_list; // this calls getCountriesListAttribute()
}

Laravel Relationship Issues : Laravel 5.4

I have 2 tables in my application... Users Conventioners
I have users id in the conventioners table and i want to access their genders from the Users table....
I have like 10 user ids in the conventioners table and 20 users in the users table...
Please how do I access all their genders in the users table...
$conventioners->users()->gender
Conventioners is an instance of the Conventioner Model which contains a relationship **belongsToMany
Thanks alot guys
Here is my Conventioner Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Conventioner extends Model
{
/**
* #var string
*/
protected $table = 'conventioners';
/**
* #var array
*/
protected $fillable = [
'user_id','year','church_id','convention_id'
];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('App\User');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function users()
{
return $this->hasMany('App\User');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function convention()
{
return $this->belongsTo('App\Convention');
}
}
Here is my ConventionController method called Convention...
It retrieves the details for the current convention
public function convention($slug)
{
if(!$this->admin()) return redirect()->back();
$convention = Convention::where('slug', $slug)->first();
$participants = Conventioner::where('convention_id', $convention->id)->get();
$conventioner = [];
foreach($participants as $participant)
{
$thisUser = [];
$thisUser['data'] = User::withTrashed()->where('id', $participant->user_id)->first();
$thisUser['convention'] = $participant;
array_push($conventioner, $thisUser);
}
var_dump($participants->users()->pluck('gender')->all());
return view('dashboard/conventions/convention', [
'convention' => $convention,
'user' => Auth::user(),
'conventioners' => $convention->conventioners(),
'participants' => $conventioner
]);
}
The problem is that users is a collection not an individual that you can call gender on. If you want a list of all the genders you can use the following:
Conventioner::where('convention_id', $convention->id)->with('users')->get()
$conventioners->pluck('users')->pluck('gender')->all();
This will return an array of the genders. You can read more about pluck here.
The pluck method retrieves all of the values for a given key

Laravel Modeling join three Table in single line

i have 3 table/Model such as Users, CurrentCurrency and CurrencyType, in CurrentCurrency 2 column are relation with CurrencyType and Users, as user_id and currency_id
i can use this code to fetch CurrentCurrency user :
$all_records = CurrentCurrency::with('user')->orderBy('id', 'DESC')->paginate(50);
this code return all records with users, now i want to create simple related with CurrencyType by Modeling, unfortunately for this table i get null
CurrentCurrency :
class CurrentCurrency extends Model
{
protected $table = 'current_currency';
protected $fillable = ['currency_id', 'current_money', 'user_id'];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('App\User');
}
public function currency_type()
{
return $this->belongsTo('App\CurrencyType');
}
}
CurrencyType:
class CurrencyType extends Model
{
protected $table = 'currency_type';
protected $fillable = ['currency_type', 'currency_symbol', 'user_id'];
public function user()
{
return $this->belongsTo('App\User');
}
public function currency()
{
return $this->hasMany('App\current_currency');
}
}
User:
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* #param $value
*/
public function setPasswordAttribute($value)
{
$this->attributes['password'] = Hash::make($value);
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function currentCurrency()
{
return $this->belongsToMany('User', 'CurrentCurrency', 'user_id', 'currency_id');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function currencyType()
{
return $this->hasMany('App\CurrencyType');
}
}
By this code i can get user information:
$all_records = CurrentCurrency::with(['user', 'currency_type'])->orderBy('id', 'DESC')->paginate(50);
foreach ($all_records as $key => $contents) {
echo $contents->user;
}
But i can not get currency_type, thats return null
RESULT:
{"id":3,"current_money":"333","user_id":1,
"created_at":"\u0622\u0630\u0631 20\u060c 1394",
"updated_at":"\u0622\u0630\u0631 20\u060c 1394",
"currency_id":1,"user":{"id":1,"name":"\u0645\u0647\u062f\u06cc",
"family":"\u067e\u06cc\u0634\u06af\u0648\u06cc","username":"mahdi","token":"",
"email":"pishguy#gmail.com",
"image_file_name":"","mobile_number":"09373036569",
"status":1,"created_at":"\u0622\u0630\u0631 20\u060c 1394",
"updated_at":"\u0622\u0630\u0631 20\u060c 1394"},
"currency_type":null}
You have to update the relation in CurrentCurrency as below:
return $this->belongsTo('App\CurrencyType','currency_id', 'id');
// where currency_id is foreign_key and id is otherKey referring to id of currency_type table
Also update your query to select user with CurrencyType as below :
$all_records = CurrentCurrency::with(array('user','currencyType'))->orderBy('id', 'DESC')->paginate(50);
http://laravel.com/docs/5.1/eloquent-relationships#updating-belongs-to-relationships
In file CurrencyType
return $this->hasMany('App\current_currency');
should be
return $this->hasMany('App\CurrentCurrency');

laravel 4 - inserting of multiple fields in array

The following function in laravel stores my form input. I can't get it to store anything other than the author id and the title. It just won't store the keywords.
Below is the function in my Postcontroller.php
public function store()
{
$input = Input::all();
$rules = array(
'title' => 'required',
'text' => 'required',
);
$validation = Validator::make($input, $rules);
if ($validation->fails()) {
return Redirect::back()->withErrors($validation)->withInput();
} else {
// create new Post instance
$post = Post::create(array(
'title' => $input['title'],
'keywords' => $input['keywords'],
));
// create Text instance w/ text body
$text = Text::create(array('text' => $input['text']));
// save new Text and associate w/ new post
$post->text()->save($text);
if (isset($input['tags'])) {
foreach ($input['tags'] as $tagId) {
$tag = Tag::find($tagId);
$post->tags()->save($tag);
}
}
// associate the post with user
$post->author()->associate(Auth::user())->save();
return Redirect::to('question/'.$post->id);
}
}
Post.php (model)
<?php
class Post extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'posts';
/**
* Whitelisted model properties for mass assignment.
*
* #var array
*/
protected $fillable = array('title');
/**
* Defines a one-to-one relationship.
*
* #see http://laravel.com/docs/eloquent#one-to-one
*/
public function text()
{
return $this->hasOne('Text');
}
/**
* Defines an inverse one-to-many relationship.
*
* #see http://laravel.com/docs/eloquent#one-to-many
*/
public function author()
{
return $this->belongsTo('User', 'author_id');
}
/**
* Defines a many-to-many relationship.
*
* #see http://laravel.com/docs/eloquent#many-to-many
*/
public function tags()
{
return $this->belongsToMany('Tag');
}
/**
* Defines an inverse one-to-many relationship.
*
* #see http://laravel.com/docs/eloquent#one-to-many
*/
public function category()
{
return $this->belongsTo('Category');
}
/**
* Defines a polymorphic one-to-one relationship.
*
* #see http://laravel.com/docs/eloquent#polymorphic-relations
*/
public function image()
{
return $this->morphOne('Image', 'imageable');
}
/**
* Defines a one-to-many relationship.
*
* #see http://laravel.com/docs/eloquent#one-to-many
*/
public function comments()
{
return $this->hasMany('Comment');
}
}
You are stopping the mass assignment of keywords with your model settings.
Change
protected $fillable = array('title');
to
protected $fillable = array('title', 'keywords');

Resources