I don’t think there is a “one true way” for this (no matter what you read about it) ... if that makes sense in your model, then that sounds good to me. I'm not quite sure what you mean when you say “many of these fields should be standardized” and why this cannot be done as part of UserEntity, but whatever. However, it is likely that you can accomplish exactly what you are trying to do without a completely separate class of objects.
Comments / Critical Reviews:
What you offer does not actually correspond to a strict "object" model, that is, UserData simply consists of things that are really UserEntity attributes, and there are no other fundamental relationships with these attributes.
I'm not sure why you need a separate object that will go outside the object ... if you need data, why can't you just bypass UserEntity and access it from there? What do you need to do with the data before passing it to the UserEntity constructor, which cannot be just as easily implemented when collecting data together in an stdClass instance and then processing it in UserEntity?
If it were me, I would do something more like the following (for example, to create a new user):
<? // assume an appropriately defined UserEntity class... // I'm using stdClass just to keep the parameters together to pass all at once // I'm assuming some basic user data passed from the browser $user_data = (object) array( 'email' => $_REQUEST['email'], 'name' => $_REQUEST['name'], 'password' => $_REQUEST['password'], 'confirm_password' => $_REQUEST['confirm_password'] ); /* validateData is static so it can be called before you create the new user It takes the $user_data object to validate and, if necessary, modify fields. It also takes a $create flag which indicates whether the data should be checked to make sure all of the necessary fields are there to create the user with. This allows you to call it on update with the $create flag unset and it will pass validation even if it missing otherwise required fields. It returns $result, which indicates pass or failure, and the potentially modified $user_data object */ $create = TRUE; list($result, $user_data) = UserEntity::validateData($user_data, $create); // equivalence allows you to pass back descriptive error messages if ($result === TRUE) { // create the user in the database, get back $user_id... $user = new UserEntity($user_id, $user_data); } else { // return error to user } // access user data either individually, or if you want just make a getter // for the entire group of data, so you can use it just like you would a // separate UserData object send_double_opt_in($user->getUserData()); ?>
Change address of additional information:
You say that these properties exist outside of UserEntity, and they can potentially live on their own ... Do you mean that these properties can be collected, used and discarded, not even intended for the UserEntity object? If this happens, then a separate object will be completely suitable for this data. If not, if the data is always subject to either the existing or the future UserEntity, then these properties will never "live independently" of ... let it be called "global data". When you look at the entire system as a whole, and not just code from moment to moment, it is likely that the data "belongs" to the UserEntity class.
As for static methods, I see no particular reason to avoid them (obviously), but for each of them. Many other architectures will be a little more complicated, but here are a few options:
- Confirm the data in the constructor. The problem is that if it is not checked, you will have to delete the database record. Ugly.
- Move database interaction with the designer along with data validation. This may violate your preferred object model, and you just need to check the status of the object after creating it (i.e. set the public property
$this->status = 'error'; or something like that to tell you that something happened it’s bad that you have to handle). - Create a standalone function to validate the data. Awful because it is a function that is specifically associated with UserEntity and / or its data.
- Or just create a separate UserData object, as you suggested, and do with it. As with step # 2, you need to have some kind of
$status property to indicate a failed check.