How to Insert a validation before DB INSERT (SLIM4 API SKELETON)

I’m working with SLIM4 API SKELETON by Mauro Bonfietti.

From my little experience, I was able to run the app and include CRUDs for my tables. Now to mold the app to my needs.

There are the Sevice and Repository phps for each table. I would like to add a CONDITION before a create/insert is done.

As an example, I have a visits table. It has visitor_id and datetime of visit. every time this visitor visits, the app inserts the visitor_id and the datetime of visit. As for the condition, let us say, the app only insert a record if the visitor’s last visit is more than 10mins older than the current visit.

You just need to fetch your visits table by your visitor_id before, and in case if the result is not empty compare datetime registered with the current one. Afterwards, depending on the result you process insert/update or not.

Thanks for the reply, what I’m looking for though is ‘where/how’ to code.

Do I create a function that checks for the condition within the visitsservice or visitsrepository. After checking with the condition, how do I code if the condition checks and at the same time if it doesn’t satisfy the condition.

Also, there is a directory for visits inside Controller directory, too.

Lets start with the basics - basic CRUD flow code structure:

  1. First option:
  • 4 routes - CREATE visit, READ visit, UPDATE visit, DELETE visit
  • 1 controller - VisitController
    • with VisitService injected into contstructor
    • with 4 actions(methods) create, get, update, delete calling related VisitService methods
  • 1 service - VisitService
    • with injected VisitRepository
    • with 4 methods create, get, update, delete
  1. Second option:
  • 4 routes - CREATE visit, READ visit, UPDATE visit, DELETE visit
  • 4 action controllers - CreateVisitActionController, etc.
    • each one with VisitService injected into contstructor
    • each one with single __invoke method calling related VisitService method
  • 1 service - VisitService
    • with injected VisitRepository
    • with 4 methods create, get, update, delete
  1. Third option:
  • 4 routes - CREATE visit, READ visit, UPDATE visit, DELETE visit
  • 4 action controllers - CreateVisitActionController, etc.
    • each one with its proper ActionService injected into constructor or as a parameter of __invoke method
    • each one with single __invoke method calling related VisitActionService by its __ivoke method
  • 4 action services - CreateVisitActionService, etc.
    • each one with injected VisitRepository
    • each one with with single __invoke method
  1. My favorite option:
  • 4 routes - CREATE visit, READ visit, UPDATE visit, DELETE visit
  • 1 controller - VisitController
    • with 4 actions(methods) create, get, update, delete
    • with 4 VisitActionServices injected as parameter into proper controller’s action(method) - CreateVisitActionService, etc…
  • 4 action services - CreateVisitActionService, etc.
    • each one with injected VisitRepository into constructor
    • each one with with single __invoke method

No matter which option you select, your issue is related to create/add process, so alternatively:

  • in your VisitService create() method or
  • in your CreateVisitActionService __invoke method you are supposed to call your VisitRepository two times depending on the situation:
    • $this->visitRepository->getById($id)
    • check required condition
    • and (or not) $this->visitRepository->create($visit)
1 Like

Just a follow, is this true if I also want to add additional information to the result.

For example, I GET an array filled with visit count by category/type. Then I want to add percentage per category/type of visit.

Regardless of an approach, it is important to leave CRUD’s actionService or service’s methods (I mean those which are able to query database) as generic as possible.
You can query count but correct me if I am wrong with percent it is not that obvious.
If you need any additional operations (transformations, calculations) do it by an additional service having appropriate method that accepts generic results of the first one as a parameter and returns them as you need:

Controller’s action example without additional transformations:

    public function getCategoriesCount(
        Request $request,
        Response $response,
        GetCategoriesCountAction $action
    ): Response {
        return ($this->responder)(
            $response,
            $action($request)
        );
    }

Controller’s action example with additional transformations:

    public function getCategoriesPercentage(
        Request $request,
        Response $response,
        GetCategoriesCountAction $action,
        TransformationService $service
    ): Response {
        $result = $action($request);
        return ($this->responder)(
            $response,
            $service->transformCountIntoPercentage($result)
        );
    }