Jump to content

Where should validation be performed?


NotionCommotion

Recommended Posts

Where should the validation take place?  Several options include:

  1. In the Slim closure.  i.e. $app->get('/', function(){/* validate before calling service */})
  2. In the service.
  3. In the mapper.
  4. In the entity domain.

I can easily create the standalone Validator class to validate scenarios such as whether a property is provided and whether it meets certain rules, however, other scenarios such as whether a record exists is closely linked to the mapper.  Also, the entity does a good job confirming that the write properties are being provided.  How important is it to locate validation at one place?

Thanks

<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

$c = new \Slim\Container();

$c['validator'] = function ($c) {};
$c['pdo'] = function ($c) {};

$c['resourceService'] = function ($c) {
    return new Resource\ResourceService(
        new Resource\ResourceMapper(
            $c['pdo'],
            $c['validator']
        ),
        $c['validator']
    );
};

$c['resourceResponder'] = function ($c) {};
$app = new \Slim\App($c);

$app->get('/someResource', function (Request $request, Response $response) {
    return $this->resourceResponder->index($response, $this->resourceService->index($request->getQueryParams()));
});
$app->get('/someResource/{id:[0-9]+}', function (Request $request, Response $response, $args) {
    return $this->resourceResponder->detail($response, $this->resourceService->read($args['id']));
});
$app->post('/someResource', function (Request $request, Response $response, $args) {
    return $this->resourceResponder->create($response, $this->resourceService->create($request->getParsedBody()));
});
$app->put('/someResource/{id:[0-9]+}', function (Request $request, Response $response, $args) {
    return $this->resourceResponder->update($response, $this->resourceService->update($args['id'], $request->getParsedBody()));
});
$app->delete('/someResource/{id:[0-9]+}', function (Request $request, Response $response, $args) {
    return $this->resourceResponder->delete($response, $this->resourceService->delete($args['id']));
});

$app->run();
class ResourceService
{
    protected $mapper, $validator;

    public function __construct(Mapper $mapper, Validator $validator) {
        $this->mapper = $mapper;
        $this->validator = $validator;
    }

    public function index(array $params=[]):array {
        $index = $this->mapper->index($params);
        return $index;
    }

    public function read(int $id):Entity {
        $entity = $this->mapper->read($id);
        return $entity;
    }

    public function create(array $params):int {
        $entity=$this->mapper->create($params);
        $id=$this->mapper->save($entity);
        return $id;
    }

    public function update(int $id, array $params):int {
        $this->update->update($id, $params);
        return $id;
    }

    public function delete(int $id):null {
        $this->mapper->delete($id);
    }

}
class ResourceMapper
{
    protected $pdo, $validator;

    public function __construct(\Pdo $pdo, Validator $validator) {
        $this->pdo = $pdo;
        $this->validator = $validator;
    }

    public function index(array $params=[]):array {
        //query DB and return an array of Resources
    }

    public function read(int $id):Entity {
        if(!$params=$this->queryDatabase($id)) {
            throw new \Exception("ID $id does not exist");
        }
        return new Resource($params);
    }

    public function create(array $params):int {
        //Or should the service create the entity?
        return new ResourceEntity($params);
    }

    public function save(Entity $entity):int {
        //Save the data.  What if a duplicate error?
        return $this->pdo->lastInsertId();
    }

    public function update(int $id, array $params):null {
        //update database.  What if id doesn't exist?
    }

    public function delete(int $id):null {
        //Delete from DB.  What if id doesn't exist or foreign key constraint?
    }

}
class ResourceEntity
{
    public function __construct(array $params, Validator $validator) {
        //As applicable
    }
}

 

Link to comment
Share on other sites

On 1/12/2019 at 9:53 AM, NotionCommotion said:

How important is it to locate validation at one place?

Less important than separation of concerns and the single responsibility principle.

You can always propagate errors up through the stack. Exceptions are good for that, and with them you can wrap low-level exceptions as they come up.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.