-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow for Eloquent model attributes to be type juggled (casted). #4948
Conversation
Awesome! I have a lot of setters and getters converting integers to booleans at the moment. Hopefully this makes its way in, good work. |
Great idea, this is a lot more readable than a lot of accessors ;) |
Installing the php-mysqlnd extension will correctly cast data from MySQL to PHP variables, instead of everything being a string. |
@danharper Not everyone has enough control to setup PHP with the myslqnd driver. 😦 |
@danharper thanks :) I suppose this also allows you to override that without the need for a bunch of accessors. Almost everything in this PR can be done already with accessors, but it's a lot more code. |
Why is this necessary? This defeats the whole point of a dynamic type system. It doesn't matter what is returned from the database. As If anything, this should be handled automatically on the DBAL level, not the model level. |
Say you return an Eloquent model instance as the result of a route, forming a simple JSON API. All of the boolean values in the payload will be integers. Some floats might be strings. This ensures consistency over the types. You'd need either the extension that Dan mentioned, or a presenter to have the data in the correct format. |
This is great! And as this doesnt change things for people that don't want to use it, makes it even nicer! |
Looks great! |
Should it cast to type if the value is |
@daylerees - JavaScript is also dynamic. Unless an external API is consuming the data, it's irrelevant. |
@milesj just for external API this will be very helpful! I had issue in the past with boolean not being cast to bool and that broke everything. Thanks a lot for this code @daylerees |
@crynobone good call man. I've just sent a patch that should allow nulls to be respected, for testing. I may change it to remove the outer value checks, or perhaps the other way around, still thinking about it. I'll squash these commits when people are happy with it. |
This would come in very handy indeed! Thanks @daylerees 👍 |
Gooooood 👍 :) |
👍 |
1 similar comment
👍 |
Good! 👍 |
+1 |
Cool. :) |
👍 |
1 similar comment
👍 |
+1 This would also be huge for us stuck using MS SQL databases. Running a select * on a table with unsupported data types without casting them makes PDO silently fail without trigger any exceptions. Selecting columns by name ends up return false which obviously isn't very helpful. |
* | ||
* @return array | ||
*/ | ||
public function getDates() | ||
public function getCasts() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't this be done once in the boot
method? Just augment the casts
property and be done with it. Do we really have to spin through all this for every single attribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was replicating what was there for the getDates()
but I'll take a look at the possibility of using boot. :)
Also, we don't need this as an accessor. We should mutate the attributes in |
{ | ||
if ($value) | ||
{ | ||
$value = $this->fromDateTime($value); | ||
if ($casts[$key] === 'date') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already handled in castAttribute
, so no need to do it here again.
@JosephSilber Fair comments. :) I see what you mean about mutating in Thanks buddy! |
@daylerees Instead of flooding your PR with a gazillion more comments, I decided to make a sample implementation of what I was thinking. See here: github.com/JosephSilber/framework. That change also neatly implements the dates for Let me know what you think. |
I like it but other tools such as Fractal already solve the problem of data being returned as JSON and not being of the correct type. That takes it away from the model and also gives you more control over the data returned. |
@jasonlewis I don't see how taking this away from the model is a net benefit. IMO this falls squarely within the domain of the model. The model's job is to return the data as found in the DB, not some poor bastardized version of it. The fact that it is PDO's fault doesn't make it any better; as it stands, the model does not return the data as it is in the DB, and that responsibility lies solely on its shoulders. |
@JosephSilber Casting is not the model's responsibility, it's the DBAL. Whether it be the repository, or data mapper, the model shouldn't be casting. |
@milesj that might be true in a purer architecture, but Eloquent is an Active Record implementation and is therefore both the judge and the executioner. |
Eloquent still plugs into the Database layer though, which is completely separate. |
FWIW, I agree with @milesj. If this is going to go into Laravel, it shouldn't be done in Eloquent, this should be done lower down in the query builder or something. |
In case anyone is interested, the Esensi/Emerson Media team just released a new 0.3.3 version of the |
Right now if you retrieve an attribute from an Eloquent model, it may not be in the right format. For example, a
boolean
value in the database will be returned as aninteger
because Eloquent has no knowledge about the table schema.This PR solves this problem by providing the
$cast
array where you can specify default set/get attribute types for Eloquent model attributes. Here's an example.Now all of the attributes provided as keys in the above array, are set and retrieved in the appropriate type. As you can see, dates have been added to this
$cast
array as a replacement for$dates
due to their similarity. This change has been made backwards compatible, and will respect the original$dates
array to allow for hotfix.