Sometimes, the defined relations in our model can be incorrect. That's normal and we're just developers. Well, even AI-devs like ChatGPT or Copilot can make mistakes, not just us. That's where all those testing and validation tools are invaluable.
Silverstripe Framework comes with a tool called
RelationValidationService that checks if the relationships are set up correctly in both directions. It's run on every dev/build. That's good. But unfortunately, you have to configure it a little bit, and then it may shout out a long red list when running dev/build?flush.
Like in real life, even if you think your relations are fine, they could be more perfect. It's always worth improving relations, so what are the common mistakes for Silverstripe ORM relations?
Well, this is easy to spot. Dev/build will break and you're forced to fix it.
has_one to e.g.
Image. Technically it works, but for Silverstripe it's better to know what's the relation back, even if you don't use it in your code. Who knows, maybe a future developer (read: you) want's to crate a task that checks if an image is used somewhere or if the image can be deleted, then the relation back can be used.
Sometimes, Silverstripe expects you to write
ClassName.RelationName. to fully understand your relations.
The back relations of a
has_many is a
has_one. And if, for some reason, the other class has two
has_ones to the original class, we all get confused, not only Silverstripe`s ORM.
In order to switch on
RelationValidationService on every dev/build, you need to configure the namespaces of the
DataObjects you want to be validated, and you need to enable output by default.
--- Only: environment: 'dev' --- SilverStripe\Dev\Validation\RelationValidationService: output_enabled: true allow_rules: myNamespace: MyCompany
Then you see a bunch of errors, can go through your code and adjust the relation namings, e.g. convert
public static array $has_many = [ 'PhotoGalleryImages' => PhotoGalleryImage::class ];
public static array $has_many = [ 'PhotoGalleryImages' => PhotoGalleryImage::class. '.Album' ];
if the relation back is called "Album".
For third party
DataObjects you refer to, you can use yaml config to add relations back, e.g.:
SilverStripe\Assets\Image: belongs_to: Event: MyProject\Model\Event.Image Notification: MyProject\Model\Notification.Image
I think this tool should be switched on by default in dev environments. In an ideal world you hook it to your unit tests to get warnings as soon as possible.
More information about RelationValidationService , e.g. how it can be included in unit tests, can be found in the documentation.