I want to create an API that display and fetch data from table(users) and another table(fruits) together base on the unique id (fruit_id) common in both table.
table->users
+----------+------------+----------+--------------+
| Id | Fruit_id | Name | Gender |
+----------+------------+----------+--------------+
| 1 | B456 | Mary | Female |
| 2 | O174 | James | Male |
table->fruits
+----------+------------+----------+--------------+
| Id | Fruit_id | Name | Quantity |
+----------+------------+----------+--------------+
| 1 | B456 | Banana | 22 |
| 2 | O174 | Orange | 34 |
I created an API in laravel where fetch all data in the users table from my controller
class UserApiController extends Controller
{
public function index()
{
return Users::all();
}
}
API display result
[
{
id: 1,
fruit_id: B456,
name: Mary,
gender: Female,
},
{
id: 2,
fruit_id: O174,
name: James,
gender: Male,
}
]
I want the API to display like the below based on the unique id (fruit_id) selection that is common between both tables how will I write the code in my controller to display the desired result.
Desired result
[
{
id: 1,
fruit_id: B456,
name: Mary,
gender: Female,
fruits: [
id: 1,
fruit_id: B456,
name: Banana,
Quantity: 22,
]
},
{
id: 2,
fruit_id: O174,
name: James,
gender: Male,
fruits: [
id: 2,
fruit_id: B456,
name: Orange,
Quantity: 34,
]
}
]
You should create a relationship inside Model\User. Then, you can use with() or load().
Example:
Users::all()->load('fruits');
https://laravel.com/docs/8.x/eloquent-relationships#one-to-many
you need to make one-to-many relationship between tables
table->users
Id - Name - Gender
table->fruits
Id - user_id - Name - Quantity
class User extends Model{
public function fruits(){
return $this->hasMany(Fruit::class,'user_id');
}
}
class Fruit extends Model{
public function user(){
return $this->belongsTo(User::class,'user_id');
}
}
User::with('fruits')->get();
Related
I'm using Gorm and Golang to fetch data from my database. Is it possible to make Gorm fetch also the objects children (foreign keys)?
Database tables
users
+----+---------+------------+
| id | name | country_id |
+----+---------+------------+
| 1 | Adam | 1 |
| 2 | Bertil | 1 |
| 3 | Charlie | 2 |
+----+---------+------------+
countries
+----+--------+
| id | name |
+----+--------+
| 1 | Sweden |
| 2 | Norway |
+----+--------+
Models
type User struct {
Id int64 `json:"-"`
Name string `json:"name"`
CountryId int64 `json:"-"`
Country Country `json:"country"`
}
type Country struct {
Id int64 `json:"-"`
Name string `json:"name"`
}
Code to fetch all users
var users []User
DB.Find(&users) // Question: How should this be modified to automatically fetch the Country?
Actual result
[
{
"name": "Adam",
"country" : {
"name": "",
}
},
...
]
Desired result
[
{
"name": "Adam",
"country" : {
"name": "Sweden",
}
},
...
]
Thanks a lot for you input!
/Klarre
Yes it is possible, it's called Preloading.
users := make([]User,0)
DB.Preload("Country").Find(&users)
how would i get the type name of my referenced table in my get
Here is my database example:
mainTable
id | typeid
1 | 1
2 | 1
3 | 2
And here is my second table
typesTable
id | type
1 | test
2 | test2
3 | test3
My relationship in my main table model is defined as :
public function type()
{
return $this->belongsTo('App\Models\typesTable', 'typeID');
}
And here is how im pulling the data:
try {
$data = Main::with('type')
->groupBy('typeID')
->get(array(
DB::raw('type as date') <---getting type column does not exist-->,
DB::raw('COUNT(*) as "views"')
));
return Respond::Ok('Success', $data);
} catch (\Throwable $th) {
return Respond::Bad('Failed', $th);
}
my problem is i cannot get the type name in my get array and am getting an error..
if i remove that line i get the following data back:
message: "Success"
data:
0: {views: 2, type: null}
1: {views: 1, type: null}
2: {views: 1, type: null}
meta: null
Please help
I am trying to create a policy for updating a user to ensure that either the person updating or the user being updated belongs to a place.
I have the current database structure for the users
| id | first_name | last_name | email | password | created_at | updated_at |
and this is the places
| id | name | description | created_at | updated_at |
I then have a pivot table which is
| user_id | place_id |
Everything links up correctly and I can pass and associate data into each models.
What I am trying to achieve is that when I send in a request according to the JSON API spec which looks like the following:
{
"type": "users",
"attributes": {
...
},
"relationships": {
"places": {
"data": [
{
"type": "places",
"id": "1"
},
{
"type": "places",
"id": "2"
}
]
}
}
}
Inside of the updated policy, I want to check that either the authenticated user or the user being updated belongs to that place.
I have a method on the User model which is the following:
public function belongsToPlaces($placeIds)
{
return $this->places()->whereIn('id', $placeIds)->count() === count($placeIds);
}
This seems to work but it really doesn't feel very secure as realistically I should check each of the IDs. I'm just wondering if there is a built-in method to do this?
I would do a diff on the placeIds you already have with the one on the user. It will return all place ids there is not in the request, if it's not present on the users places. So check if the diff is empty, then everything is fine, otherwise the id's are invalid.
public function belongsToPlaces($placeIds)
{
return collect($placeIds)->diff($this->places()->pluck('id'))->isEmpty();
}
I have two types in my schema:
type Resident = { type Visitor = {
id id
name name
} }
In my database:
Residents and Visitors Tables:
+--------+-------+ +--------+---------+
| res_id | name | | vis_id | name |
+--------+-------+ +--------+---------+
| 1 | Alice | | 1 | Charlie |
| 2 | Bob | +--------+---------+
+--------+-------+
And then a table that shows which visitor belongs to which resident:
+--------+--------+--------------+
| res_id | vis_id | relationship |
+--------+--------+--------------+
| 1 | 1 | fam/fri |
| 2 | 1 | contractor |
+--------+--------+--------------+
Each visitor could either be a "fam/fri" or a "contractor" to a resident. So Charlie is Alice's visitor as her family or friend. However, Charlie is also a visitor to Bob, but instead as a contractor.
Question: How do I structure my schema so that when I query Alice, Charlie returns as a fam/fri, and when I query Bob, Charlie is returned as a contractor? I imagine this:
{
Resident(id: 1) { "Resident" {
name "Alice"
Visitor { "Visitor" {
id ===> "1"
name "Charlie"
relationship "fam/fri"
} }
} }
}
and also:
{
Resident(id: 2) { "Resident" {
name "Bob"
Visitor { "Visitor" {
id ===> "1"
name "Charlie"
relationship "contractor"
} }
} }
}
Something like:
type Query {
resident(id: Int): Resident
}
type Resident {
id: Int!
name: String!
visitors: [Visitor!]!
}
type Vistor {
id: Int!
name: String!
relationship: VisitorRelationship!
}
enum VisitorRelationship {
CONTRACTOR
FAMILY_OR_FRIEND
}
Note that by convention field names should be camelCase and type names should be in PascalCase. If the data returned from your data source (whether that's a database, API, or whatever) is not in the same shape as what you want to return from your GraphQL service, then you should transform the data before returning it inside your resolver, for example:
const relationshipMap = {
'fam/fri': 'FAMILY_OR_FRIEND',
'contractor': 'CONTRACTOR',
}
const resolvers = {
Query: {
resident: (root, args) => {
const resident = await Resident.findById(args.id)
// assuming resident has a property named joinTable that's
// an array and each relationship has a property named visitor
return {
...resident,
visitors: resident.joinTable.map(relationship => {
return {
...joinTable.visitor,
relationship: relationshipMap[joinTable.relationship],
}
})
}
},
},
}
You can also map enums to custom values this way.
I have three tables,
User cities user_cities
id name title id name user_id city_id
1 aaa designer 1 cityA 2 1
2 bbb developer 2 cityB 2 2
3 ccc designer 3 cityC 1 2
1 1
2 3
3 2
After joining and querying the database my result is,
data: {
0: {
id: 1
name: aaa,
title: designer,
cities :[
0: {
id: 1,
name: cityA
}
1: {
id: 2,
name: cityB
}
2: {
id: 3,
name: cityC
}
]
},
1: {
id: 2
name: bbb,
title: developer,
cities :[
0: {
id: 1,
name: cityA
}
1: {
id: 2,
name: cityB
}
]
}
1: {
id: 3
name: ccc,
title: designer,
cities :[
0: {
id: 2,
name: cityB
}
]
}
}
Everything is fine until here. But i want to groupBy by cities and take count.
If i filter by title=designer the filtered data will display and i want to make group by cities and take count of it.
So my final result will be,
cityA = 1 counts
cityC = 2 counts
Help me to solve the problem.
You might use the withCount to eager load the relationship counts.
I assume you already have the cities relationship defined in the User.php model:
class User
{
public function cities()
{
return $this->belongsToMany(City::class);
}
}
Then:
$users = User::withCount('cities')->get();
I think the results are gonna be:
data: {
0: {
id: 1
name: aaa,
title: designer,
cities_count: 3
},
1: {
id: 2
name: bbb,
title: developer,
cities_count: 2
}
1: {
id: 3
name: ccc,
title: designer,
cities_count: 1
}
}
An alternative could be using lazy eager loading:
$users = User::all()->loadCount('cities');