docs icon indicating copy to clipboard operation
docs copied to clipboard

Enhance Dependency Injection Documentation with more examples and Application Skeleton

Open jamisonbryant opened this issue 8 months ago • 5 comments

Description

The Main Idea

Our current dependency injection documentation primarily explains the technical implementation but lacks sufficient explanation of the conceptual benefits and practical applications. The examples given are very high-level (what's a UsersService and how is my app supposed to use it?)

We should significantly expand our DI documentation with more copy-pastable examples and potentially create an application skeleton that demonstrates DI best practices within a CakePHP context.

Potential Roadblocks

  • Finding the right balance between beginner-friendly explanations and advanced usage patterns
  • Adapting existing examples to new framework versions
  • Maintaining additional example code as the framework evolves
  • Ensuring the application skeleton doesn't become overly complex or opinionated
  • Adding more documentation creates more content to maintain with limited contributor resources

User Feedback/Frustration

  • New developers struggle to understand why they should use dependency injection/service-oriented architecture instead of good ol' Tables, Behaviors, and Components
  • Experienced developers lack examples for implementing DI in complex scenarios
  • There are very few (to my knowledge) questions from the community about DI best practices...is anyone using it?
  • Teams migrating from older CakePHP versions find the DI approach conceptually challenging

Potential Next Steps

  1. Enhance the DI docs explaining the benefits (testability, flexibility, separation of concerns)
  2. Develop a progressive series of examples from basic to advanced use cases
  3. Document common patterns for injecting services, repositories, and factories
  4. Create a minimal but complete application skeleton showcasing DI patterns
  5. Add specific examples for testing components with injected dependencies
  6. Consider creating video tutorials demonstrating DI implementation in real-world scenarios - CakeFest?
  7. Poll community to identify the most confusing aspects of DI to address in documentation

CakePHP Version

6

jamisonbryant avatar Apr 26 '25 16:04 jamisonbryant

I personally see a much deeper integration of the DIC (Dependency Injection Container) in the core where every object, that could be adjusted/overwritten by the user, gets fetched from the DIC instead of doing new $class().

This would allow users to hook into exactly those object creation places and insert their custom overwritten objects instead of - if its present at all - going throug either Configure values (if they are present for that specific object) or passing a className to the registry config.

E.g.

  • ErrorLogger classes which are currently configured via the Error.logger config value
  • Any registry should pull the object from the DIC instead of manually doing new $class() (e.g. just like we already do for the CommandFactory::create method)
  • any internal classes like CommandScanner should also be fetched from the DIC to allow adjustments/extension being done. we just don't provide the BC promise for those classes, but that doesn't mean, that users shouldn't be able to easily extend it.
  • any non internal class, which gets created via new MyService() (e.g. new ContentTypeNegotiation()) and can't be adjusted via Configure values, should be fetched from the DIC

So conceptionally I'd like to move any object creation logic from the Configure namespace into the DI concept so anything done via Configure should only contain "simple" configuration, not class configuration.

This of course should NOT be done for entity objects where state is important per created object. But we have a lot of places where we manually just create objects "inline" and therefore make it hard for users to extend those specific classes.

@steinkel I know we talked about this briefly so I am curious what your stance on this is as well.

LordSimal avatar Apr 27 '25 10:04 LordSimal

@LordSimal A lot of good ideas. I think that's worth it's own issue. Want me to make one?

jamisonbryant avatar Apr 28 '25 20:04 jamisonbryant

Maybe Symfony's dependency injection could be used as inspiration, ex: https://github.com/symfony/symfony/blob/7.3/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php

I liked the use of $container->getParameter|$container->hasParameter .

rochamarcelo avatar Apr 29 '25 01:04 rochamarcelo

I think it's a good move. I would aim for the places that are hard to modify for the users. I also understand DI is possible now through registries or some configure params. In that case, even if it's not implemented the same way, we still are capable to inject the instances and let the framework use them. In these cases I would aim to keep the framework BC.

steinkel avatar Apr 29 '25 07:04 steinkel

This issue is stale because it has been open for 120 days with no activity. Remove the stale label or comment or this will be closed in 15 days

github-actions[bot] avatar Aug 28 '25 00:08 github-actions[bot]