Passing Multiple Parameters to Laravel Resource Collection - laravel

I am creating an API via apiResource with following code being passed to the resource collection
$coupons=Coupons:paginate(15);
$brand='brand1';
$brand_id='123';
return CouponResource::collection($coupons);
I am passing $coupons variable to the Resource Collection. But i want to pass $brand and $brand_id too.
How can I do that?

if you have created a relationship for brand you can use that
$coupons=Coupons::with('brand')->paginate(15);
or you can use appended parameters in your Coupons model
$appends =['brand_id','brand'];
and then
public function getBrandIdAttribute(){
return $this->brand()->id;
}
public function getBrandAttribute(){
return $this->brand()->name;
}

Related

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()

BadMethodCallException Call to undefined method App\User::map()

I want to add additional data to $user collection so can get the profile fields in the view
I have tried using $user['profileFields'] = $this->getProfileFields() and pass $user to the view using compatct or with and this is working fine.
DD
However, I have found some reference over the net saying I can extend using map but when I tried it is giving the following error
BadMethodCallException
Call to undefined method App\User::map()
So here is what I am trying to understand
Question:
Is the below code is wrong and won't work for what I am looking for and the first approach is the solution? Is there any
recommended method to add additional data to the $user collection?
public function show(User $user)
{
$user->map(function ($user){
$user['profileFields'] = $this->getProfileFields();
return $user;
});
return view('admin.user.show', compact('user'));
}
collection methods are works on the collection, here you're getting the object of user.
$user->profileFields = $user->getProfileFields();
return view('admin.user.show', compact('user'));
If the profileFields is in another table and having a foreign key with model ProfileField, then try to add a one to one relation to the User model.
Inside the User model, add a function
public function profileFields()
{
return $this->belongsTo('App\ProfileField', 'foreign_key','other_key');
}
This will give you the profileFields in every user when calling using eloquent.

Nested With() in Laravel Model Collection Return

I have a collection that is returned as such:
$scheduleLoads = Load::with('shipment','driver','tractor');
Now, my question is related to the with issue - is there a way to add the relationships of these relationships into my returned collection?
For example:
In the Load model I have the following relationship to shipment:
public function shipment(){
return $this->belongsTo(shipment::class, 'shipmentID');
}
In the shipment model I have the following relationship:
public function shiptoAccount(){
return $this->belongsTo('App\Customer', 'ship_to');
}
Is there a way to include the shiptoAccount return of the shipment associated with the Loads collections?
Use the "dot" syntax (documentation):
$scheduleLoads = Load::with('shipment.shiptoAccount', 'driver', 'tractor');

Additional attributes in Laravel all request

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;

Getting ID from url and using it in CRUD controller laravel

I need to add orders to existing customers. From my customers.show view I use the following to visit the order form.
href="{{action('OrderController#create', $customer['id'])}}
The link of the page looks like:
/orders/create?2f10f8a0-30b9-11e8-8711-dd477b141226
I've been using the following route::get to no avail to be able to use this ID in my resource controller for Orders
Route::get('orders/create/{id}', 'OrderController#create');
Basically need to be able to to something along the lines of below to be able to show customer details while displaying the create order form as well but getting stuck on best way to pass the id through for the current customer
public function create(){
$customer = Customer::find($id)
return view('orders.create', compact('customer'));
}
With Laravel, you just need to add the parameters you specified in the route as function parameters, like below:
public function create($id){
$customer = Customer::find($id)
return view('orders.create', compact('customer'));
}
You are not passing the $id argument in the create function.
Change it to:
public function create( $id ){
$customer = Customer::find($id)
return view('orders.create', compact('customer'));
}

Resources