I think you may want to look at having a User Factory. You could have methods that take an array of data (from a form's POST) and return a User object. This lets you encapsulate the entire process of creating a new User object for use within your application (and persists to your datastore). You can do all of your try/catches in this single place and all your controllers just call this one function (code isn't scattered in all of your controllers).
class UserFactory
{
/** @var Doctrine Entity Manager */
private $_em;
function __construct(EntityManager $em) {
$this->_em = $em;
}
function createUserFromArray($data) {
$user = new User();
$user->setUsername($data['username']);
$user->setEmail($data['email']);
$this->_em->persist($user);
$this->_em->flush(); // Or this could be called from some other place
return $user;
}
}
Then in your controller all you do is something like this:
// Get the EntityManger from wherever (registry, session, etc)
$userFactory = new UserFactory($em);
$user = $userFactory->createFromArray($dataFromForm);
Two things additional things.
One, if you use explicit getters and setters for your properties (username and email) you can throw exceptions within those functions if they don't meet the criteria.
In your User class:
function setEmail($email) {
// Do some validations on the email address
if (!is_valid_email($email)) {
throw new Exception('Invalid Email');
}
$this->email = $email;
}
Two, I think this is the question you were really asking is about the lifecycle callbacks. You define those on/in your Model/Entity classes themselves.
class User
{
/** @PrePersist @PreUpdate */
function ensureUniqueEmail()
{
// Do your check, else throw exception
}
}