Skip to content

Abstract

Mauro Gadaleta edited this page Sep 8, 2017 · 1 revision

How to Manage Common Dependencies with Parent Services

As you add more functionality to your application, you may well start to have related classes that share some of the same dependencies. For example, you may have multiple repository classes which need entity manager service for example:

// ... ./App/Repository/BaseRepository
class BaseRepository {
  constructor (entityManager) {
    this._entityManager = entityManager
  }
}

// ... ./App/Repository/UserRepository
class UserRepository extends BaseRepository {
  /**
   * @param {number} id
   * @return {Promise<User>}
   */
  findById(id) {
    return this._entityManager//...
  }
}

// ... ./App/Repository/PostRepository
class PostRepository extends BaseRepository {
  /**
   * @param {string} title
   * @return {Promise<Post>}
   */
  findByTitle(title) {
    return this._entityManager//...
  }
}

Just as you use inheritance to avoid duplication in your code, the service container allows you to extend parent services in order to avoid duplicated service definitions:

YAML
services:
    app.base_repository:
        # as no class is configured, the parent service MUST be abstract
        class: ./App/Repository/BaseRepository
        abstract:  true
        arguments: ['@entity_manager']

    app.user_repository:
        class:  ./App/Repository/UserRepository
        parent: app.base_repository

    app.post_repository:
        class:  ./App/Repository/PostRepository
        parent: app.base_repository

    # more services definition...
JS
import BaseRepository from './App/Repository/BaseRepository'
import UserRepository from './App/Repository/UserRepository'
import PostRepository from './App/Repository/PostRepository'
import {Reference} from 'node-dependency-injection'

let baseDefinition = container.register('app.base_repository', BaseRepository)
  .addArgument(new Reference('entity_manager'))
baseDefinition.abstract = true

let userDefinition = container.register('app.user_repository', UserRepository)
userDefinition.parent = 'app.base_repository'

let postDefinition = container.register('app.post_repository', PostRepository)
userDefinition.parent = 'app.base_repository'

// more definitions

In this context, having a parent service implies that the arguments and method calls of the parent service should be used for the child services. EntityManager will be injected.