Skip to content
Advertisement

Cannot call abstract method interface in Service-Repository pattern

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());
}
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement