Found an example
there is a thing in laravel called FormRequest
.
Sometimes, I need extra validation. So I need to use some service there somehow. What options I have
- facade
- service locator via app() global function
- I also have instance of container there via
$this->container
which one is the best here? I suppose instance of container
I can't do constructor injection. Why? Because for me, it seams that there are too many arguments on the __construct
method
it look like this
Am I wrong with this one?
Also they (FormRequest
s) help me to make controllers slim.
I get all the extra data there (for example get user by email,
I mean not the current session user, but the one that I, for example, edit)
so I don't need to do this in other place.
what I also can do is to make some separate method, name it, for example, afterValidationRequestDataSetter
,
on the form request, call it at the end of all operations like
$this->container->call([$this, 'afterValidationRequestDataSetter'])
and it will inject all the dependencies that I need
(I suppose, have not tested yet), but that
-
is not constructor injection
-
looks a bit like a magic since you can't do search on who calls this method (especially, it will be hard for new people on the project)
what is your ides about that?
p.s. not laravel zombie-fan and not forcing people to use facades
Inject the service needed for said validation.
None of these is viable: if you need
SomeValidator
, it should be explicitly declared by the public API of the unit that you are working with, either as constructor argument or additional method argument.Yes you can do constructor injection: avoiding constructor injection to then add runtime service lookups is just hiding complexity, and building up false confidence. Each runtime lookup is a late failure, a hard-to-debug endpoint, and added hidden complexity. If it is complex, then you can "divide et impera" into smaller units, but do not hide dependencies for the sake of it.
Yes: if it is complex, it is complex. If you add service location at runtime, you are not just having just complexity, but also runtime chaos (chaos is another degree worse than complex).
A request is not a service, so it shouldn't retain runtime services in its internals: it should be built by either a factory (which has all required services), or by a named constructor (which is just a simpler factory) that receives the required services (including validators) at runtime.
Argh, please don't do any of that. You are introducing multiple problems:
$this
, I suppose) now has invalid state untilafterValidationRequestDataSetter
. Objects should always be in a valid state, because you cannot predict if any of their public API will be hit between state mutations.