In my Laravel9 project, I have many controllers that have similar functions like:
TestController.php
namespace AppHttpControllersApi; use AppContractsTestInterface; use AppHttpControllersController; class TestController extends Controller { public function __construct( private TestInterface $testService, private $moduleName = 'Test Name', ) {} public function index() { $tests = $this->testService->index(); $response = response([ 'message' => __('Read' . $this->moduleName . 'successfully'), 'data' => $tests, ], 200); return $response; } }
Test1Controller.php
namespace AppHttpControllersApi; use AppContractsTest1Interface; use AppHttpControllersController; class Test1Controller extends ApiController { public function __construct( private Test1Interface $test1Service, private $moduleName = 'Test Name 1', ) {} public function index() { $test1s = $this->test1Service->index(); $response = response([ 'message' => __('Read' . $this->moduleName . 'successfully'), 'data' => $test1s, ], 200); return $response; } }
So I modified them into:
TestController.php
namespace AppHttpControllersApi; use AppContractsTestInterface; use AppHttpControllersApiApiController; class TestController extends ApiController { protected function service() { return TestInterface::class; } }
Test1Controller.php
namespace AppHttpControllersApi; use AppContractsTest1Interface; use AppHttpControllersApiApiController; class Test1Controller extends ApiController { protected function service() { return Test1Interface::class; } }
ApiController.php
namespace AppHttpControllersApi; use AppHttpControllersController; abstract class ApiController extends Controller { private $serviceClass; public function __construct() { $this->serviceClass = $this->service(); } abstract protected function service(); public function index() { return $this->serviceClass::index(); } }
TestInterface.php
namespace AppContracts; interface TestInterface extends BaseInterface { }
BaseInterface.php
namespace AppContracts; interface BaseInterface { public function index(); }
Then I bind interfaces into services in AppServiceProvider.php, like:
$this->app->bind('AppContractsTestInterface', 'AppServicesTestService'); $this->app->bind('AppContractsTest1Interface', 'AppServicesTest1Service');
TestService.php:
namespace AppServices; use AppContractsTestInterface; use AppRepositoriesTestRepository; class TestService implements TestInterface { public function __construct( private TestRepository $testRepo, ) {} public function index() { return $this->testRepo->index(); } }
Test1Service.php
namespace AppServices; use AppContractsTest1Interface; use AppRepositoriesTest1Repository; class Test1Service implements Test1Interface { public function __construct( private Test1Repository $test1Repo, ) {} public function index() { return $this->test1Repo->index(); } }
When I call TestController::index on my route, I get:
Cannot call abstract method AppContractsTestInterface::index()
How can I fix it or do any better suggestions? Thanks.
Advertisement
Answer
I just solved the problem by modifying the following line in ApiController.php:
private $serviceClass; public function __construct( private Container $app, ) { $this->serviceClass = $app->make($this->service()); }