I am implementing the Repository Pattern (service) in a Laravel application and I have some doubts about the usage of interfaces with these services.
I have created an interface called CRUD
(code bellow) to serve as a way to always keep the same names for the services that are going to implement CRUD methods.
<?php
namespace AppInterfaces;
interface CRUD
{
public function create(array $data);
public function update(int $id, array $data);
public function delete(string $ids);
};
Bellow there’s an example of how I call my service and the service itself, and that’s where my doubts are. Usually I’ll see people witing an interface for each service and demanding the controller to have injected an objet of that type. Because of that, people will have to bind a specific type (interface) to the controller. It seems redundant and thus I simply passed the service I need.
Now, is this ok or I should pass the CRUD interface to the controller in this case? Or should I even create another interface specifically for each service?
<?php
namespace AppHttpControllersCms;
use AppHttpControllersController;
use AppHttpRequestsGroupRequest;
use AppModelsGroup;
use AppServicesGroupsService;
use IlluminateHttpRequest;
class GroupsController extends Controller
{
private $service;
public function __construct(GroupsService $service)
{
$this->service = $service;
}
public function store(GroupRequest $request)
{
$result = $this->service->create($request->all());
return redirect()->back()->with('response', $result);
}
public function update(GroupRequest $request, $id)
{
$result = $this->service->update($id, $request->all());
return redirect()->back()->with('response', $result);
}
public function destroy($groups_id)
{
$result = $this->service->delete($groups_id);
return redirect()->back()->with('response', $result);
}
}
<?php
namespace AppServices;
use AppModelsGroup;
use AppInterfacesCRUD;
use Exception;
class GroupsService implements CRUD
{
public function listAll()
{
return Group::all();
}
public function create(array $data)
{
$modules_id = array_pop($data);
$group = Group::create($data);
$group->modules()->attach($modules_id);
return cms_response(trans('cms.groups.success_create'));
}
public function update(int $id, array $data)
{
try {
$modules_ids = $data['modules'];
unset($data['modules']);
$group = $this->__findOrFail($id);
$group->update($data);
$group->modules()->sync($modules_ids);
return cms_response(trans('cms.groups.success_update'));
} catch (Throwable $th) {
return cms_response($th->getMessage(), false, 400);
}
}
public function delete(string $ids)
{
Group::whereIn('id', json_decode($ids))->delete();
return cms_response(trans('cms.groups.success_delete'));
}
private function __findOrFail(int $id)
{
$group = Group::find($id);
if ($group instanceof Group) {
return $group;
}
throw new Exception(trans('cms.groups.error_not_found'));
}
}
2
Answers
If you want to use Repository Design Patteren You have to create seprate Interface for each service accroing to SOLID Principle. You have to create custom service provider and register your interface and service class and then inject interface in construtor of controller.
You can also follow below article.
https://itnext.io/repository-design-pattern-done-right-in-laravel-d177b5fa75d4
I did something with repo pattern in laravel 8 you might be interested:
thats how i did it:
first of all, you need to implement a provider
in this file i created the binding:
then in file:
in file:
AppRepositoriesEventStreamRepository.php
in file:
AppHttpControllersEventStreamController.php
note: i think i removed all unnecessary -validations- and -returns- in controller for better reading.
Hope it helps!!