DataMapper validation

Hi

I’ve searched through the topics, but hadn’t found an answer to that.
I’ve been struggling with my domian model for the last few days, trying different patterns. I’ve kinda settled on the DataMapper and friends, but one thing still buffles me - validation.

Let me explain it with some code.

class UserMapper {
        
    function __construct (DB $db) {
        $this->db = $db;
    }   

    function find($id) {
        // find user in the db
        $user = new User;
        $user->id = $result->id;
        [...]
        return $user;
    }   

    public save(User $user) {
        // save user
    }   

}

class User {
        
    public  $id,
            $name;

}



In my controller I would use something like

class UserController {

    function __construct(UserMapper $mapper) {
        $this->mapper = $mapper;
    }   
    
    function action() {
        $user = $this->mapper->find(1);
        $user->name = 'John';
        $this->mapper->save($user);
    }
    
}   

There are different approches to validation, some people do not allow their domain objects to become invalid, some people allow and validate before saveing etc. Personally I find the latter approach more practical.

I liked the rails approach to validation - definig rules in the Domain object, but as rails uses AR, I found it a bit of a hack to use in my case.

I could create is_valid method in User class, but this way I would be able to validate only the simple cases like enforce variable type etc.
But what about enforcing uniqueness? I would have to get access to my mapper, which smells.

I also don’t like putting validation logic in my Mapper, somehow it doesn’t feel right. Maybe I should move it to a Validation class like UserValidation and make it a dependency on my Mapper? Or inject the UserValdiation object from a Controller…

But then again, should the UserValidation make queries (like checking unique values), or ask Mapper for db stuff?

I’m totally confused. I’ve read tons of material recently, mostly from Java world, but I feel even more lost than before…

Thanks!

DataMapper != Model.

You’re missing a proper model entirely, the controller should not know of the mapper directly. The model should access the datamapper, do the validation and your controller should access the model only. This way all your validation and data manipulation logic is entirely reusable. :slight_smile:

What exactly do you mean by “Model” and “The model” ? Because it’s not clear from your response.
Also, what’s wrong with controller talking to the mapper? I’ve seen it in a lot of places and I’ve never thought there’s something wrong with it.

Thanks

The model is the part of the system which contains your validation, datamappers, domain logic, etc.

Most MVC frameworks don’t include a proper model (see http://blog.astrumfutura.com/2008/12/the-m-in-mvc-why-models-are-misunderstood-and-unappreciated/ for a good explanation)

Essentially the model contains what you have in your controller code.

As a very rough example:


<?php

class UserModel {
	public function validate($details) {
		//
	}

	public function save($details, $id = null) {
		if ($this->validate($details)) {
			if ($id != null) $user = $this->userMapper->find($id);
			else $user = $this->userMapper->create();

			foreach ($details as $key => $value) $user->$key = $value;

			$this->userMapper->save($user);
		}		
	}

}

class UserController { 

    function __construct(UserModel $model) { 
        $this->model = $model; 
    }    
     
    function action() { 
	//simple example...
        $this->model->save($_POST['user'], $_POST['id']);
    } 
     
}  
?>

The point here is reusability. Any part of the system can now update the user details because the logic behind it is removed from the controller (which is really part of the presentation layer). Models can talk to each other too, which gives you a lot of possibilities, especially when you have related data.

Just be sure you never use “Model” as part of the class name for a model class. Otherwise, a bunch of folks will come out of the wood work and tell you how wrong you are.

So call UserModel something else.

I had a model class once. It was for the models table. The website incidentally was a modeling agency. The girls were pretty but the dual meaning of the term ‘model’ for that site hurt my head.