I'm trying to apply Clean Architecture in my PHP application. At the moment I have my business logic entity User
and service UsersService
. UsersService
collects all of the use cases related to the User entity.
UsersService->createUser(someData)
takes Users repository and stores it in the database.
I call createUser
use case in my Controller and in my Cli Task. And I want to integrate logging system in my project. I want to log something inside use case and inside controller/task.
Where I need to place my Loggers factory/Logger
interfaces?
Well the premise here is that in your internal layers know nothing from externals ones, so any interfaces you use in your domain should lays in the domain, that gives you the hability to change how you log later without making a single change in your business logic, so just create a Log interface in your domain, implement it from outside and voila.
In your domain it could looks like this:
interface ILogger {
log(level: string, message: string): void
}
class MyUseCase {
public constructor(private readonly logger: ILogger){}
public execute(input: Input): void {
// some stuff
this.ILogger.log('level', 'message')
// some other stuff
}
}
and in your framework and drivers layers you could:
class MyLogger implements ILogger {
log(level: string, message: string): void {
myChosenLoggerTech.log(level, message) // ie winston, console.log, etc
}
}
So now when MyUseCase
is instantiated can use:
new MyUseCase(new MyLogger())
But wait, nothing is that simple, generally speaking there are two log use cases:
All right, if your case is number 2 go with this solution, but if your case is number 1 maybe you should make the action of logging more explicit by wrapping it into a dedicated entity, or exception or whatever truly represents your business. You can check here for a more detailed explanation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With