-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
service() and single_service() return type other than object #8572
Comments
In my understanding, a service is an object. Why do you think an array as a service? |
lonnieezell in codeigniter4 foundations Book: Services are simple: it’s a way to create an instance of a class and all of its dependencies. It can either provide a brand new instance of the class, or a shared instance that will always be returned when that service is called. A shared instance is the default, as that allows simple class re-use throughout the framework. Almost all of the system classes are available as a service. This allows you to easily grab, for example, the IncomingRequest instance that represents this request no matter where you are in the code. And don’t worry, if you’re into testing, it provides a simple way to insert your own version for use during tests. |
I just realized, but is it necessary to return CodeIgniter4/system/Common.php Line 1006 in 65c6a61
|
It's because the phpdocs state that these functions return a shared instance ( |
Null here means to say the requested service was not found. |
Oh, I got. |
@lonnieezell what's your say on this? |
I don't see any issue with allowing people to return what they want, honestly. My original idea for it was to replace IoC containers in a simpler way, so it was originally envisioned serving only a single class. However, is there a reason to restrict end users from making creative uses out of it that we haven't thought about? I don't think so. |
If it is kind of a container, it may be better to be |
I think that's where the fault is. You make code with a vision in mind what it will do and what it will not. That is your contract with your end users. Allowing them to do virtually anything with it seems reckless, to say the least. It's like allowing me as your end user use the cache library to manipulate images and later complain why the cache driver is not saving the image. It's exaggerated but I hope I get my message through. |
You're exaggerating my thought a bit. The contract with the users originally was it would return a cached version of whatever they did within that method. And it was that way until we decided to make everything strictly typed. It was only then we changed the contract with the users. We've all used it seen people use things in ways people didn't originally expect. And I'm sure sometimes we've been bit by it. But we are not talking about should we allow people to manipulate images with a cache library. We're talking about whether null values, something we currently allow to be returned, should allow to be cached, and getting hung up on their use case for it. |
It is clear that Services class was designed to return objects,
and all documentation tells it. So aren't both Services that returns arrays and Services that returns null simply misused? If we change the Services to a container that can contain anything, it is better to do the following:
Services should be used as little as possible. Because:
However, since Services is so easy to use, users may use them without limit. The pattern of pulling dependent objects is an anti-pattern. For example, this is not good. class Foo
{
public function bar()
{
$baz = service('baz'); // is equals to `Services::baz()`
$baz->doSomething();
// ...
}
} This is better. class Foo
{
public function __construct(private Baz $baz)
{}
public function bar()
{
$this->baz->doSomething();
// ...
}
} |
I'll say it again but to even think of completely changing that central of a component to something that works completely different is crazy and is a huge disservice to the users. I will agree that looking at it now it has become more like a service locator than it originally was. If anything we should look at ways to simplify that process again. Maybe by adding a publish feature that copies the service methods from modules or composer packages into the app services class? That would allow us to get back to it just being a single static call without all of the other stuff we've added. I think the argument about coupling is a little overblown in this case, honestly. You're already tightly coupled to the framework. It is relatively rare rarely that someone completely replaces the framework. I think it's fine to encourage people to use the Services more responsibly by grabbing the service in the controller and passing it in as a dependency to child classes though that can get pretty ugly at times. End of the day I feel like we have to come back and ask what is best for the users? That's not always what we learned in college. Sometimes simplifying and de-normalizing is necessary for ease of use and performance. |
I'm glad that you know the current Services is not so simple than it originally was. I don't say that we should replace Services with something completely different soon. But I would like to say using Services is not so good.
We could consider that approach, but it will be still a major change.
We are already doing that. The following note has been around for quite some time.
|
No member actively supports this proposal. |
@paulbalandan you've added strict object return type for service() and single_service() in 4.3.7
The issue I'm hading with this one is that I'm using services to return array of objects. So I had to override those functions in Common.php to remove the type hint
I don't see reason why service should only be an object and I thing the type hint should be set as mixed or at least to union type null|object|array but for union types PHP7 support needs to be dropped.
The text was updated successfully, but these errors were encountered: