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
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 $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
];
});
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
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);
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?