I have made all Relationships and they work. I just wanted to add it, to my API with this code
$devices = Device::with(['Devicemodel' => function($query)
{
$query->with(['Manufacture', 'Devicetype']);
}])
Because Device has a relationship with Devicemodel. This works. And Devicemodel has a relationship with Manufacture and Devicetype. But i get returned NULL. Why?
EDIT:
I forgot to tell, i have a resource, and i return this
public function toArray($request)
{
//return parent::toArray($request);
return [
'id' => $this->id,
'devicetype' => $this->devicetype,
'value1' => $this->value1,
'value2' => $this->value2,
'value3' => $this->value3,
'manufacture' => $this->manufacture,
'devicemodel' => $this->devicemodel,
'remark' => $this->remark
];
}
if i do only return parent::toArray($request); it works.
Related
I use laravel 8 & have 3 table:
Products, ProductPrice & ProductsPublisher:
this is my Products model for this relationship:
public function lastPrice(){
return $this->hasMany(ProductPrice::class)->where('status','active')->orderBy('created_at','DESC')->distinct('publisher_id');
}
and this is my productsPrice model for publisher relationship:
public function getPublisher(){
return $this->belongsTo(ProductsPublisher::class,'publisher_id');
}
now, i want to use laravel resource for my api, i wrote products resource:
public function toArray($request)
{
return [
'id' => $this->id,
'price' => lastPrice::make($this->lastPrice),
'status' => $this->status,
'slug' => $this->slug,
'title' => $this->title,
'description' => $this->description,
'txt' => $this->txt,
'lang' => $this->lang,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
but in lastPrice resource, when i wrote like this:
return [
'id' => $this->id,
'main_price' => $this->main_price
];
it give me this error:
Property [id] does not exist on this collection instance.
when i use this code:
return parent::toArray($request);
get response but because i need to use another relationship in my lastPirce for publishers, i cant use that code and should return separately my data.
What i should to do?
thanks
Edit 1:
this is my Controller Code:
$products = Product::where('id',$id)->where('slug',$slug)->where('status','confirm')->first();
if(!$products){
return $this->sendError('Post does not exist.');
}else{
return $this->sendResponse(new \App\Http\Resources\Products\Products($products), 'Posts fetched.');
}
and this is sendResponse & sendError:
public function sendResponse($result, $message)
{
$response = [
'success' => true,
'data' => $result,
'message' => $message,
];
return response()->json($response, 200);
}
public function sendError($error, $errorMessages = [], $code = 404)
{
$response = [
'success' => false,
'message' => $error,
];
if(!empty($errorMessages)){
$response['data'] = $errorMessages;
}
return response()->json($response, $code);
}
thanks.
Edit 2:
i change my lastPrice Resource toArray function to this and my problem solved, but i think this isn't a clean way, any better idea?
$old_data = parent::toArray($request);
$co = 0;
$new_data = [];
foreach ($old_data as $index){
$publisher_data = Cache::remember('publisher'.$index['publisher_id'], env('CACHE_TIME_LONG') , function () use ($index) {
return ProductsPublisher::where('id' , $index['publisher_id'])->first();
});
$new_data[$co]['main_prices'] = $index['main_price'];
$new_data[$co]['off_prices'] = $index['off_price'];
$new_data[$co]['publisher'] = SinglePublisher::make($publisher_data);
$new_data[$co]['created_at'] = $index['created_at'];
$co++;
}
return $new_data;
I'm developing an API with Laravel. In one of the endpoint I'm accessing, some fields are showing a null value, but it should have some information.
Note the "addicionais_descricao" and "valor" fields, both always come with null values when I include them in the attributeitems array, but if I leave it at the initial level, the data is presented, but it doesn't solve my case, because I need this information with the attribute items:
enter image description here
This is where the endpoint calls, I make the query in the "Attribute" table, which has a relationship with the "Attributeitems" table, while the "attributeitems" table is linked to "Attribute" and "product".
public function show($id)
{
$atributos = Atributo::query('atributo')
->select(
'atributo.id',
'atributo.atrdescricao',
'atributoitens.atributo_id',
'atributoitens.produto_id',
'produto.prodescricao',
'produto.provalor'
)
->leftJoin('atributoitens', 'atributo.id', '=', 'atributoitens.atributo_id')
->leftJoin('produto', 'produto.id', '=', 'atributoitens.produto_id')
->where('atributo.id', '=', $id)
->get()->unique('id');
return AtributoResource::collection($atributos);
}
Resource Atributo:
public function toArray($request)
{
return [
'id' => $this->id,
'descricao' => $this->atrdescricao,
'atributoitens' => AtributoitensResource::collection($this->atributoitens),
];
}
Resource Atributo Itens:
public function toArray($request)
{
return [
'id' => $this->id,
'atributo' => $this->atributo_id,
'produtos' => $this->produto_id,
'adicionais_descricao' => $this->prodescricao,
'valor' => $this->provalor
];
}
What is the correct procedure for this situation?
Take this example as a reference :
Controller
$data = $shop->products()
->whereStatus(true)
->where('product_shop.active', true)
->where('product_shop.quantity', '>=', $this->min_product_qty)
->paginate(50);
return (new ProductCollection($data))
->response()
->setStatusCode(200);
ProductCollection
public function toArray($request)
{
return [
'data' => $this->collection
->map(function($product) use ($request) {
return (new ProductResource($product))->toArray($request);
}),
'brand' => $this->when($request->brand, $request->brand)
];
}
ProductResource
public function toArray($request)
{
return [
'type' => 'product',
'id' => (string) $this->id,
'attributes' => [
'uuid' => $this->uuid,
'name' => $this->name,
'slug' => $this->slug,
'description' => $this->description,
'thumb_path' => $this->thumb_path,
'cover_path' => $this->cover_path,
],
'relationships' => [
'brand' => $this->brand
]
];
}
Something like this should help you do what you want. I cant exactly do it for you. by the way why you are not using Eloquent, something like
Attribute::where(...)->with(['relation_1', 'products'])->get();
public function toArray($request)
{
return [
'id' => $this->id,
'attributes' => [...],
'products' => $this->collection
->map(function($this->product) use ($request) {
return (new ProductResource($product))->toArray($request);
}),
];
}
Hi I'm trying to get data and mapping it in resources, but somehow I'm getting error ErrorException: Trying to get property name of non-object. I'm already define the relationship in models, but somehow I'm still getting the error.
User Models
public function shop()
{
return $this->hasOne(Shop::class);
}
Shop Models
public function user()
{
return $this->belongsTo(User::class);
}
And I'm using the resources (ShopCollection) in controller when getting data like this
public function index()
{
return new ShopCollection(Shop::all());
}
This is how I mapping the data in ShopCollection
public function toArray($request)
{
return [
'data' => $this->collection->map(function($data) {
return [
'id_toko' => $data->id,
'name' => $data->name,
'user' => [
'name' => $data->user->name,
'email' => $data->user->email,
'avatar' => $data->user->avatar,
'avatar_original' => $data->user->avatar_original
],
'logo' => api_asset($data->logo),
...
];
})
];
}
Sorry about my english and thank you for your kind help
ErrorException: Trying to get property name of non-object
This very common error is also pretty simple to debug: somewhere, one of your variables is null but you are still trying to use one of it's property.
It is very likely, from what we can see in your code, that $data->user returns null at some point.
It's hard to tell when and where since you didn't provided the line, but I'm confident that's the case.
Since your resource is a Collection, Laravel iterates through it.
You can catch the problematic entry by adding:
public function toArray($request)
{
return [
'data' => $this->collection->map(function($data) {
if($data->user == null){
dd($data);
};
return [
'id_toko' => $data->id,
'name' => $data->name,
'user' => [
'name' => $data->user->name,
'email' => $data->user->email,
'avatar' => $data->user->avatar,
'avatar_original' => $data->user->avatar_original
],
'logo' => api_asset($data->logo),
...
];
})
];
}
This is answer assumes the problem is from $data->user. If that's not the case, edit your question with the full error stack trace.
Thanks to #toyi answer I can found out what is the problem.
The reason why I got the error is because some of shops have null user_id. So to handle it I check it first before using it.
This is the code:
public function toArray($request)
{
return [
'data' => $this->collection->map(function($data) {
$user = $data->user ? [
'name' => $data->user->name,
'email' => $data->user->email,
'avatar' => $data->user->avatar,
'avatar_original' => $data->user->avatar_original
] : [];
return [
'id_toko' => $data->id,
'name' => $data->name,
'user' => $user,
'logo' => api_asset($data->logo),
...
I am trying to get comment and it's replies in laravel api,I tried following way and faced to this error, how can I solve it?
this is my controller:
public function postSinglePage(Request $request)
{
$post_id=$request->get('post_id');
$post = Post::where('id',$post_id)->where('status', '=', 1)->get();
return response([
"posts" => GetPostsSinglePageData::collection($post),
]);
}
and this is my resource collection to get post and it's comments:
public function toArray($request)
{
return [
'post_id' => $this->id,
"name" => $this->post_title,
"excerpt" => $this->post_excerpt,
"thumbnail" => $this->getFirstMediaUrl("images"),
"logo" => $this->getFirstMediaUrl("images"),
'comment_count'=>getCommentCount($this->id),
'comments'=> new CommentCollection(Comment::select('*')->where('post_id',$this->id)),
"like" => DB::table("like_tb")->select('like_dislike')
->where("type_like",'=','post')
->where('related_id',$this->id)
->get(),
"share" => DB::table("share_tb")->select("share_number")
->where('type','=','post')
->where("related_id",$this->id)
->get(),
];
}
this is comment collection:
public function toArray($request)
{
return [
'commentId'=>$this->id,
'courseId'=>$this->post_id,
'commentDate'=>$this->date,
'commentText'=>$this->body,
'userId'=>$this->user_id,
'replays'=>ReplyCommentCollection::collection(\App\Models\Comment\ReplyComment::where('comment_id',$this->id)->get()),
'users'=>UserInfoCollection::collection(User::where('id',$this->user_id)->get()),
];
}
$this->id not work in inner other function you must write like this:
public function toArray($request)
{
$comments=Comment::select('*')->where('post_id',$this->id)->get();
$commentCollection= CommentCollection::collection($comments);
return [
'post_id' => $this->id,
"name" => $this->post_title,
"excerpt" => $this->post_excerpt,
"thumbnail" => $this->getFirstMediaUrl("images"),
"logo" => $this->getFirstMediaUrl("images"),
'comment_count'=>getCommentCount($this->id),
'comments'=> $commentCollection,
"like" => DB::table("like_tb")->select('like_dislike')
->where("type_like",'=','post')
->where('related_id',$this->id)
->get(),
"share" => DB::table("share_tb")->select("share_number")
->where('type','=','post')
->where("related_id",$this->id)
->get(),
];
}
So I've been trying to get a second level relation out of my "CategoryResource" but it's not working, here is some of my code :
First, My model :
public function children()
{
return $this->hasMany(Category::class, 'parent_id', 'id');
}
public function sub_children()
{
return $this->hasMany(Category::class, 'parent_id');
}
and then the "CategoryResource" :
$data = [
'id' => $this->id,
'parent_id' => $this->parent_id,
'order' => $this->order,
'name' => $this->name,
'slug' => $this->slug,
'childs' => CategoryResource::collection($this->whenLoaded('children') && $this->whenLoaded('children')),
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
];
My Controller
return CategoryResource::collection(Category::where('parent_id',null)->with('children.sub_children')->get());
Is there anyway i can retrieve my nested relation through laravel resource ?
You could use with function in the relationship. It would be something like this:
public function children()
{
return $this->hasMany(Category::class, 'parent_id', 'id')
->with('children');
}
It is going to load the children and then "subChildren" as relations of the first object.
So, you are going to load it as:
$children = $originalObject->children;
foreach ($children as $c) {
$subChildren = $c->children;
}
Check if this works for your problem.