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(),
];
}
Related
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 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.
i'm working on a graphql API using Laravel GraphQL.
As shown in the documentation "Privacy" section, it should be possible to add callback function to a GraphQLType fields privacy attribute. The field is supposed to return null, when the callback returns false.
Similar to the example in the laravel graphql Docs, i've added a privacy callback like so:
public function fields(): array {
return [
'email' => [
'type' => Type::string(),
'description' => 'The email of user',
'privacy' => function(User $user): bool {
return $user->isMe();
}
],
];
}
It appears to me, that this callback function never gets called.
I read something about a possible requirement, that i should resolve my query using the $getSelectFields function to query the $fields manually $with the selected columns. But unfortunately the $select
public function resolve($root, $args, $context, ResolveInfo $info, Closure $getSelectFields) {
$fields = $getSelectFields();
$with = $fields->getRelations(); // empty array
$select = $fields->getSelect(); // empty array
return User::select($select)->with($with)->get();
}
In my case this does not make any difference.
In my query resolver i do as following:
public function resolve($root, $args, $context, ResolveInfo $info, Closure $getSelectFields) {
/** #var SelectFields $fields */
$fields = $getSelectFields();
$select = $fields->getSelect();
$with = $fields->getRelations();
exit(var_dump($fields)); // #RESULT
}
My result looks like this:
object(Rebing\\GraphQL\\Support\\SelectFields)#4668 (2) {
[\"select\":\"Rebing\\GraphQL\\Support\\SelectFields\":private]=> array(0) {}
[\"relations\":\"Rebing\\GraphQL\\Support\\SelectFields\":private]=> array(0) {}
}
So my question is: "How do i use the privacy attribute callback in Laravel Rebing GraphQL?"
I'm using:
PHP 7.3
Laravel 7.17
Rebing Graphql Laravel 5.1
Thanks in advance,
greets Jules
Some more Details about my use case
EpUser.php
namespace App\GraphQL\Type;
use App\CommunityImage;
use App\User;
use Carbon\Carbon;
use GraphQL\Type\Definition\Type;
use Illuminate\Support\Facades\Auth;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Type as GraphQLType;
class EpUser extends GraphQLType {
protected $attributes = [
'name' => 'EpUser',
'description' => 'A type',
'model' => User::class,
];
public function fields(): array {
return [
'id' => [
'type' => Type::nonNull(Type::int()),
'description' => 'The id of the user',
'privacy' => function(User $user): bool {
return false;
}
],
'email' => [
'type' => Type::string(),
'description' => 'The email of user',
'privacy' => function(User $user): bool {
return $user->isMe();
}
],
'firstName' => [
'type' => Type::string(),
'description' => 'The firstName of user'
],
'lastName' => [
'type' => Type::string(),
'description' => 'The lastName of user'
],
'fullName' => [
'type' => Type::string(),
'description' => 'The fullName of user',
'selectable' => false,
'resolve' => function(User $user) {
return $user->firstName . " " . $user->lastName;
}
],
'gender' => [
'type' => Type::string(),
'description' => 'The gender of the user'
],
'isOnline' => [
'type' => Type::boolean(),
'description' => '',
'selectable' => false,
'resolve' => function(User $user, $args) {
return $user->isOnline();
}
]
];
}
[...]
And this is the UsersQuery which should respond with a user pagination object, that contains an array of users with a privacy attribute:
UsersQuery.php
namespace App\GraphQL\Query;
use App\Artist;
use App\FilePath;
use Closure;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Query;
use Illuminate\Support\Facades\Auth;
use GraphQL\Type\Definition\ResolveInfo;
use Rebing\GraphQL\Support\Facades\GraphQL;
use App\User;
class UsersQuery extends Query {
protected $attributes = [
'name' => 'UsersQuery',
'description' => 'A query',
'model' => User::class,
];
public function type(): Type {
return GraphQL::type('userPagination');
}
public function authorize($root, array $args, $ctx, ResolveInfo $resolveInfo = NULL, $getSelectFields = NULL): bool {
return Auth::check();
}
public function args(): array {
return [
'id' => [
'type' => Type::int(),
'description' => 'The id of the user'
],
'slug' => [
'type' => Type::string(),
'description' => 'The slug of the user'
],
'pagination' => [
'type' => Type::nonNull(GraphQL::type('paginationInput')),
'description' => 'The pagination of the users to query',
'rules' => 'required',
],
'search' => [
'type' => Type::string(),
'description' => 'a string to search for users'
],
'roles' => [
'type' => Type::listOf(Type::string()),
'description' => 'The roles of the user',
'rules' => 'sometimes|required|array|in:user,developer,administrator'
]
];
}
public function resolve($root, $args, $context, ResolveInfo $info, Closure $getSelectFields) {
if(isset($args['id']) || isset($args['slug'])) {
if(isset($args['slug'])) {
$user = User::where('slug', $args['slug'])->first();
} else {
$user = User::find($args['id']);
}
return [
'items' => $args['pagination']['limit'] > 0 && $user ? [$user] : NULL,
'itemTotal' => $user ? 1 : 0
];
}
$sortBy = $args['pagination']['sortBy'] ?? 'id';
$sortByDesc = isset($args['pagination']['sortByDesc']) ? $args['pagination']['sortByDesc'] : true;
$sortByType = $sortByDesc ? 'desc' : 'asc';
$search = false;
if(isset($args['search']) && $args['search']) {
$search = true;
$query = User::search($args['search']);
} else {
$query = User::query();
}
if(!empty($sortBy)) {
$query->orderBy($sortBy, $sortByType);
}
// Todo: eloquent search can't serach for whereHas
if(isset($args['roles']) && !$search) {
if(is_array($args['roles'])) {
foreach($args['roles'] as &$role) {
$query->whereHas('roles',
function($q) use ($role) {
$q->where('name', $role);
});
}
} else {
$query->whereHas('roles',
function($q) use ($args) {
$q->where('name', $args['roles']);
});
}
}
if($search) {
$userPaginationObject = [
'itemTotal' => $query->count(),
'items' => $query->getWithLimitAndOffset($args['pagination']['limit'],
$args['pagination']['offset'])
];
} else {
$userPaginationObject = [
'itemTotal' => $query->count(),
'items' => $query->limit($args['pagination']['limit'])->offset($args['pagination']['offset'])->get()
];
}
return $userPaginationObject;
}
}
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.