Additional attributes in Laravel all request - laravel

Good day.
For example, I have a model People with fields/attributes:
name
surname
and the model also has this method:
public function FullName()
{
return "{$this->name} {$this->surname}";
}
if I make the next request:
$p = $people->all();
I'll get collection with names and surnames as attributes
how i can make function execution for each in all() request?
What is the best practice?

Well, depends on what kind of result do you want.
OPTION A: Have name, surname and full_name in all the items of the array.
Eleazar's answer is correct, but a little bit incomplete.
1. Define a new accessor in your model.
This will define a new attribute in your model, just like name or surname. When the new attribute is defined, you can just do $user->full_name to get the attribute.
As the documentation says, to define an accessor you need to add a method in your model:
// The function name will need to start with `get`and ends with `Attribute`
// with the attribute field in-between in camel case.
public function getFullNameAttribute() // notice that the attribute name is in CamelCase.
{
return $this->name . ' ' . $this->surname;
}
2. Append the attribute to the model
This will make the attribute to be considered just like any other attribute, so whenever a record of the table is called, this attribute will be added to the record.
To accomplish this you'll need to add this new value in the protected $appends configuration property of the model, as you can see in the documentation:
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The accessors to append to the model's array form.
*
* #var array
*/
// notice that here the attribute name is in snake_case
protected $appends = ['full_name'];
}
3. Make sure that this attribute is visible
Notice this important part of the docs:
Once the attribute has been added to the appends list, it will be
included in both the model's array and JSON representations.
Attributes in the appends array will also respect the visible and
hidden settings configured on the model.
4. Query your data.
When doing the following:
$p = $people->all();
The $p array should have name, surname and also the new full_name attribute for each item.
OPTION B: Just get the full_name for specific purposes.
You can do the following when querying, iterate each result to get the attribute.
Now to do this you can iterate the collection with a foreach sentence, but given that whenever querying data, the array returned is always a Collection instance, so you simply use the map function:
$full_names = $p->map(function ($person) {
// This will only return the person full name,
// if you want additional information just custom this part.
return $person->fullname;
});
Using collection higher order messages it can be even shorter:
$full_names = $p->map->fullname;

I use the following:
public function getFullNameAttribute()
{
return "{$this['name']} {$this['lastname']}";
}
and then, I add it in appends:
class User extends Authenticatable {
protected $appends = ['fullname'];
}
What do you think?

In your model write a function to concatenate the name
public function getFullNameAttribute() {
return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name);
}
now you can call it this way
$user = User::find(1);
echo $user->full_name;
or
Auth::user()->full_name;

Related

How to compare two objects and get different columns in Laravel

I have two objects of the same record which I am getting from the database. One is before the update, and the other is after the update. I want to know the column values which are changed during this update query.
$before_update = DeliveryRun::find($id);
$before_update->name = $request->input('name');
$before_update->save();
$after_update = DeliveryRun::find($id);
compare($before_update, $after_update)
I would define a method on your DeliveryRun model which can be used to compare objects of the same type.
Lets say we want to be able to do something like $deliveryRun->compareTo($otherDeliveryRun). That seems like a nice fluid syntax and reads well in my opinion.
What we want to do is get the attributes and their values for the DeliveryRun we're calling compareTo on and then compare them against the attributes and values for the DeliveryRun we provide as an arguement to the compareTo method.
class DeliveryRun extends Model
{
public function compareTo(DeliveryRun $other)
{
$attributes = collect($this->getAttributes())
->map(function ($attribute, $key) use ($other) {
if ($attribute != $other->$key) {
return $key = $attribute;
}
})->reject(function ($attribute, $key) {
return !$attribute || in_array($key, ['id', 'created_at', 'updated_at']);
});
return $attributes;
}
}
The above gets the attributes for the current ($this) DeliveryRun, converts the array returned from getAttributes() to a collection so we can use the map() function and then loops over each attribute on the DeliveryRun model comparing the key and value of each against the $other DeliveryRun model provided.
The reject() call is used to remove attributes which are the same and some attribute keys which you might not be interested in leaving you just the attributes that have changed.
Update
I am saving object in other variable before update $before_update = $delivery_run; but after update $before_update variable I also gets updated
If I am understanding you correctly, you're still comparing the same object to itself. Try something like the following.
$before = clone $delivery_run; // use clone to force a copy
$delivery_run->name = 'something';
$delivery_run->save();
$difference = $before->compareTo($delivery_run);
I would consider using getChanges() as suggested by #Clément Baconnier if all you're doing is looking to get the changes of an object straight after the object has been saved/updated.

Laravel - How to change response format for specific fields

I've "Product" model.
And need to change some value formats for only responses.
For example;
I've "price" on database as decimal (11,2).
I want this as "1.000.000,00" format on response.
Or created_at field to "Carbon::parse($this->created_at)->toDayDatetimeString()"
Or I want to add 3 specific columns with my user attribute, on response. (is_allowed etc.)
How can this be possible on model?
How can I response like that?
You can use Mutator and Accessor to set format :
https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators
public function setDateAttribute($date) {
$this->attributes['date'] = Carbon::createFromFormat('Y-m-d', $date);
}
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
As a best practice in Laravel you can use Eloquent Resources: Eloquent Resources
It's basically a "transformer" between models data and API/Responses Output.
The only one thing to notice is that in the Resource files yout must specify all fields and relations (if needed) of the Model manually.
In the toArray() function you can modify the type of all data of your model as you prefer.
If not, you can access the new field by $model->my_custom_field (Laravel can resolve the name of the getter function automatically).
public function toArray($request)
{
$editedFieldValue = doSomething();
return [
'my_field' => $editedFieldValue,
'other_field' => '',
];
}
If you want to do that in Model, you can create customs fields:
class MuModel extends Model
{
protected $appends = ['my_custom_field'];
public function getMyCustomFiledAttribute(){
$newData = doSomething($this->existent_field);
return $newData;
}
}
The $appends variable add the new fields to all responses generated from the Model, as a normal database field.
P.S.: You can create a getAttribute() function for existent database attribute and return the value as you want!
For example: getCreatedAtAttribute()

What are Mutators and Accessors in Laravel

I am trying to understand accessors & mutators and why I need them. And my another ask is the middle part of an attribute's method for an example:
Accessor:
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
Mutator:
public function setFirstNameAttribute($value)
{
$this->attributes['first_name'] = strtolower($value);
}
Here, we can see getFirstNameAttribute and setFirstNameAttribute methods and I haven't been able to clear the middle part FirstName of them. I will really be grateful for a better explanation and kind cooperation.
Accessors create a "fake" attribute on the object which you can access as if it were a database column. So if your person has first_name and last_name attributes, you could write:
public function getFullNameAttribute()
{
return $this->first_name . " " . $this->last_name;
}
Then you can call $user->full_name and it will return the accessor. It converts the function name into a snake_case attribute, so getFooBarBazAttribute function would be accessible through $user->foo_bar_baz.
Mutator is a way to change data when it is set, so if you want all your emails in your database to be lowercase only, you could do:
public function setEmailAttribute($value)
{
$this->attributes['email'] = strtolower($value);
}
Then if you did $user->email = "EMAIL#GMAIL.com"; $user->save(); in the database it would set email#gmail.com
From the docs accessor and mutator both are public function in Laravel model for getting and setting model's attributes
An accessor will automatically be called by Eloquent when attempting to retrieve the value of the first_name attribute:
$fullName = $user->full_name;
It's for customizing a model's attributes or adding fake attributes
On the other hand mutator is for setting a real attribute of a model
Mutator will be automatically called when we attempt to set the value of the an attribute
Sometimes it happens that you have to modify the column value that was stored in a database. For Example, if you want to show column values that qualify some condition then you have to use Accessor and Mutator. where Accessor get value and Mutator set value.
By $append=[]; you can create any random column that fulfills your application demand.
here I am only telling about Accessor. In this code total_holiday_hours is my DB column name and i want to modify that value so that
i used $this->attributes['total_holiday_hours'] otherwise you can access this way
$this->total_holiday_hours.
function getTotalHolidayHoursAttribute()
{
if( $this->attributes['total_holiday_hours'] && $this->holiday_session == date('Y') )
{
return $this->attributes['total_holiday_hours'];
}
return 225;
}

laravel 5 model method not working

I have a table with rows with column contain string "this\dIs\dA\dString"
$callPlans = CustomerCallPlan::where('customer_id', $customer->id)->get();
I get the values like above and expected string 'thisXIsXAXString'
as you guess I replace '\d' with 'X'. to do this I use method below inside model class.
class CustomerCallPlan extends Model
{
protected $table = 'customer_callplan';
protected $fillable = [
'template',
'priority',
'customer_id',
'strip',
'add_number',
'actiontype',
'data'
];
public function getNumbertemplateAttribute() {
return str_replace('\d', 'X', $this->attributes['template']);
}
}
But somehow data comes to model without replaced.. what might be cause this ??
This is called an accessor and it'll automatically be called by Eloquent when attempting to retrieve the value. The method name should be the camel cased name of the column you wish to access, prepended by get and followed by Attribute, for example getColumnNameAttribute() will take the column colum_name.

How do I automatically set model properties when retrieved from the db?

In my route I have:
$products = Product::where('category',$category)->get();
return $products[0]->x;
How can I set up my Product model so that the route returns abcd1234?
This is what I currently have in my model:
public function __construct(){
$this->x = 'abcd1234';
}
You need an accessor.
Add this to your Product model:
public function getXAttribute()
{
return 'abcd1234';
}
Access it with:
$product = Product::where('category', $category)->first();
return $product->x;
Having a 1 character attribute name may cause a problem though, id recommend changing the X to something with more than one character in camel case for the accessor.

Resources