Binding service to a controller

Hi,
I am defining UserService.js in app/Services and want to bind it to app/Controllers/Http/UserController. It is basically a class with a method inside and a constructor.
When in UserController I require UserService
const UserService = use('App/Services/UserService')
and call the method of UserService I get undefined; I guess because UserService constructor hasn’t been invoked.
What should I do to get it invoked and have the UserService instance available in UserController? In other words, how can I implement the IoC? I read the doc but it is not so clear
Thank you

try this way

1 Like

Here is an example of a repo from nuxt and adonis team https://github.com/SwitchTecno/adonuxt-template (this is my fork but it’s the same). In this files you can see, how service is implemented in NuxtController.

the service is app/Services/Nuxt.js

'use strict'

const Config = use('Config')
const { Nuxt, Builder } = require('nuxt')

class NuxtService {
  constructor () {
    this.nuxt = null
  }

  /**
   * Starts the build process
   * Build command
   *
   * @method boot
   *
   * @return {void}
   */
  build (dev = use('Env').get('NODE_ENV') === 'development') {
    const config = Config.merge('nuxt', { dev })

    this.nuxt = new Nuxt(config)

    if (this.nuxt.options.dev) {
      return new Builder(this.nuxt).build()
    }
  }

  /**
   * Starts the build process
   * Build command
   *
   * @method boot
   *
   * @return {void}
   */
  buildProject () {
    const config = Config.merge('nuxt', { dev: false })
    this.nuxt = new Nuxt(config)
    return new Builder(this.nuxt).build()
  }

  /**
   * Handles the HTTP request by making the appropriate
   * response, based upon the URL.
   *
   * @method render
   *
   * @param  {Object} req
   * @param  {Object} res
   *
   * @return {Promise}
   */
  render (req, res) {
    return this.nuxt.render(req, res)
  }
}

module.exports = new NuxtService()

and is required here: app/Controllers/Http/NuxtController.js

'use strict'

const NuxtService = use('App/Services/Nuxt')

class NuxtController {
  async render ({ request, response, session }) {
    /**
     * Do not end the response when this method has been executed.
     * Nuxt will write the response in background and will close
     * the response when required.
     *
     * @type {Boolean}
     */
    response.implicitEnd = false

    /**
     * Since response is now handled by Nuxt, we should commit any session
     * values. This will make sure features like CSRF protection works as
     * expected.
     */
    await session.commit()

    /**
     * Finally handover request to nuxt
     */
    await NuxtService.render(request.request, response.response)
  }
}

module.exports = NuxtController
1 Like

Hello stavrogin!, Welcome.
You need to export your functions in the UserService.js then use in the controller

//UserService.js
const User = use('App/Model/User')
async function getUser(user_id) {
    return await User.find(user_id)
}

async function getAllUser() {
    return await User.all()
}

// You need to export these functions as below
module.exports = {
    getUser,
    getAllUser
}

and then in the Controller

// UserController.js
const UserService = use('App/Services/UserService')

class UserController {
    async index({ request, response }) {
        const data = request.body()
        let user = UserService.getUser(data.user_id)
        return user
    }
}
1 Like

Thank you all guys!!

All the solution work, but what about using IoC container and providers, for example defining providers/Service/Provider.js

class Provider extends ServiceProvider {
  register () {
    this.app.bind('App/User/Service', () => {
      return new (require('../../app/Services/UserService'))()
    })
  }
}

And then requiring
const userService = use('App/User/Service')
in UserController? It should return an instance created by IoC container, but I am not 100% sure that it is the best practice