Making Laravel Nova custom fields more developer-friendly

We have an incredible ORM working behind the scenes, Eloquent.

It will take care of transforming our field’s output into the value we want it to be when its time has come.

The only thing we need to do is to explain how to achieve this transformation.

That’s something we can do using PHP’s magic methods, like __toString.

In case of a desired JSON result, we could even implement the JsonSerializable interface.

If the value is retrieved as an array, Laravel’s Collections are probably the way to go.

It doesn’t necessarily need to be hard to implement, most of the time it will make the code more readable, testable and maintainable.

Okay, but… when does a field return its wrapped value?Technically speaking, we do not return a value when working with Nova fields.

The field directly hydrates models using its extended fillAttributeFromRequest method, “storing” its value directly on the concerned model.

When another field needs to interact with this value, it could use the model to access the targeted attribute.

Laravel Nova’s documentation shows a very straightforward example on how to store direct request input on the model:Most of the time however, complex fields need to act upon the provided request data, meaning the data is first treated by some custom methods:This approach requires to write a lot of value treatment logic in the field itself.

Instead, we could extract those methods into a value object, where all the value treatment would take place.

This way, our core Field class remains tidy and the Value class can now become the subject of its own specific unit tests.

Furthermore, by implementing serialization interfaces on the Value class, we don’t even need to extract the treated value before assigning it to the model’s attribute.

Without knowing it, we didn’t only implement a few good code design principles, we also opened the door to a new world of value sharing between field packages.

In the last example, our MySerializableNovaFieldValue class can now implement interfaces that provide useful information to other third-party actors.

The JsonSerializable interface is probably one of the most straightforward examples, but why not go further?.Maybe some day we’ll find common patterns in field interactions that could be translated into “official” Nova interfaces, providing the missing collective view.

Am I dreaming out loud or could this become a reality?.Let’s find out.

One thing I didn’t mention yet is that a similar scenario could take place during a field’s resolving process since it could also be exploited or displayed in other related complex fields.

Why not use the same Value class during the field resolving and the attribute filling processes?.It certainly depends on the field’s specificities, but it’s worth thinking about.

What now?I’ve been using Laravel Nova on a few projects and have searched for, installed and built some packages to improve its interface or features.

One thing I learned is that most other developers are doing the same, but nobody really uses those packages in the same way or for the same purposes.

We’re all pretty creative when it comes to implementing tools.

Let’s make each other’s life easier by creating adaptable packages or at least understandable results, especially when we’re talking about packages handling small bits of complicated user interfaces, such as Nova Fields.

I’m sure there are plenty other things worth mentioning in this topic and that some important use cases were left out.

Can you think about some of them?.I’d be glad to discuss them, let me know on Twitter!.

. More details

Leave a Reply