Laravel JOIN DB Raw return hasMany Relathsionship - laravel

i have case in my query, i want expect like this
one project hasMany User
total_feedback is calculated from id in feedback table
where the project_id in the feedback table has a relation to the pivot table, namely project_user , i want to calculated how much feedback on a project,
i want expect return JSON like this
"success": 1,
"data": [
{
"id": 1,
"Project_name": "Project Tania Yessi Laksmiwati",
"user_name": {
"User A",
"User B",
"User C",
"User D",
}
"total_feedback": 0
},
{
"id": 2,
"Project_name": "Project Bakijan Bancar Anggriawan",
"user_name": {
"User F",
"User G",
"User C",
}
"total_feedback": 10
},
{
"id": 3,
"Project_name": "Project Mahesa Vega Mahendra",
"user_name": {
"Users A"
},
"total_feedback": 6
},
return JSON above is one project hasMany users
but, now i get return json like this bellow :
"success": 1,
"data": [
{
"id": 1,
"Project_name": "Project Tania Yessi Laksmiwati",
"user_name": "Ilyas Simanjuntak",
"total_feedback": 0
},
{
"id": 2,
"Project_name": "Project Bakijan Bancar Anggriawan",
"user_name": "Ilyas Simanjuntak",
"total_feedback": 0
},
one project return just one users, even though the project with id 1 has 3 users, like project_user table like this bellow
project_id | user_id
1 2
1 4
1 5
this is my query
$user = $this->request->attributes->get('_user');
$query = "SELECT A.id, A.`name` AS Project_name, D.`name` AS user_name, COUNT(C.`id`) AS total_feedback FROM `project` A
JOIN `project_user` B ON A.`id` = B.`project_id` AND B.`user_id` = $user->id
LEFT JOIN `feedback` C ON C.`project_id` = B.`project_id` AND C.`request_id` = B.`user_id`
JOIN `users` D ON D.`id` = B.`user_id`
GROUP BY A.`id`";
$getFeedback = DB::select(DB::raw($query));
but i get project with ID 1 just return one users,, in my case above how to return one project with many users from database, i use the DB query ,, or any suggestion ? Thanks! regards.

If you already have relationships setup, why aren't you using Eloquent for this? You can easily do this with Eloquent with() and withCount() methods. Assuming you have setup your model relationships correctly, you can do something like this instead:
Auth::user()
->projects()
->with(['users', function($query) {
return $query->pluck('name');
}])
->withCount('feedback as total_feedback')
->get();

Related

Can I restrict a mutation to update an object based on the object itself?

I have the following objects in my database:
[
{
"id": 1,
"name": "foo",
"objType": "A"
},
{
"id": 2,
"name": "bar",
"objType": "B"
}
]
And the following users:
[
{
"id": 3,
"name": "User A",
"role": "admin"
},
{
"id": 4,
"name": "User B",
"role": "client"
}
]
And I have a schema like:
enum ObjTypeEnum {
A
B
}
type MyObj {
id: Int
name: String
objType: ObjTypeEnum
}
type Mutation {
updateObj(id: Int!, name: String): MyObj
}
The user A can update any obj that he wants because he is an admin. However, the user B can only update an object only if this object is of type B.
That means:
If the user B tries to update the object 2, using the mutation updateObj(2, "new name"), this should be totally ok. However, if he tries to update the object 1, updateObj(1, "new name"), now this should return an error for this user.
My naïve solution for this is get the object in the resolver, check its type and, if is ok for the current user, then proceed with the update, otherwise throw an error. But I have the feeling I'm in the wrong direction and not using graphql properly...
Is it possible to do it using directives or something more generic, since the key that using to validate the update is an enum?

Laravel query showing different Result in DB::Table and DB::Select with inner join

I'm using 3 table
1.organizations
2.users
3.organization_user
So the organization_user is the pivot table for getting org. and user.
DB::select("SELECT users.name 'User Name',organizations.name 'Org Name'
FROM users INNER JOIN organization_users ON
organization_users.user_id=users.id
INNER JOIN organizations ON
organizations.id=organization_users.organization_id
WHERE organization_users.organization_id=$org_id");
And getting the below result
[
{
"User Name": "Navid Anjum",
"Org Name": "org1"
},
{
"User Name": "kamal",
"Org Name": "org1"
} ]
But when using
DB::table('organization_users')
->join('users','users.id','=','organization_users.user_id')
->join('organizations','organizations.id','=',
'organization_users.organization_id')
->select('users.name as Name','organizations.name as Org Name')
->where('organization_users.id','=',$org_id)
->get();
And getting the below result
[
{
"Name": "Navid Anjum",
"Org Name": "org1"
} ]
So What I'm doing wrong?
you not set the right id for organization_users in the second statement :
DB::table('organization_users')
->join('users','users.id','=','organization_users.user_id')
->join('organizations','organizations.id','=',
'organization_users.organization_id')
->select('users.name as Name','organizations.name as Org Name')
->where('organization_users.organization_id','=',$org_id)
->get();

Merge Model and its Relationship with result like join query in laravel

I'm new at Laravel and Programming at that. I have a problem joining model with its relationship, here is what my model:
class MainClass extends Model
{
public function first()
{
return $this->hasMany(First::class);
}
public function second()
{
return $this->hasMany(Second::class);
}
public function third()
{
return $this->hasMany(Third::class);
}
}
When i try to get MainClass records then load it's relationship like:
$main = Main::where('status', 'ready')->get()
$main->load(['first','second'])
Here's what i got:
[{
"id":"1",
"name":"First Person",
"status": "ready",
"first":[
{"main_id": "1", "prop":"One"},
{"main_id":"1", "prop":"Two"}],
"second":[
{"main_id": "1", "other":"Yes"},
{"main_id":"1", "other":"Two"},
{"main_id":"1", "other":"Three"}]
},{
"id":"5",
"name":"Fifth Person",
"status": "ready",
"first":[
{"main_id": "5", "prop":"Five"},
{"main_id":"5", "prop":"Six"}],
"second":[
{"main_id": "5", "other":"Laptop"},
{"main_id":"5", "other":"Pc"}]
}]
How can i merge that relationship so the result will be like join query,
this is what i want:
[{
"id":"1",
"name":"First Person",
"status": "ready",
"prop":"One",
"other:"Yes"
},{
"id":"1",
"name":"First Person",
"status": "ready",
"prop":"Two",
"other":"Two"
}]
I know there is a way to combine collection with merge or push in laravel, but i can't seem to get it right.
As of why not using join query, because i want to load relationship dynamically, so relation is not always loaded, but sometime they do. While join query, i have to write it manually (as far as i know) :-)
Maybe someone can point me somewhere, or maybe there is a package for something like this?
Thanks in advance
Use eager loading, fetching the collection, then run groupBy, then the each, then the map function to return the results formatted as your wish.
Why not just simply run the joins
You can do it with join;
$main = Main::query()->select(['main.id', 'main.name', 'main.status', 'f.prop', 's.other', 't.blabla'])
->leftJoin('first as f', 'f.main_id', 'main.id')
->leftJoin('second as s', 's.main_id', 'main.id')
->leftJoin('third as t', 't.main_id', 'main.id')
->where('main.status', 'ready')
->get();

How to insert an object and related array objects in one mutation

I have two tables reels and reel_variations, reels can have many reel_variations and reel_variations belong to one reel. I have read the Hasura docs and haven't been able to figure out how to insert a reel and a couple of reel variations in a single mutation.
mutation insertReelsAndVariations($objects: [reels_insert_input!]! = {}) {
insert_reels(objects: $objects) {
affected_rows
returning {
description
id
name
variations {
ball_bearings
braid_capacity
created_at
deleted_at
gear_ratio
max_drag
line_capacity
id
model_number
recovery
reel_id
retrieve
}
}
}
}
Variables
{
"objects": {
"name": "nice reel",
"description": "wicked nice reel",
"variations": {
"data": {
"ball_bearings": "djjdfkjdkjfdjkfjkd",
"braid_capacity": "dkfjdkfjkdf",
"gear_ratio": "20:1",
"max_drag": "20lbs",
"line_capacity": "400yrds",
"model_number": "jfdkjfkjdkfjkdjfjdf",
"recovery": "30 per turn"
}
}
}
}
Errors
{
"errors": [
{
"extensions": {
"path": "$.selectionSet.insert_reels.args.objects[0].variations.data",
"code": "constraint-violation"
},
"message": "Not-NULL violation. null value in column \"reel_id\" violates not-null constraint"
}
]
}
That's because the reel_id column is not set as a foreign key col referencing the reels table. So u can simply:
Make the reel_id col a foreign key which points to the id column of reels table!

How can I create a relationship between `json` column and a `int` (id) column in Hasura + Postgres?

I have 2 tables users and post
Table users has columns id and post, column contains an array of the form [1, 2, 3, 4, 5] - where 1, 2, 3, 4, 5 is id in table post
In the table posts the following columns id and text
Table users:
https://i.stack.imgur.com/ywdS7.png
Table posts:
https://i.stack.imgur.com/IBdpb.png
in hasura made an array relation
https://i.stack.imgur.com/311sd.png
Next I made the following request
{
users_test {
postz {
id
}
}
}
I would like to receive such data in response:
postz: [
   {
     text: 'qwe'
   },
   {
     text: 'sdf'
   }
]
But with such a request, I get a trace. error:
{
"errors": [
{
"extensions": {
"internal": {
"statement": "SELECT coalesce(json_agg(\"root\" ), '[]' ) AS \"root\" FROM (SELECT row_to_json((SELECT \"_5_e\" FROM (SELECT \"_4_root.ar.root.postz\".\"postz\" AS \"postz\" ) AS \"_5_e\" ) ) AS \"root\" FROM (SELECT * FROM \"public\".\"users_test\" WHERE ('true') ) AS \"_0_root.base\" LEFT OUTER JOIN LATERAL (SELECT coalesce(json_agg(\"postz\" ), '[]' ) AS \"postz\" FROM (SELECT row_to_json((SELECT \"_2_e\" FROM (SELECT \"_1_root.ar.root.postz.base\".\"id\" AS \"id\" ) AS \"_2_e\" ) ) AS \"postz\" FROM (SELECT * FROM \"public\".\"posts\" WHERE ((\"_0_root.base\".\"post\") = (\"id\")) ) AS \"_1_root.ar.root.postz.base\" ) AS \"_3_root.ar.root.postz\" ) AS \"_4_root.ar.root.postz\" ON ('true') ) AS \"_6_root\" ",
"prepared": true,
"error": {
"exec_status": "FatalError",
"hint": "No operator matches the given name and argument type(s). You might need to add explicit type casts.",
"message": "operator does not exist: json = integer",
"status_code": "42883",
"description": null
},
"arguments": [
"(Oid 114,Just (\"{\\\"x-hasura-role\\\":\\\"admin\\\"}\",Binary))"
]
},
"path": "$",
"code": "unexpected"
},
"message": "postgres query error"
}
]
}
What am I doing wrong and how can I fix it?
A few suggestions:
There are some typos in your query, as far as I can tell. Try:
{
users {
id
posts {
text
}
}
}
You don't need the post column on the users table. You just need a user_id column on the posts table, and a foreign key constraint from the posts table to the users table using the user_id and id columns of the tables respectively. Check out the docs here:
https://docs.hasura.io/1.0/graphql/manual/schema/relationships/create.html#step-3-create-an-array-relationship
https://docs.hasura.io/1.0/graphql/manual/schema/relationships/database-modelling/one-to-many.html
If you have to have the post array column for some reason, you can use computed fields to create a "relationship" between a json array and another table’s id.
https://docs.hasura.io/1.0/graphql/manual/schema/computed-fields.html#table-computed-fields
Your function would:
Take in the json array column
Extract the id's
Return select * from table where id in id's
Example:
https://jsonb-relationships-hasura.herokuapp.com/console/api-explorer
Computed field definition at: https://jsonb-relationships-hasura.herokuapp.com/console/data/schema/public/tables/authors/modify
Run these queries:
# Get list of articles for each author
query {
authors {
id
name
articles
}
}
# Get actual articles for each author
query {
authors {
id
name
owned_articles {
id
title
}
}
}

Resources