How to send specific fields in Laravel Resource - laravel

I need to send specific fields from the API resource
here is my User resource code
namespace App\Http\Resources;
use App\Models\MediaFile;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Storage;
class User extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
$attributes = $this->getAttributes();
unset($attributes['password']);
return [
'type' => 'users',
'attributes' => $attributes,
];
}
}
Below are my attributes
"attributes": {
"id": "1",
"email": "email",
"full_name": "Name",
"permission": "admin",
"security_key": "alpha",
"token": "encrypted token",
"two_factor_enabled": "true",
"created_at": "2020-05-15 08:56:50",
"updated_at": "2020-05-15 08:56:57",
}
I would like hide specific fields in specific routes. How can I implement this?

use makeHidden
$user = \App\Models\User::firstOrFail();
$user->makeHidden(['email', 'phone']);
return $user;

You can use two approaches:
$attributes = [
"id"=> "1",
"email" => "pera",
"full_name" => "Name",
"permission" => "admin",
"security_key" => "alpha",
"token" => "encrypted token",
"two_factor_enabled" => "true",
"created_at" => "2020-05-15 08:56:50",
"updated_at" => "2020-05-15 08:56:57",
];
PHP approach: unset($attributes['id'], $attributes['security_key']);
Laravel approach: Arr::except($attributes, ['id','security_key']);

Related

Array to string conversion using laravel 8

I am trying to insert data but unfortunately i am getting error Array to string conversion please help me how can i resolve that thanks.
please check error https://flareapp.io/share/x5Mznjem
return request
{
"_token": "3qLsIoNwWiOuze8aurlSQGqU4FsgttXgY6sMFYnw",
"icon": "0AKj2DRZii6yhJsoWKLNUbmOWKrXzOqKoFJTF4LI.jpg",
"name": "fdgdfg",
"person_name": "dfg",
"contact_number": "43543543",
"city": [
"2",
"3",
"4",
"5"
],
"location": [
"1",
"3",
"4"
],
"address": "A-232 Gulshan-e-hadeed ph 2"
}
controller
public function store(Request $request)
{
// return $request->all();
$request->validate([
'name' => "required",
'icon' => 'nullable',
'person_name' => 'required',
'contact_number' => 'required',
]);
$agency = Agency::create($request->except('_token'));
foreach ($request->city as $key => $value) {
$agencyCityLocation = new AgencyCityLocation;
$agencyCityLocation->agency_id = $agency->id;
$agencyCityLocation->city_id = $value;
$agencyCityLocation->location_id = $request->location;
$agencyCityLocation->save();
}
return redirect()->route('agency');
}
Replace this
$agencyCityLocation->location_id = $request->location;
By
$agencyCityLocation->location_id = $request->location[$key]
The issue is this line:
$agencyCityLocation->location_id = $request->location;
As you wrote $request->location is an array...
"location": [
"1",
"3",
"4"
],
...and I assume, that in $agencyCityLocation->location_id only one string is expected and not an array.
One solution would be to iterate through the locations as well (as you do with the cities), but actually we don't know how you want to save your data into the database. Do you want one DB entry for each city - location combination or is the city combined with the location?

laravel pass array see object

I'm stuck and probably missing something really obvious.. but..
I'm trying to pass an array of roles via jwt to my SPA (not a jwt question - that bit works fine)
I get my list of role names via
$roles = $this->roles->pluck('title')->toArray();
the roles function is
public function roles()
{
return $this->belongsToMany(Role::class);
}
in laravel this works fine and logging $roles out I see ["Admin"]
on the SPA response, however, I see the entire roles object joined to the user object (the user object is supposed to be passed over here) eg:
{
"user": {
"id": 1,
"name": "Admin",
"email": "example#example.com",
"email_verified_at": null,
"user_loggedin_state": null,
"user_login_time": null,
"user_login_hash": "",
"user_log_out_time": null,
"user_phone": "123456",
"user_job": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"team_id": 1,
"roles": [
{
"id": 1,
"title": "Admin",
"created_at": null,
"updated_at": null,
"deleted_at": null,
"pivot": {
"user_id": 1,
"role_id": 1
}
}
]
}
}
What I want is
{
"user": {
"id": 1,
"name": "Admin",
"email": "example#example.com",
"email_verified_at": null,
"user_loggedin_state": null,
"user_login_time": null,
"user_login_hash": "",
"user_log_out_time": null,
"user_phone": "123456",
"user_job": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"team_id": 1,
"roles": ["Admin"]
}
}
I definitely pass the array to jwt, not the object - to validate this I wrapped the $roles in a function
public function rolesArray()
{
$roles = $this->roles->pluck('title')->toArray();
Log::info($roles);
return $roles;
}
and the jwt fn
public function getJWTCustomClaims() {
return [
'roles' => $this->rolesArray(),
];
}
Use API Resources for getting your own outputs.
Run this command to make a new resource for getting users:
php artisan make:resource UserListResource
In App/Http/Resourcers open UserListResource.php file
Change toArray method to:
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'email_verified_at' => $this->email_verified_at,
'user_loggedin_state' => $this->user_loggedin_state,
'user_login_time' => $this->user_login_time,
'user_login_hash' => $this->user_login_hash,
'user_log_out_time' => $this->user_log_out_time,
'user_phone' => $this->user_phone,
'user_job' => $this->user_job,
'create_dates' => [
'created_at_human' => $this->created_at->diffForHumans(),
'created_at' => $this->created_at
],
'update_dates' => [
'updated_at_human' => $this->updated_at->diffForHumans(),
'updated_at' => $this->updated_at
],
'deleted_dates' => [
'deleted_at_human' => $this->deleted_at->diffForHumans(),
'deleted_at' => $this->deleted_at
],
'team_id' => $this->team_id
'roles' => new RolesShowResource($this->roles),
];
}
Then make Roles resources:
php artisan make:resource RolesShowResource
Open the RolesShowResource.php and do these changes:
public function toArray($request)
{
return [
'title' => $this->title,
];
}
So when you want to return objects try using the code below in fetching users:
return UserListResource::collection($users);
ok the bleeding obvious was that all this data is of course in the JWT payload..
I was confused since the moment I added stuff in the custom fields - Laravel sent the User object across in the response as well (which I want to find a way of stopping since its in the clear)

local query scope for the array attribute

I want to filter evaluations with a query scope, but in my model I have a fillable which is an array and it is from there that I want to filter
I have an attribute in my model that is a goal (array) where the roles assigned to that evaluation are saved for each evaluation.
protected $fillable = [
'id',
'title',
'description',
'editable_before',
'available_start',
'available_end',
'client_id',
'meta',
];
protected $casts = [
'meta' => 'array',
];
this is an evaluation that tests to show you
"id": 90,
"title": "inquiry Irvin Giovanni",
"description": "description encuesta irvin",
"instructions": null,
"editable_before": null,
"available_start": "2017-11-13 00:00:00",
"available_end": "2017-11-13 00:00:00",
"client_id": 9,
"meta": {
"userTypes": [
{
"role": "COACH",
"level": "KIN"
},
{
"role": "ADMIN",
"level": "SEC"
},
{
"role": "PROF",
"level": "SEC"
}
]
}
I want to filter the evaluation depending on the type of role that the query scope receives
idea:
public function scopeRole($query, $role)
{
return $query->where('meta.userTypes', '=', $role);
}
the idea is that in the parameter of the query scope function could pass "ADMIN", "PROF", "COACH" and I return the evaluations that have a certain parameter

Eloquent hasmany relationship issue

I am building an API with the lumen micro-framework using Eloquent for the database.
When i use this code to get the shoppinglists from a group, everything works
$group = Group::with(['shoppingLists' => function($query) {
}])->get();
It returns the following object
{
"id": "797799c2-6044-4a3a-a3a6-a71fbb17de68",
"name": "'t snackske",
"description": "best group ever",
"user_id": "7e74223a-ea06-46bf-ab1a-abb01b287e32",
"created_at": "2015-08-09 20:06:40",
"updated_at": "2015-08-09 20:06:40",
"shopping_lists": [
{
"id": "2423eb3c-7dab-4672-b382-895788dec6a0",
"name": "shop",
"description": "food",
"user_id": "7e74223a-ea06-46bf-ab1a-abb01b287e32",
"group_id": "797799c2-6044-4a3a-a3a6-a71fbb17de68",
"created_at": "2015-08-09 20:06:40",
"updated_at": "2015-08-09 20:06:40"
}
]
}
And when I check the queries that are logged i get the following queries:
{
"query": "select * from `groups`",
"bindings": [],
"time": 0.31
},
{
"query": "select * from `shopping_lists` where `shopping_lists`.`group_id` in (?)",
"bindings": [
"797799c2-6044-4a3a-a3a6-a71fbb17de68"
],
"time": 0.34
}
But when i try select specific fields for the shoppinglists this query returns no records
The query builder:
$group = Group::with(['shoppingLists' => function($query) {
$query->addSelect('id', 'name', 'description');
}])->get();
The response:
{
"id": "797799c2-6044-4a3a-a3a6-a71fbb17de68",
"name": "Group",
"description": "testgroup",
"user_id": "7e74223a-ea06-46bf-ab1a-abb01b287e32",
"created_at": "2015-08-09 20:06:40",
"updated_at": "2015-08-09 20:06:40",
"shopping_lists": []
}
The queries from the getQueryLog function
{
"query": "select * from `groups`",
"bindings": [],
"time": 0.23
},
{
"query": "select `id`, `name`, `description` from `shopping_lists` where `shopping_lists`.`group_id` in (?)",
"bindings": [
"797799c2-6044-4a3a-a3a6-a71fbb17de68"
],
"time": 0.32
}
When i copy and paste the last query from the query log in mysql i get the correct row. For some reason, eloquent doesn't show the data from the shopping_lists.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Group extends Model
{
protected $increments = false;
protected $fillable = [
'id',
'name',
'description',
'user_id'
];
protected $primaryKey = 'id';
/**
* Get shoppinglists from this group
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function shoppingLists()
{
return $this->hasMany('App\ShoppingList', 'group_id', 'id');
}
}
You may have to add the foreign key column to the addSelect() method for Laravel to do it's magic.
Group::with(['shoppingLists' => function($query) {
$query->addSelect('id', 'group_id', 'name', 'description');
}])->get();

Transform Laravel Eloquent result

When I execute this in my Controller
$data = User::with('teams')->find(2);
return response(['data' => $data]);
I get this as result
{
"id": 2,
"country_id": 1,
"first_name": "John",
"last_name": "Doe",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "2015-02-02 23:08:21",
"full_name": "John Doe",
"teams": [
{
"id": 1,
"name": "Helpdesk medewerker",
"description": ""
},
{
"id": 2,
"name": "Retentie",
"description": ""
}
]
}
Im not interested in the full teams data, but only interested in the teamNames of the user.
I've done this by adding this
$data->each(function($user) {
$user->team_names = $user->teams->lists('name');
unset($user->teams);
});
I was wondering if this is the correct way of modifying the Eloquent result.
You can use an attribute accessor for that. Add this to your model:
protected $hidden = ['teams']; // hide teams relation in JSON output
protected $appends = ['team_names']; // add custom attribute to JSON output
public function getTeamNamesAttribute(){
return $this->teams->lists('name');
}
To change hidden and appends dynamically you can use the setter methods:
$data = User::with('teams')->find(2);
$data->setHidden(['teams']);
Filter out the columns you want in your first build.
$data = User::with(['teams' => function($query){
return $query->select('name');
}])->find(2);
Will output:
{
...
"teams": [
{
"name": "Helpdesk medewerker"
},
{
"name": "Retentie"
}
]
}
You can also use the lists method.
$data = User::with(['teams' => function($query){
return $query->lists('name');
}])->find(2);
Will output:
{
...
"teams": ["Helpdesk medewerker", "Retentie"]
}

Resources