You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
How to use path params and body in a single query? #8
In the current approach, we pass parameters to SQL query only from a single source (path params or body params):
GET: uses path params
POST: uses body params
PUT: uses body params
DELETE: uses path params
But even for a simple PUT endpoint it isn't enough: we want to extract object ID from a path and other parameters from a body. Here is an example of generated code that we should improve:
app.put('/v1/categories/:categoryId',(req,res)=>{pool.query('UPDATE categories SET name = :name , name_ru = :nameRu , slug = :slug , updated_at = NOW() , updated_by = :userId WHERE id = :categoryId',{"name": req.body.name,"nameRu": req.body.nameRu,"slug": req.body.slug,"userId": req.body.userId,"categoryId": req.body.categoryId},
We can see that categoryId is bound to req.body.categoryId while it should use a value from req.params.categoryId.
Also there will be more cases where we need to combine different sources: userId might be extracted from a header. We might want to access cookies or query parameters.
Instead of always binding to body parameters, we can first search what path parameters are defined. In the example above, categoryId is defined in a path, so this can take precedence. Everything else will be bind to default source.
Pros:
minimal modifications are required
Cons:
the more conventions (magic) we have, the more knowledge is required from users to grasp it
Hey @php-coder, to be honest the all cons about all options are make sense. So, if I were you, I'd look at another way:
modify a bit your yaml declaration. For example, I'd add a new directive params:
- path: /v1/categories/:categoryIdparams:
- header: userId <--list of params that we take from header>
- body: name, name_ru, slug <-- <list of params that we take from body>.....put: >- UPDATE categories SET name = :name , name_ru = :nameRu , slug = :slug , updated_at = NOW() , updated_by = :userId WHERE id = :categoryId
@theshamuel In other words, we can move binding logic into YAML configuration. Another con of that approach is that it makes configuration more verbose.
- path: /v1/categories/:categoryId
params:
- header: userId <--list of params that we take from header>
- body: name, name_ru, slug <-- <list of params that we take from body>
.....
put: >-
By the way, this way we will make params global, i.e. it will be available within put and other possible verbs (get, post, etc). This is isn't desirable.
At the same time, if we try to move this into a method, we will have to introduce a property for a query:
In order to push this forward, in the ddb2e16 commit the 2nd approach was partially implemented. All parameters now must have a prefix b or p: :b.param or p.param.
This might be not a best API but at least it allow us to proceed.
Activity
php-coder commentedon Jul 15, 2020
Option 1: improve the current logic
Instead of always binding to body parameters, we can first search what path parameters are defined. In the example above, categoryId is defined in a path, so this can take precedence. Everything else will be bind to default source.
Pros:
Cons:
php-coder commentedon Jul 15, 2020
Option 2: enhance SQL queries with variables
Example:
The syntax can be different:
$body.name${body.name}#{body.name}bodyis one of the sources and can beheader,path,query,cookie, etcPros:
Cons:
php-coder commentedon Jul 15, 2020
Option 3: mix the previous approaches
Example:
Pros:
Cons:
theshamuel commentedon Jul 17, 2020
Hey @php-coder, to be honest the all cons about all options are make sense. So, if I were you, I'd look at another way:
modify a bit your yaml declaration. For example, I'd add a new directive params:
Pros:
Cons:
php-coder commentedon Jul 17, 2020
@theshamuel In other words, we can move binding logic into YAML configuration. Another con of that approach is that it makes configuration more verbose.
Thank you for the input! I'll think about it.
php-coder commentedon Jul 26, 2020
By the way, this way we will make
paramsglobal, i.e. it will be available withinputand other possible verbs (get,post, etc). This is isn't desirable.At the same time, if we try to move this into a method, we will have to introduce a property for a query:
feat: add support for parameter prefixes in order to be able to expli…
php-coder commentedon Jul 26, 2020
In order to push this forward, in the ddb2e16 commit the 2nd approach was partially implemented. All parameters now must have a prefix
borp::b.paramorp.param.This might be not a best API but at least it allow us to proceed.