Skip to content

Using DataObjects

Greg Bowler edited this page Jun 20, 2023 · 1 revision

This library was intended to provide consistency throughout PHP.Gt repositories, but there's no reason your projects should not take advantage of its features.

There are two ways you will want to use this library: 1) Building a DataObject from a data structure, 2) Creating a DataObject with keys and values.

When building a DataObject from a data structure, you will use the DataObjectBuilder class. First, instantiate the object:

$builder = new Gt\DataObject\DataObjectBuilder();

Then, you have two functions: fromObject and fromAssociativeArray. PHP data structures can almost always be expressed as these primitive types. If your origin data does not conform to a simple object or associative array, you can use a function like array_walk to manipulate it first.

Using the DataObject class

Whether you've built a DataObject using the DataObjectBuilder or you've constructed one yourself, the DataObject instance you have is completely immutable. This means that all changes to the data will return a new instance rather than affecting the original.

Immutablility is made possible using the with and without functions. For example, we can create a new instance and call it "originalObject": $originalObject = new DataObject();. Within our code, we can then overwrite the reference to the original object every time we set a key-value: $originalObject = $originalObject->with("name", "Cody");.

Once we have a reference to a DataObject with its data set, we can pass it to other areas of the system. It doesn't matter what the other subsystems do with the object they are passed - because it is immutable, you can be confident that the data will never change. For example:

$originalData = (new DataObject())
->with("name", "Cody")
->with("colour", "orange");

// We are confident that between external calls, our $originalData can never be manipulated.
ProjectSubsystem::processUser($originalData);
AnotherSubsystem::doSomething($originalData);

Encapsulation

You can use the without function to provide certain subsystems with the data minus one or more keys. This could be useful if one system processes the user data, but another should not be able to see the user's personal details.

In the following simplified example, the $user variable is some kind of DataObject that contains personal information and sensitive credit card information. We can pass the entire object to the payment processor, but withhold the credit card information from the shipping processor.

$user = UserRepository::getLoggedInUser();

PaymentProcessor::takePayment($user);
ShippingProcessor::handleShipping($user->without("credit-card"));

Check out some examples.

Clone this wiki locally