Models are one of the most important building blocks to any well-formed application, but a few common misconceptions persist throughout the development community that can make working with models excruciating. A properly constructed model should not only be powerful, but it should be extremely easy to work with.
While models do contain specific data, they are far more than simple data structures. They should contain all logic possible to manage, manipulate, and validate the correctness of data as it is updated. By treating your models as nothing more than a place to dump your data, you are doing yourself and your application a severe disservice; your business logic is going to be scattered throughout the rest of your application, and you will have a progressively more difficult time as you try to maintain and build upon your existing system. Do not fall into the anemic model trap.
In addition, models should be independent of the data-access layer. If I am modeling a blog article, the article should not know nor care to know whether it was created from a mysql database, an xml file, user input, or the divine spaghetti monster. No matter how it was populated or where it was persisted, the blog article is a blog article, and that is all that is important.
To manage my data access, I am a huge proponent of Doctrine 2. Of which, one of my favorite features is that my models are completely decoupled from Doctrine itself. This means there is no base model class that defines a ton of functionality for interacting with your data abstraction, so you have near endless flexibility when it comes to creating your models. However, just because you are not required to extend a base record class does not mean that working with many of your models cannot be improved with some simple, abstract implementations. Utilizing a simple abstract model and a few best practices can ensure your models remain incredibly versatile while still preserving the strict integrity of your data.
Let’s start with a simple blog article model:
In our AbstractModel, we will utilize php’s magic methods to provide access to our entity properties in both a convenient and secure way. All calls to retrieve a property’s value will map through an appropriate accessor if one exists, and all attempts to set an entity property will map through an appropriate mutator if one exists.
With these simple methods, our protected entity properties are accessible like public properties, but individual models can ensure that their access and modification is still bound by filtering/validation through mutators and accessors. Let’s implement some of these in our article model:
With that, our article model filters and validates incoming and outgoing data. Our article date is set immediately upon instantiation, the title is always trimmed and its length validated, the date can be set by multiple different types of values but is always stored as a DateTime, and we can utilize a convenience accessor (even as a property) to get the date formatted as a string.
If you are the type of developer that insists on having 100% data integrity in your models at all times, you could take this filtering and validation one step further by passing all required fields as arguments in the constructor. On the other hand, if you’re like me you would abstract out the logic for handling data validation, so you could reuse the validation in forms that accept input from the user to populate your models and create a prePersist lifecycle callback (Doctrine only) that runs through the validation before a new model is persisted in the database.
To finish this up, here are some ad hoc examples of code using the ArticleModel: