PHP Value Objects

I’ve been thinking about using value objects a lot in PHP. I’ve thought a bit about how best to implement so I gave it a shot. I’m still very early in development and I’ve only completed the emailAddress object and begun work on the phone number types, but I’d be interested in any thoughts that anyone has.

Likewise, I’d love it if anyone wanted to fork the repo and add their own types. I certainly need to pad it out further and finish the types that I started, and I’m interested in thoughts about the structure as it stands. I can see something really simple becoming quite complicated if I’m not careful.

I don’t know if you’ve seen it already, but I came across this site a while back: http://www.phpvalueobjects.info/. Among other things it, it links to this repo which seems to have a similar goal to your own.

Yeah, I’ve seen some of these, but they’re often over complicated and/or mutable, and I was trying to avoid that while still creating useful object. EmailAddress, for example, needs only to be validated and then retrieved on request (ie when you want to echo it, use it for DB insert etc). Phone number is a little different since you’ll be able to say this is a UK phone number and get it back in a couple of different formats. I expect that a Money type would do much the same; pass in a float value with a GBP validator, for example, and be able to return the value and do different things within the confines of what you can do with the £Sterling

Nice Antnee. Theoretically, any entity field needing validation could be a PVO, couldn’t it? One I am thinking of for sure is a plain postal address. There are a ton of rules to make up a complete postal address, depending on the country.

And hey looky looky! Following that link from fretburner, it leads to this.

https://github.com/nicolopignatelli/valueobjects/tree/master/src

and in it, there is this!

https://github.com/nicolopignatelli/valueobjects/blob/master/src/Geography/Address.php

I’ve been wondering about this for some time, as I need exactly this solution. Thanks guys! One to check of the list and I just learned a new technique.

Scott

This is exactly what I was trying to address (no pun intended). It’s technically going to be a PostalAddress object, but you may want to validate it as a UK address, a US address etc. You may want to format it in a way that includes the country (ie if you’re mailing abroad) or you may want a local address. You can’t put all of that in a single class without it bloating to high heaven. So I decided to go for passing in a validator object that defines the rules at runtime, rather than having a UKPostalAddress object, for example, which would probably extend the base PostalAddress object. The problem that I see with this solution is that I can type hint for a PostalAddress object, but I can’t easily type hint for the UK version if I’m composing it at runtime. Then again, maybe type hinting for this isn’t a good solution anyway and instead I should be doing something like if ('GB' == $address->country()) {}

Hmm…the validation and even the formatting is based on the country. I noticed the library I linked to actually formats the string output of the object to a US typical address, no matter what address it is holding. This wouldn’t really work, I don’t think. Should formatting or even string output even be part of the value object at all? Because, then I’d have to ask, what do you do when formatting numbers and currency? You’d need to know a locale value to properly format them.

Scott

True, you could simply store a value and pass that into a formatter of some kind. Primarily I was looking for things like getting the area code etc from a phone number. Or having an address object and getting the postcode from it. Personally, I’d build an address object from a combination of others, such as a name object, street, town etc

Yes, and the country code too! :smile:

That is what the other library I linked to does partially too. They have a country and street class, for instance. I like your approach better though, with the validation being done separately.

Scott

Yes, partially :slight_smile: They have a StringLiteral for a postcode, for example, presumably because a postcode is a difficult thing to validate globally. I’m not a fan of that solution, personally. I’d have built a postcode object and passed in a UKPostCode validator… but then you probably know that by now :smiley: Once you’ve got these things you can build a proper address.

This is my major sticking point with the different VO implementations that I’ve seen; they seem to just validate on their own and if I want to provide a different validator I need to extend the class. I wanted to do this at runtime from a collection of validators. I feel that this is more flexible and I’ll continue to take my solution that way. It’ll probably take a while to make it usable for anything other than pet projects, mind you; a simple concept that requires a LOT of work :slight_smile:

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.