Jump to content
NotionCommotion

Where should validation be performed?

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
    }
}

 

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

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.