I'm creating a photography app to help photographers keep track of their clients. This is my first project using Adonis.JS and I really enjoy it so far, but been stuck on this problem for a while and can't find an answer anywhere. I'll share my Models, Controllers, and Migrations (possibly not creating the relationships right, been awhile since I've done any back-end work)
Workflow: A User has many clients, a client has many services Need to be able to get the services from the user.
When saving in my ServiceController I've tried things like:
const user = await auth.getUser();
service.fill({
name,
price,
quantity,
due_date
});
await user.clients().services().save(service);
return service;
but sadly I get a 500 error reading: "user.clients(...).services is not a function" which does make sense, just not sure how else to go about it.
One way I had working was:
const clients = await Database.table('clients').select('*').where('user_id', user.id);
await Database.table('services')
.insert({
name,
price,
quantity,
due_date: dueDate,
client_id: clients[0].id
});
return service;
I just didn't feel like that solution was right, it felt kind of hacky given that Adonis gives Lucid, and I'm not sure; but I feel like that query will cause issues at some point.
User Model
class User extends Model {
clients() {
return this.hasMany('App/Models/Client');
}
}
Client Model
class Client extends Model {
users() {
return this.belongsToMany('App/Models/User');
}
services() {
return this.hasMany('App/Model/Service');
}
}
Service Model
class Service extends Model {
client() {
return this.belongsTo('App/Models/Client');
}
}
Service Controller
async store ({ auth, request, response }) {
// Get Authenticated user
const user = await auth.getUser();
// Retrieve new service from payload
const { name, price, quantity, dueDate } = request.all();
const service = new Service();
service.fill({
name,
price,
quantity,
due_date: dueDate
});
await user.clients().services().save(service);
return service;
}
Client Controller
// Get Authenticated user
const user = await auth.getUser();
// Retrieve new client from payload
const { name, email, address, phoneNumber } = request.all();
const client = new Client();
client.fill({
name,
email,
address,
phone_number: phoneNumber
});
await user.clients().save(client);
return client;
Service Schema
class ServiceSchema extends Schema {
up () {
this.create('services', (table) => {
table.increments();
table.string('name', 255).notNullable();
table.integer('price', 25).notNullable();
table.integer('quantity', 25).notNullable().defaultTo(1);
table.date('due_date', 100).notNullable();
table.boolean('paid').notNullable().defaultTo(false);
table.integer('client_id', 25).unsigned().references('id').inTable('clients');
table.timestamps();
});
}
down () {
this.drop('services');
}
}
Client Schema
class ClientSchema extends Schema {
up () {
this.create('clients', (table) => {
table.increments();
table.string('name', 255).notNullable();
table.string('email', 255).notNullable();
table.string('address', 255).notNullable();
table.string('phone_number', 25).notNullable();
table.integer('user_id', 25).unsigned().references('id').inTable('users');
table.timestamps();
});
}
down () {
this.drop('clients');
}
}
User Schema
class UserSchema extends Schema {
up () {
this.create('users', (table) => {
table.increments()
table.string('first_name', 80).notNullable();
table.string('last_name', 80).notNullable();
table.string('email', 254).notNullable().unique();
table.string('password', 60).notNullable();
table.timestamps();
});
}
down () {
this.drop('users');
}
}
I want my tables to end up looking like this if possible:
Users Table
| id | first_name | last_name | email | password | created_at | updated_at |
Clients Table
| id | name | email | address | phone_number | user_id | created_at | updated_at |
Services Table
| id | name | quantity | due_date | paid | client_id | created_at | updated_at |
and I need a way to save to services with a reference to the client ID. I was hoping to do this with Lucid, but if that's not applicable here that's fine. Just wanting that consistency.
I ended up deciding that I should probably just pass the clientId in through the body.
Service Controller:
async store ({ auth, request, response }) {
// Get Authenticated user
const user = await auth.getUser();
// Retrieve new service from payload
const { name, price, quantity, dueDate, clientId } = request.all();
const service = await Service.create({
name,
price,
quantity,
due_date: dueDate,
client_id: clientId
});
return response.status(200).send(service);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.