-3

I'm trying to inject an Entity via DI into a service.

The Entity is created from a JSON-Field in the database (which got queried from the user-request) via the Doctrine-JSON-ODM-library (https://github.com/dunglas/doctrine-json-odm).

I would generally write a Context-class, which would take Request & Repository to return the Dependency( as described here https://blogs.cuttingedge.it/steven/posts/2015/code-smell-injecting-runtime-data-into-components/ ). However since my dependencies rely on deeply nested data inside a tree-structure, this does not seem feasible.

/* Doctrine-Entity queried from DB with User-Request-Parameters */
class Page
{
    /**
     * @var Slot[]
     * @ORM\Column(type="json_document", options={"jsonb": true})
     */
    private $slots = [];
}

/* First level of nesting */
class Slot
{
    /** @var Components[] */
    private $components;
}

/* Entity to be injected */
class Component
{
   // multiple data-fields
}

// Service which will need to work with the Component-Data
class ComponentRenderService
{
   // multiple functions which all need (read)-access to the
   // Component-data
}

How can I resolve a dependency which get's created via a deeply nested-structure?

peterp
  • 3
  • 1
  • I don't see a reason why you wouldn't be able to pass the entity to your Service method call as an argument. Services are injected with dependencies at init level, before any other operations, meaning you would have to query or instantiate your entity at some point during container compilation. Very unlikely that you need to do this at this point. You should just pass your entity to service method which then manipulates it after your user-request query operation. – domagoj Sep 01 '19 at 15:20
  • The dependency injection container is built at compile time, not at runtime. So when the application is running and you get the the entity from the DB, it's too late to configure the DIC. You need to inject the proper repositories and use those to get the necessary entities. No idea what you mean by "deeply nested", or why would it be a problem. Good luck! – yivi Sep 01 '19 at 16:00
  • @Domagoj this would work but has this downside (quoted from the linked article in my question) `"The addition of these parameters to the Save method will ripple through the system because the direct and indirect consumers of the ICustomerRepository abstraction will need to add these parameters to their API as well—all the way up the chain. Not only would this pollute the API, it would also force you to make sweeping changes throughout the code base for each and every piece of runtime data that some implementation requires in the future."` – peterp Sep 02 '19 at 06:59

1 Answers1

-1

Adding to my comment on original post, once you pass the entity as method argument, you can set it as class variable, i.e.:

$service->method($entity)

class Service 
{

    private $entity;

    public function method($entity) // You call this somewhere
    {
       // If I understood you correctly, this is what you need
       $this->entity = $entity; // You set it as a class variable (same as DI does in constructor)

       // do stuff to $this->entity
    }


   public function otherMethod()
   {
      // you can access $this->entity here provided that you called `method` first
   }

}
domagoj
  • 906
  • 1
  • 8
  • 20
  • This would definitely solve the problem. The only risk that I see is that it's not clear that `otherMethod` requires `method` to be called first (especially if there are multiple otherMethods). I'll accept this answer if there are no other solutions coming up. – peterp Sep 02 '19 at 06:57