How to use alias in laravel eager loading - laravel

I want to use alias with laravel eager loading. This is my query
Message::whereIn('conversation_id',$msgs)
->where('deleted', '!=', $userId)
->with(array('last_sender' =>function($query) use ($userId){
$query->where('id','!=', $userId);
$query->select('id', 'userName', 'profilePic','firstName', 'lastName');
}))
->with(array('last_reciever' =>function($query) use ($userId){
$query->where('id','!=', $userId);
$query->select('id', 'userName', 'profilePic','firstName', 'lastName');
}))
->orderBy('conversation_id', 'desc')
->orderBy('id', 'desc')
->groupBy('conversation_id')
->get();
This query returns user object either as last_sender and last_reciever stays null or last_reciever and last_sender stays null.
This is the result object that this query returns
{
"data": [
{
"id": 85,
"conversation_id": 18,
"last_reciever": null,
"last_sender": {
"id": 39,
"userName": "df76236sd",
"profilePic": "aFHZmeMHQ6nd3Ll3nzCqYEw2CTBsun3f1hxm3yKc.jpeg",
"firstName": "sadek ",
"lastName": "sdfsd"
},
"msg": "abe sala",
"attachment": null,
"deleted": 0,
"seen": 0,
"created_at": "2017-08-19 02:24:05",
"updated_at": "2017-08-19 02:24:05"
},
{
"id": 80,
"conversation_id": 16,
"last_reciever": {
"id": 39,
"userName": "df76236sd",
"profilePic": "aFHZmeMHQ6nd3Ll3nzCqYEw2CTBsun3f1hxm3yKc.jpeg",
"firstName": "sadek ",
"lastName": "sdfsd"
},
"last_sender": null,
"msg": "now should be working just fine",
"attachment": null,
"deleted": 0,
"seen": 1,
"created_at": "2017-08-19 02:19:34",
"updated_at": "2017-08-19 02:19:34"
}
]
}
What I am trying to do is replace the both last_sender and last_reciever with a custom name oponent . For this I tried to use something like this
Message::whereIn('conversation_id',$msgs)
->where('deleted', '!=', $userId)
->with(array('last_sender as oponent' =>function($query) use ($userId){
$query->where('id','!=', $userId);
$query->select('id', 'userName', 'profilePic','firstName', 'lastName');
}))
->with(array('last_reciever as oponent' =>function($query) use ($userId){
$query->where('id','!=', $userId);
$query->select('id', 'userName', 'profilePic','firstName', 'lastName');
}))
->orderBy('conversation_id', 'desc')
->orderBy('id', 'desc')
->groupBy('conversation_id')
->get();
And it doesn't work. Is there any other ways to achieve this?
Thank you.

You could either override the values in the model using toArray()
public function toArray()
{
return [
'oponent' => $this->last_sender. " " .$this->last_reciever,
];
}
Or use laravel api resources
class User extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
If you want to return a collection using laravel api resources
Route::get('/user', function () {
return UserResource::collection(User::all());
});
https://laravel.com/docs/5.6/eloquent-resources

Related

How to pull actual values from foreign id when an array of ids is returned?

I am making an e-commerce site where the person can make an offer for the product. And I want to display all the offers on product at a place where I get the product.After that want to get the information about the user who made the offer and the parent offer in the same query.
I am getting the product like this
`public function show(Product $product)
{
// return response()->json($product);
return new SingleProductResource($product);
}`
The SingleProductResource returns the following
`public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'type' => $this->type,
'images' => $this->images,
'status' => $this->status,
'owner' => $this->user,
'offers' => $this->offers,
];
}`
Offers returns an array like this
`"offers": [
{
"id": 2,
"user_id": null,
"product_id": 1,
"offer_amount": "3",
"parent_id": 2,
"created_at": "2022-11-12T07:54:10.000000Z",
"updated_at": "2022-11-12T07:54:10.000000Z"
},
{
"id": 4,
"user_id": 1,
"product_id": 1,
"offer_amount": "3",
"parent_id": 2,
"created_at": "2022-11-12T08:01:29.000000Z",
"updated_at": "2022-11-12T08:01:29.000000Z"
},
{
"id": 5,
"user_id": null,
"product_id": 1,
"offer_amount": "3",
"parent_id": null,
"created_at": "2022-11-12T08:01:56.000000Z",
"updated_at": "2022-11-12T08:01:56.000000Z"
}
]`
But I want to get the user information directly in this query.
I cannot do this(see comment below) inside the resource as $this->offers returns an array.
`return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'type' => $this->type,
'images' => $this->images,
'status' => $this->status,
'creator' => $this->user,
'offers' => $this->offers->user, //this
];`
You will need to trim your $product in some way. For example
$products = Product::leftJoin('offers', 'products.id', 'offers.product_id')
->where('user_id')
->where('products.id', $product['id'])
->get();
return new SingleProductResource::collection($products);

return user model with eager loading laravel

return $data =InteractiveSession::with('messages.user')->where('exercise_id',$exercise->id)->first();
This code will return data like below
{
"id": 1,
"exercise_id": 48,
"messages": [
{
"id": 1,
"from_user": 69,
"message": "Hi",
"interactive_session_id": 1,
"user": {
"id": 69,
"first_name": "Jobin"
}
}
]}
how can i return data like below??
{
"id": 1,
"exercise_id": 48,
"messages": [
{
"id": 1,
"from_user":{
"id": 69,
"first_name": "Jobin"
},
"message": "Hi",
"interactive_session_id": 1,
}
]}
i have tables interactivesession,message,users, using hasmany relation
You can create a relation for from_user to the user model, and then do return $data = InteractiveSession::with(['messages.user', 'fromUser'])->where('exercise_id',$exercise->id)->first(); (remember fromUser should be your relation name)
Try this:
$data = InteractiveSession::with('messages.user')->where('exercise_id',$exercise->id)->first();
$data->transform(function($record) {
$messages = $record->messages->transform(function($message) {
'id' => $message->id,
'from_user' => [
'id' => $message->user->id,
'first_name' => $message->user->first_name
],
'message' => $message->message,
'interactive_session_id' => $message->interactive_session_id
});
return [
'id' => $record->id,
'exercise_id' => $record->exercise_id,
'messages' => $messages
];
});

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

returning response with json in laravel api removes the collection pagination links

i'm using laravel for webservice. i want to return a collection like this:
return response()->json([data => $data]);
and i'm using laravel api resouces for transforming the collection. this is my resource:
class Item extends JsonResource
public function toArray($request)
{
return [
'id' => $this->id,
'name'=> $this->name,
'city_dependent' => $this->city_dependent,
];
}
when i pass a collection to the resource like:
$items = Item::where('active' , 1)->paginate(10);
$data = Item::collection($items);
everything works good. if i return the $data, the pagination links and meta are returning and there is no problem.
"links": {
"first": "http://127.0.0.1:8000/api/category/items?page=1",
"last": "http://127.0.0.1:8000/api/category/items?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://127.0.0.1:8000/api/category/items",
"per_page": 10,
"to": 3,
"total": 3
}
but if i return the data with response()->json() like below, all data about "meta" and "links" are remove! and everything else is ok.
return response()->json([
'result' =>true,
'data' => $data
]);
why the pagination data and links are removed from the data? is there anything that i missed?

Resources