Laravel Spatie Permissions - user and role relation get only id and name - laravel

I'm using Laravel Spatie Permissions to manage roles and permissions in my app. I'm traing to retrieve only Role id and name in the relation between users and roles. My UserResource looks like this:
class UserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'surname' => $this->surname,
'email' => $this->email,
'inactive' => $this->inactive,
'roles' => $this->roles
];
}
}
And the json looks like this:
"data": [
{
"id": 1,
"name": "Admin",
"surname": "Sudo",
"email": "admin#sudo.com",
"inactive": 0,
"roles": [
{
"id": 1,
"name": "Admin",
"guard_name": "web",
"created_at": "2020-05-28 23:18:58",
"updated_at": "2020-05-28 23:18:58",
"pivot": {
"model_id": 1,
"role_id": 1,
"model_type": "App\\User"
}
}
]
},
]
What I really need it's a json like this:
"data": [
{
"id": 1,
"name": "Admin",
"surname": "Sudo",
"email": "admin#sudo.com",
"inactive": 0,
"roles": [
{
"id": 1,
"name": "Admin",
},
{
"id": 2,
"name": "Default",
},
{
"id": 3,
"name": "Guest",
}
]
},
]
I really don't know how to modified my models relations or the parameter $this->roles (in UserResources) to could get this json.

The easiest solution was using a map function:
'roles' => $this->roles->map(function($role){
return [
'id' => $role['id'],
'name' => $role['name']
];
})

You can create a RoleResource:
class RoleResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
];
}
}
And use it on your UserResource:
class UserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'surname' => $this->surname,
'email' => $this->email,
'inactive' => $this->inactive,
'roles' => RoleResource::collection($this->roles),
];
}
}

Related

Change model return array structure

When i request my model::all() i get the data like this:
{
"id": 2,
"user_id": 1,
"type_of_numbers": "mobile",
"pcd_accepted": null,
"first_possible_date": "2021-03-02 15:10:50",
"email": "example#customer.nl",
"customer_id": "Seb",
"customer_initials": "der",
"customer_prefix": "seb",
"customer_last_name": "er",
"customer_company": "seb b.v",
"customer_street": "fds fds fdse",
"customer_house_number": "12",
"customer_house_number_suffix": "A",
"customer_zip_code": "1000ff",
"customer_city": "test",
"status": "blocked",
"status_message": null,
"delayed_answer_reason": null,
"delayed_answer_date": null,
"created_at": "2021-03-02T13:01:15.000000Z",
"updated_at": "2021-03-02T13:02:15.000000Z"
},
How can i get this?
{
"id": 2,
"user_id": 1,
"type_of_numbers": "mobile",
"pcd_accepted": null,
"first_possible_date": "2021-03-02 15:10:50",
"email": "example#customer.nl",
"customer: {
"id": "Seb",
"initials": "der",
"prefix": "seb",
"last_name": "er",
"company": "seb b.v",
"street": "fds fds fdse",
"house_number": "12",
"house_number_suffix": "A",
"zip_code": "1000ff",
"city": "test"
},
"status": "blocked",
"status_message": null,
"delayed_answer_reason": null,
"delayed_answer_date": null,
"created_at": "2021-03-02T13:01:15.000000Z",
"updated_at": "2021-03-02T13:02:15.000000Z"
},
Is it possible to do this in the model? I tried using JsonResource but this works only if i pass 1 array and not a bulk.
JsonResource code:
class JsonResponse extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'note' => $this->note,
'planned_completion_date' => $this->planned_completion_date,
'pcd_accepted' => $this->pcd_accpeted,
'email' => $this->email,
'customer' => [
'id' => $this->customer_id,
'initials' => $this->customer_initials,
'prefix' => $this->customer_prefix,
'last_name' => $this->customer_last_name,
'company' => $this->customer_company,
'street' => $this->customer_street,
'house_number' => $this->customer_house_number,
'house_number_suffix' => $this->customer_house_number_suffix,
'zip_code' => $this->customer_zip_code,
'city' => $this->customer_city
],
'status' => $this->status,
'status_message' => $this->status_message,
'delayed_answer_reason' => $this->delayed_answer_reason,
'delayed_answer_date' => $this->delayed_answer_date,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at
];
}
}
Maybe an ideea would be to try resource collections https://laravel.com/docs/8.x/eloquent-resources#resource-collections

Laravel API Resource not returning data with one to many relationship

In my DoctorController, I have show method like below -
public function show(Doctor $doctor){
DoctorResource::withoutWrapping();
return new DoctorResource($doctor->load('expertises'));
}
In my DoctorResource, if I do
public function toArray($request){
return parent::toArray($request);
}
It returns -
{
"id": 1,
"name": "John Doe",
"mobile": "1234567890",
"email": null,
"avatar": null,
"bio": "Lorem Ipsum 2",
"email_verified_at": null,
"mobile_verified_at": null,
"is_account_verified": 0,
"account_status": "Active",
"created_at": "2020-12-03T07:45:07.000000Z",
"updated_at": "2020-12-03T10:49:30.000000Z",
"expertises": [
{
"id": 1,
"expertise": "ABC",
"created_at": null,
"updated_at": null,
"pivot": {
"doctor_id": 1,
"expertise_id": 1,
"created_at": "2020-12-03T10:49:29.000000Z",
"updated_at": "2020-12-03T10:49:29.000000Z"
}
},
{
"id": 2,
"expertise": "XYZ",
"created_at": null,
"updated_at": null,
"pivot": {
"doctor_id": 1,
"expertise_id": 2,
"created_at": "2020-12-03T10:49:29.000000Z",
"updated_at": "2020-12-03T10:49:29.000000Z"
}
}
]
}
But I want to return certain fields from my DoctorResource, So I did this but it is giving me an error. Exception: Property [expertise] does not exist on this collection instance.
public function toArray($request){
return [
'id' => $this->id,
'name' => $this->name,
'mobile' => $this->mobile,
'email' => $this->email,
'avatar' => $this->avatar,
'bio' => $this->bio,
'expertises' => [
'name' => $this->expertises->expertise
]
];
}
you have define another Json Resource to do that:
first you can retrive the model and add keys and values based on each model properties like :
public function toArray($request){
return [
'id' => $this->id,
'name' => $this->name,
'mobile' => $this->mobile,
'email' => $this->email,
'avatar' => $this->avatar,
'bio' => $this->bio,
'expertises' => ExpertiesResource::collection($this->experties);
];
}
and you have to define Resource Collection as Follow:
class ExpertiesResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
"id" => $this->id,
"exp" => $this->exp,
.....
];
}
}
when your JsonResource has an Array of Object(Resource), you have to Define That Resource and make use of it like use App\Http\Resources\ExpertiesResource

How we can get data into api resource when we have morphMany relation

I dont want a json response. I want to use api Resource for this output. Can anyone help me regarding this. Help will be highly appriciated.
This is News Model
<?php
namespace Modules\Newsletter\Entities;
use Brexis\LaravelWorkflow\Traits\WorkflowTrait;
//use Hyn\Tenancy\Abstracts\TenantModel as TenancyModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class News extends Model {
use WorkflowTrait;
protected $table = 'news_info';
protected $fillable = [
'title', 'header', 'description', 'status', 'created_by', 'media_url', 'media_thumbnail',
];
public function reviews() {
return $this->morphMany(NewsReview::class, 'reviewable');
}
public function reviewsCountByCategory() {
return $this->morphMany(NewsReview::class, 'reviewable')
->select(
'reviewable_id',
DB::raw("COUNT(CASE WHEN review_reaction=1 THEN 1 ELSE NULL END) as review_bad"),
DB::raw("COUNT(CASE WHEN review_reaction=2 THEN 1 ELSE NULL END) as review_average"),
DB::raw("COUNT(CASE WHEN review_reaction=3 THEN 1 ELSE NULL END) as review_good")
)
->groupBy('reviewable_id');
}
}
This is Review model
<?php
namespace Modules\Newsletter\Entities;
use App\User;
//use Hyn\Tenancy\Abstracts\TenantModel as TenancyModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class NewsReview extends Model {
use SoftDeletes;
protected $fillable = [
'review_text',
'review_reaction',
'is_visible',
'reviewed_by',
'reviewable_id',
'reviewable_type'
];
public function reviewable() {
return $this->morphTo();
}
public function news(){
return $this->belongsTo(News::class);
}
public function reviewer() {
return $this->hasOne(User::class, 'id', 'reviewed_by');
}
}
This is my function inside Controller
public function searchNews(Request $request,$title) {
try {
$result=News::with('reviewsCountByCategory')->where('status', 'pre_validation')
->where('title', 'LIKE',"%$title%")
->orderBy('title', 'asc')->paginate(3);
return response()->json(['status' => TRUE, 'data' => $result], 200);
} catch (\Exception $e) {
return response()->json(['status' => FALSE, 'msg' => 'Internal Server Error','error' => $e->getMessage()], 500);
}
}
This is current response I am getting now
{
"status": true,
"data": {
"current_page": 1,
"data": [
{
"id": 8,
"title": "AndraPradesh CM Tested Positive",
"header": "Todays Headline",
"description": "Corona Virus spreds Globaly",
"status": "pre_validation",
"created_by": 2,
"media_type": null,
"media_url": "www.abc.com",
"media_thumbnail": null,
"is_send_with_newsletter": 0,
"created_at": "2020-07-24 11:28:34",
"updated_at": "2020-07-24 11:28:34",
"deleted_at": null,
"reviews_count_by_category": []
},
{
"id": 2,
"title": "Anurag singh",
"header": "Todayfdfdf",
"description": "Hoell",
"status": "pre_validation",
"created_by": 1,
"media_type": null,
"media_url": "www.abc.com",
"media_thumbnail": null,
"is_send_with_newsletter": 0,
"created_at": "2020-07-22 11:13:50",
"updated_at": "2020-07-22 11:13:50",
"deleted_at": null,
"reviews_count_by_category": [
{
"reviewable_id": 2,
"review_bad": 0,
"review_average": 1,
"review_good": 0
}
]
},
{
"id": 9,
"title": "Chandigarh is famous for its natural Beauty",
"header": "Todays Headline",
"description": "Corona Virus spreds Globaly",
"status": "pre_validation",
"created_by": 2,
"media_type": null,
"media_url": "www.abc.com",
"media_thumbnail": null,
"is_send_with_newsletter": 0,
"created_at": "2020-07-24 11:29:18",
"updated_at": "2020-07-24 11:29:18",
"deleted_at": null,
"reviews_count_by_category": []
}
],
This is my Review resource
<?php
namespace Modules\Newsletter\Transformers;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\Resource;
class ReviewResource extends Resource {
/**
* #param Request
* #return array
*/
public function toArray($request) {
return [
'review_id' => $this->id,
'review_text' => $this->review_text,
'review_reaction' => new NewsResource($this->reviewsCountByCategory),
'is_visible' => $this->is_visible,
'reviewed_by' => new UserResource($this->reviewer),
'news' => new NewsResource($this->reviews),
];
}
}
This is my NewsResource
<?php
namespace Modules\Newsletter\Transformers;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\Resource;
class NewsResource extends Resource {
/**
* #param Request
* #return array
*/
public function toArray($request) {
return [
'news_id' => $this->id,
'title' => $this->title,
'header' => $this->header,
'description' => $this->description,
'status' => $this->status,
'media_url' => $this->media_url,
'media_thumbnail' => $this->media_thumbnail,
];
}
}
But I dont want a json response. I want to use api Resource for this output. Can anyone help me regarding this. Help will be highly appriciated.
Inside your function in the controller, instead of this
return response()->json(['status' => TRUE, 'data' => $result], 200);
NewsResource.php
public function toArray($request) {
$reviews = [];
foreach($this->reviews as $review){
array_push($reviews, [
'review_id' => $review->id,
'review_text' => $review->review_text,
'is_visible' => $review->is_visible,
]);
}
return [
'news_id' => $this->id,
'title' => $this->title,
'header' => $this->header,
'description' => $this->description,
'status' => $this->status,
'media_url' => $this->media_url,
'media_thumbnail' => $this->media_thumbnail,
'reviews' => $reviews,
];
}
Use the NewsResource
return NewsResource::collection($result);

Laravel API Resource Collection return specific fields from other resource

I am working on an api that will be accessible via a mobile app.
I have defined resources and collections for respective endpoints. My problem is now is that I want to return different api json data based on what ever collection.
Here is an example
Provinces has cities and suburbs, so in json format I need to have
"data": [
{
"id": 1,
"name": "Eastern Cape",
"cities": [
{
"name": "Alice"
},
],
"suburbs": [
"name": "Suburb 1"
]
},
]
I want different data when the cities resource is called in news api collection
"data": [
{
"id": 1,
"name": "Eastern Cape",
"cities": [
{
"name": "Alice",
"municipality": "municipality name",
},
],
"suburbs": [
"name": "Suburb 1",
"ward_number": "ward 1"
]
},
]
This is an NewsResource Api
public function toArray($request)
{
// return parent::toArray($request);
return [
'id'=> $this->id,
'title' => $this->title,
'slug' => $this->slug,
'content' => $this->content,
'created_at' => $this->created_at,
'category_id' => $this->news_category_id,
'featured_image' => url($this->featured_image),
'author' => new UserResource($this->user),
'category' => new NewsCategoryResource($this->category), //Only category Name to be displayed
'municipality' => new MunicipalityResource($this->municipality), // Only Municipality Name to be displayed
'comments' => new NewsCommentResource($this->comments),
];
}
I don't really know what is your code structure, but hope this help for you
You may use different queries, for example
/** For the obvious resource calling */
return SomeResource::collection (SomeModel::with(['suburbs', 'cities'])
/** Other filter queries */
->get());
/** For the cities resource calling */
return SomeResource::collection (SomeModel::with(['suburbs:id,ward_number', 'cities:id,municipality'])
/** Other filter queries */
->get());
In your Resource class which you use for the cities/suburbs data, do it like so
return [
/** Some data which you need */
'municipality' => $this->when($this->municipality !== null, $this->municipality),
'ward_number' => $this->when($this->ward_number !== null, $this->ward_number),
];

How to set, Laravel Queue Payload format

How to set, Laravel Queue Payload format.
I don't want to change the source code.
source code:
File Path: vendor\laravel\framework\src\Illuminate\Queue\Queue.php
/**
* Create a payload for an object-based queue handler.
*
* #param mixed $job
* #return array
*/
protected function createObjectPayload($job)
{
return [
'displayName' => $this->getDisplayName($job),
'job' => 'Illuminate\Queue\CallQueuedHandler#call',
'maxTries' => $job->tries ?? null,
'timeout' => $job->timeout ?? null,
'timeoutAt' => $this->getJobExpiration($job),
'data' => [
'commandName' => get_class($job),
'command' => serialize(clone $job),
],
];
}
Queue data:
{
"displayName": "App\\Jobs\\SendReminderEmail",
"job": "Illuminate\\Queue\\CallQueuedHandler#call",
"maxTries": null,
"timeout": null,
"timeoutAt": null,
"data": {
"commandName": "App\\Jobs\\SendReminderEmail",
"command": "O:26:\"App\\Jobs\\SendReminderEmail\":8:{s:11:\"0000*0000username\";s:19:\"2017-12-29 07:05:53\";s:6:\"0000*0000job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:5:\"delay\";N;s:7:\"chained\";a:0:{}}"
}
}
But,i want this format:
{
"message": {
"Username": "test",
},
"messageType": [
"urn:message:App\\Jobs\\SendReminderEmail"
]
}

Resources