Hello,
I upgraded cakephp from 4.5.9 to 5.1.4. I was using serviceawaretrait to load services at base controller. But now I found that CakePHP 5.1.4 standard way is DI. I tried it but getting errors when I try to use services in controller. For the context, I have many controllers and services so I need help to guide me how can I fix the errors and able to use existing services in existing controllers with minimal code changes.
Yes, I see that. Can’t we use constructor based injection instead of method injection? Even Method injection not working.
constructor based injection isn’t preferred/working here since the controller isn’t created by the container.
And what exactly do you mean by “its not working”. Please give more context. Do you get an error. Do you call the right URL. what code example can you show. I can’t help you with “its not working”
Ok let say, I have below files.
- TestController: addTest()
- TestService: ValidateTestExistance()
Now, Application.php has below code
public function services(ContainerInterface $container): void
{
$container
->add(TestService::class);
}
TestsController:
public function addTest(TestService $testService){
$validate = $testService->ValidateTestExistance();
...............................
}
So I am getting error like function ValidateTestExistance called on null. It means that I am not getting service object here.
JFI, I have existing code with ServiceAwareTraits and ServiceRegistry…
No idea what you mean by ServiceAwareTraits and ServiceRegistry, those are not default CakePHP
But before doing that, just try var_dump($testService); and see if you get an instance.
Also make sure you have the correct use statements at the top of your controller to correctly import your TestService class
Ok, Anyway please can you tell me that do we have any other approach than to use services as method injection in controller class?
As, my current project has lots of methods and controllers. Can we do something like create helper function which loads the service from container and then inject in controller’s constructor?
From what you described it should work. All you need to do is add the service to the container in your src/Application.php
// At the Top of your class
use App\Services\TestService;
public function services(ContainerInterface $container): void
{
$container->add(TestService::class);
}
and then you can do in any controller
// At the Top of your class
use App\Services\TestService;
public function add(TestService $testService) {
var_dump('I am here');
var_dump($testService);
}
I’d make sure that you actually call the correct controller action by checking, that you get the I am here output. Maybe you think you are calling the correct URL even though you are going somewhere different.