In my Laravel9 project, I have many controllers that have similar functions like:
TestController.php
JavaScript
x
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
JavaScript
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
JavaScript
namespace AppHttpControllersApi;
use AppContractsTestInterface;
use AppHttpControllersApiApiController;
class TestController extends ApiController
{
protected function service()
{
return TestInterface::class;
}
}
Test1Controller.php
JavaScript
namespace AppHttpControllersApi;
use AppContractsTest1Interface;
use AppHttpControllersApiApiController;
class Test1Controller extends ApiController
{
protected function service()
{
return Test1Interface::class;
}
}
ApiController.php
JavaScript
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
JavaScript
namespace AppContracts;
interface TestInterface extends BaseInterface
{
}
BaseInterface.php
JavaScript
namespace AppContracts;
interface BaseInterface
{
public function index();
}
Then I bind interfaces into services in AppServiceProvider.php, like:
JavaScript
$this->app->bind('AppContractsTestInterface', 'AppServicesTestService');
$this->app->bind('AppContractsTest1Interface', 'AppServicesTest1Service');
TestService.php:
JavaScript
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
JavaScript
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:
JavaScript
private $serviceClass;
public function __construct(
private Container $app,
)
{
$this->serviceClass = $app->make($this->service());
}