One possibly approach for this is to introduce a third service SL and inject it, like this:
- Mapper is an interface
- GroupMapper implements Mapper, receives SL by injection
- UserMapper implements Mapper, receives SL by injection
- SL has methods:
- function register($name, Mapper m)
- function get($name) : Mapper
- GroupMapper::__construct(SL $sl, ...) includes something like:
- $this->sl = $sl;
- $this->sl->register('group', $this);
- UserMapper::__construct(SL $sl, ...) includes something like:
- $this->sl = $sl;
- $this->sl->register('user', $this)
Then, assuming $um is an instance of UserMapper obtained the DIC, and it needs to use the group mapper service: $um->sl->get('user') returns the group mapper.
In essence, what this boils down to is implementing a service locator, which is not really nice, but has the advantage that it is tiny, essentially being a filtered subset of the full DIC. This will work as long as you do not start using either service before all mutually dependent services have been initialized, which may not be a good fit for some situations.
Another possibility is to make your service ContainerAware and use it in the same, but IMHO this is worse, although a bit shorter, because you essentially allow use of anything from the DIC without any control. The pattern I suggest minimizes the "contact surface".