Just wanted to know if it is possible to eager-load a defined accessor in Laravel Repository. I am currently using this l5-repository package and Laravel 5.4.
In my UserInfo.php model, I have this function
public function getFullNameAttribute()
{
return ucfirst($this->first_name . " ". $this->last_name);
}
Then I am trying to eager load that accessor in my controller like this.
$user_infos = $this->repository->with('full_name')->all();
// or $user_infos = $this->repository->with('getFullNameAttribute')->all();
return response()->json([ 'data' => $user_infos ]);
I know that it is not gonna work. I am just looking for a similar way to add my accessor full_name in my collection. So I don't need to concatenate in my front end. So my expected result would be
{
id : 1,
first_name : "Sample fname",
last_name : "Sample lname",
.....
.....
full_name : "Sample fname Sample lname",
}
Use $appends in your model UserInfo.php
protected $appends = ['full_name'];
This will append this custom field in your collection.
Then you can see it here :
$user_infos = UserInfo::all();
$user_infos->toJson();
You can see the appended accessor in the json.
Related
i have a model called Customer that has HasMany Relatinship toNotes model
public function notes()
{
return $this->hasMany(Note::class);
}
and Note has BelongsTo relationship to Customer
public function customer()
{
return $this->belongsTo(Customer::class);
}
then i defined the same relationship in Note nova resource
BelongsTo::make('Customer', 'customer', Customer::class)
until here every thing works perfectly now if want to call ->searchable() on BelongsTo field it doesn't return any thing from search
BelongsTo::make('Customer', 'customer', Customer::class)->searchable()
how can i solve this problem
Your BelongsTo field is in different table, so if you want to search something in Note Resource with Customer field your search won't work. In this case I use SearchesRelations package for searching. You could install this package and put this code in your Resource class
public static $searchRelations = [
'customer' => ['name', 'another_customer_field'],
];
Please check the documentation for more details SearchesRelations .
the field that you call srearchable() on must be in search array in your resource.
so if your field is BelogsTo you must put the title field of the resource that you are belonging to into sreach array
in my case the title field is
public static $title = 'name';
so i put it in
public static $search = [
'id',
'name',
];
and every thing works as expected
I have a laravel table with a column I've defined like this in the migration:
$table->json('json');
And in the model, I cast it to an array:
protected $casts = [
'json' => 'array'
];
This works perfectly the majority of the time I need it, but there's one api call I'm making where I actually want my collection of that Model to give me the raw string rather than casting it to the array.
So, assuming my model is called Model, my api call looks like this:
$systemModels = Model::whereNull('user_id')->get();
$userModels = Model::where('user_id', $user->id)->get();
return response()->json([
'user_models' => $userModels->toArray(),
'system_models' => $systemModels->toArray()
]);
This is where I'd like the 'json' column of my Model to be rendered as a string rather than cast to an array. Is there a reliable way to do that?
Inside your model you can define a custom attribute which is added when the model is serialized:
class YourModel extends Model
{
protected $appends = ['json_raw'];
public function getJsonRawAttribute()
{
return $this->attributes['json'];
// or return json_encode($this->attributes['json']);
}
}
And then when doing the toArray() you can do $userModels->makeHidden('json')->toArray(); to remove the casted field you do not want.
Suppose I have a Course model like this :
class Course extends Model
{
public $primaryKey = 'course_id';
protected $appends = ['teacher_name'];
public function getTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
}
public function teacher ()
{
return $this->belongsTo('App\User', 'teacher', 'user_id');
}
}
And in the other hand there is a User model like this :
class User extends Authenticatable
{
public $primaryKey = 'user_id';
protected $appends = ['full_name'];
public function getFullNameAttribute ()
{
return $this->name . ' ' . $this->family;
}
public function course ()
{
return $this->hasMany('App\Course', 'teacher', 'user_id');
}
}
As you can see there is a hasMany relationship between those.
There is an full_name accessor in User model.
Now I want to add a teacher_name accessor to Course model that uses it's teacher relations and gets full_name of teacher and appends to Course always.
In fact I want whenever call a Course model, it's related teacher name included like other properties.
But every time , when call a Course model , I got this error :
exception 'ErrorException' with message 'Trying to get property of non-object' in D:\wamp\www\lms-api\app\Course.php:166
That refers to this line of Course model :
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
I do not know how can I solve that and what is problem exactly.
Yikes some interesting answers here.
FYI to those coming after me- getFooAttribute() should return the data, and not modify the internal attributes array.
If you set a new value in the attributes array (that doesnt exist in this model's db schema) and then attempt to save the model, you'll hit a query exception.
It's worth reading up the laravel docs on attribute accessors/mutators for more info.
Furthermore, if you need to access a related object from within the model (like in an accessor) you ought to call $related = $this->getRelation('foo'); - note that if the relation isnt loaded (e.g., if you didnt fetch this object/collection with eager loaded relations) then $this->getRelation() could return null, but crucially if it is loaded, it won't run the same query(ies) to fetch the data again. So couple that with if (!$this->relationLoaded('foo')) { $this->loadRelation('foo'); }. You can then interact with the related object/collection as normal.
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
Should be
$this->attributes['teacher_name'] = $this->teacher->full_name;
First thing is that you want to reference the relationship, so loose the brackets (), and because the relationship is belongsTo, you will have one user / teacher returned. So you don't need the first().
We haven't seen your fields but probably you will have to change:
return $this->belongsTo('App\User', 'teacher', 'user_id');
to
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
where foreign_key and other_key are the primary keys that you need to make the join on.
Check this link from the documentation for reference:
https://laravel.com/docs/5.4/eloquent-relationships#one-to-many-inverse
the right way to do this is:
COURSE
public function setTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher->full_name;
}
100% working for me.
I have one to one relationship between Order and Shipment. I have to add the accessor of shipments table column from orders table.
function getOrderNoAttribute()
{
$appendText = "OR100";
if($this->orderShipment()->first()) {
$appendText = $this->orderShipment()->first()->is_shipping === 1 ? "ORE100" : "OR100";
}
return $appendText . $this->attributes['id'];
}
This error is only object data to array use or array data to object data use.
example::
$var->feild insted of $var[feild]
$var[feild] insted of $var->feild
You should use return for accessors . something like this :
public function getTeacherNameAttribute ()
{
return $this->teacher()->first()->full_name ?? '';
}
maybe a course hasn't teacher.
When creating an entry using create() - Why does it return a relationship of pilot_id table instead of just showing the value of pilot_id?
For example, in the repository class:
public function createFlight()
$flight = App\Flight::create([
'name' => 'Flight 10'
'pilot_id' => 4
]);
return $flight;
}
In the controller:
public function show()
{
$data = $this->flight->createFlight();
return $data
}
It would return json on the screen but it is not showing the relationship table (pilot) of pilot_id.
Try adding the following to your Flight model, like so. By default you need to tell Laravel to include any relationships.
protected $with = ['pilot'];
That will make it so everytime it includes the relationship. If this is not desirable, then you will want to load the relationships when you return the flight, like so.
return $flight->load(['pilot']);
It shows pilot_id is 4 because that's what its value is. Did you create a relationship on the Flight so that Laravel knows how to retrieve the model for Pilot? It should look something like this:
public function pilot()
{
return $this->hasOne('App\Pilot');
}
When you return a model directly from the controller, it invokes the toJson() method to convert the object to a string. If you want to append the contents of a related model you can do so by adding the relationship to the $with variable on the Flight model.
protected $with = ['pilot']
I am using Zizaco/entrust laravel package and suppose I want to fetch users with teacher role.
I want return selected users and their name and family combination like this :
[
1 => 'ali nasiri',
2 => 'majid basirati'
]
For that, I wrote this code :
$teachers =
Role::where('name', 'teacher')->first()->users()->lists('name', 'users.user_id');
But that returns like this :
{
"1": "ali",
"2": "majid"
}
Means that only name field was returned because we can define one field in first Parameter of lists method.
How Can I do that and what is best solution ?
In your user model, add a custom attribute(accessor):
<?php
use Zizaco\Entrust\Traits\EntrustUserTrait;
class User extends Eloquent
{
use EntrustUserTrait; // add this trait to your user model
...
protected $appends = ['full_name'];
//Setter of full name attribute
public function getFullNameAttribute()
{
return $this->name.' '.$this->surname;
}
}
Then use it to access the full name:
$teachers = User::whereHas('roles',function($q){
return $q->where('name','teacher');
})
->get()
->lists('full_name');