LoopBack中before save钩子无法通过ctx访问外部模型与请求对象
I've run into similar issues with LoopBack 3's operation hooks before, so here are practical fixes for your problems:
1. Get Request Object, URL, HTTP Method, and User ID
The default operation hook context (ctx) doesn't include the request object directly, but you can pass it through using a beforeRemote hook or use the loopback-context module.
Option 1: Pass Request via beforeRemote Hook (Most Reliable)
This method attaches the request to the hook's options, making it accessible in any subsequent operation hooks:
module.exports = function (Org) { // Attach req to all remote method options Org.beforeRemote('**', function(ctx, _, next) { ctx.options.req = ctx.req; next(); }); // Access request data in your operation hook (e.g., access hook) Org.observe('access', function(ctx, next) { const req = ctx.options.req; if (req) { const url = req.originalUrl; const httpMethod = req.method; // Get userId if your API uses LoopBack's default authentication const userId = req.accessToken?.userId; console.log('Request URL:', url); console.log('HTTP Method:', httpMethod); console.log('Authenticated User ID:', userId); } next(); }); };
Option 2: Use loopback-context for Global Access
If you prefer a global approach, install the loopback-context module first:
npm install loopback-context
Then add the middleware to server/middleware.json:
"initial": { "loopback-context#per-request": {} }
Now you can fetch the request in your operation hook:
const LoopBackContext = require('loopback-context'); module.exports = function (Org) { Org.observe('access', function(ctx, next) { const currentCtx = LoopBackContext.getCurrentContext(); if (currentCtx) { const req = currentCtx.get('req'); const url = req.originalUrl; const httpMethod = req.method; const userId = req.accessToken?.userId; // Use the data as needed } next(); }); };
Note: This can have context loss issues with async operations, so the beforeRemote method is generally safer.
2. Access External Models
You don't need ctx to access other models—use the Org model's app property to fetch any registered model:
module.exports = function (Org) { Org.observe('access', async function(ctx, next) { // Fetch an external model (e.g., User) const User = Org.app.models.User; // Example: Fetch a user using the userId from the request const req = ctx.options.req; if (req?.accessToken?.userId) { const user = await User.findById(req.accessToken.userId); console.log('Fetched User:', user); } next(); }); };
Just make sure the external model is registered in server/model-config.json—this works for any model you've set up in your LoopBack app.
Quick Notes
- This assumes you're using LoopBack 3 (your code syntax matches it). For LoopBack 4, the approach is different.
- To get
userId, ensure your API has authentication enabled (using LoopBack's built-inAccessTokenmodel or a third-party auth component). - Different operation hooks (e.g.,
before save,after delete) will have slightly differentctxstructures, butoptionsis consistently available to pass custom data.
内容的提问来源于stack exchange,提问作者Gary

