Can I bind public Eloquent Model properties?

I am little lost - what the 27 Dec release exactly provided in the terms of:
Enable setting Eloquent models and collections of models as public properties.

Can I do wire:model="product.title" or wire:click="$toggle('product.status')"?

So far, I am preparing property values for the model biding in my mount($id) method:

$this->product = Product::find($id);
$this->title = $this->product->title;
$this->price = $this->product->price;

And having public properties: $title, $price

If it’s not possible to bind data to model properties like wire:model="product.price", can you help me understand what’s so great about this 27 Dec release that brought “Model serialization to public properties”, please?

Anyone please feel free to correct or add on to this. For future readers, this is based on 0.7.0, and things could change.

The short answer: No, your model is not directly accessible in javascript, and properties cannot be bound.

Medium Answer:

Well, it is, kind of, but not in the way you want to use it; not in a way that you can bind the properties to inputs (more on that later). You can however ->toArray() it to a different public property and bind the properties with dot notation so you don’t end up with such a monster of a component defining a public property for each thing you want to bind. Syncing them back together, validation, and authorization is still on you.

Long Answer:

First, you have to understand the lifecycle of a livewire request. The quick and dirty of it is public properties and values are passed into javascript at the end of the request, user does something that changes data, and then they are passed back to php and reassigned at the beginning of each request. This is how livewire emulates state. Protected properties are not passed, and their state is not persisted.

Before the update, public property’s could only be data types that can be used by javascript, which model objects are not, so you had to assign models to a protected property. Also there would be a huge security opening by exposing the full contents of your model to javascript, so that alone is reason enough to not allow them to be public. Since that model wasn’t being sent back and forth between the back and front, it had to be saved somewhere to keep it’s state to be usable again on the next request, so protected properties were being saved to the cache.

Cool, problem solved right? Well not exactly. When you combine that:

  1. State is being stored in 2 spots,
  2. How the cache was being maintained to keep it manageable,
  3. Actions a user could do.

A certain mixture of the three would cause public and private properties to become out of sync, and things would break.

If you have worked with laravel’s queues, this is how it’s handled in the background when you pass a model to your queue. This also brings us to what is put into javascript from your model:

  • The model name/namespace
  • Database connection name
  • Id
  • Loaded relation names

This is what the queue worker uses to pull the model out of the database and do whatever needs done. The whole model is not being serialized and passed, only those four things. Or else we would be back to the problem of exposing to much to the front end. This is also why you can’t data bind in the way you were looking to do.

You can see this by going into your console and starting with livewire.components.componentsById. You will get a list of ids livewire uses, and the names you assigned of the components on the page. Tack on the id and then data: livewire.components.componentsById.{id}.data and you will see what javascript has.

So your queue, and now liviewire, has the information it needs to reach into the database and pull what it needs to work with. State is only in one spot and stays in sync, your model isn’t broadcasted to the world, and life is good.

Now why not just keep the model information there on the back end and hit the database every time instead of passing that information back and forth each time? Well it couldn’t be dynamic, and another behind the scenes aspect that was implemented with this is the database is only hit when it needs to. Without that life wouldn’t be good. If you have a text input and you’ve seen how many requests are sent back and forth as the user is typing, you don’t want your database being queried every time for no reason.

So in the end, it didn’t really change the way you code that much (although in a roundabout way it did give us computed properties). But with the other proposed solutions at the time to fix the problem, the way you code would have changed.

Hope that helps clear it up, and you can go more in depth here, here, and somewhere in here.

2 Likes

What an excellent answer xxdalexx! Very much appreciated, I have learnt a lot.