-
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
[8.x] ArrayObject + Collection Custom Casts #36245
Conversation
This is brilliant |
This is excellent Taylor. Thanks! |
This is very handy while working with arrays, It's Awsome. |
Yes! Currently hand-rolling these for a better DX. Would love to see them as a first-class cast in the framework so there's some consistency between projects. |
You know I love it :) |
Came up against this exact thing a few days ago. Nice. What about the Could any of the current string based cast names be moved to this format too (still supported but documented in the same way these may be to provide consistency with things like dates and times that return carbon instances)? |
@timrspratt technically every cast can be turned into a custom cast - but there would be little benefit in doing so in practical terms. Especially for primitives like integers, etc. |
You saved a lot of extra lines in my code. |
*/ | ||
public function collect() | ||
{ | ||
return collect($this->getArrayCopy()); |
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.
Because the ArrayObject
is already Traversable
, you don't need to get an ->getArrayCopy()
here.
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 believe one of my project is exactly waiting for that
huge 👍 +1. please. |
Really love this! It could be awesome if we even could extend this so when using |
How can i get ride this error when the data have special characters ? "JSON: Malformed UTF-8 characters, possibly incorrectly encoded." I faced this issue when i cast my field to 'array'
|
Very helpful addition! |
Added encrypted counterparts. |
*/ | ||
public static function castUsing(array $arguments) | ||
{ | ||
return new class implements CastsAttributes { |
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 anonymous class makes me feel warm and fuzzy
This will come in very handy |
I've bumped into this a couple of time. Love the solution! |
@taylorotwell, you are getting close to what I already suggested over a year ago. At least this way we will come to this goal. P.S.: sorry for the trigger. You yourself asked the opinion of others 🙂 |
This is great! For a slightly more "typed" approach I created laravel-popo-caster just last week. Would love any feedback |
This is brilliant @taylorotwell .. I’ve been doing a hack around it |
return new class implements CastsAttributes { | ||
public function get($model, $key, $value, $attributes) | ||
{ | ||
return new ArrayObject(json_decode($attributes[$key], true)); |
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.
ArrayObject
construct will only take an array, or object. json_decode()
can possibly return bool
, null
among others.
(also worth noting json_decode()
does not handle invalid json, which you either have to use the exception flag for, or json_last_error()
)
https://www.php.net/manual/en/function.json-decode.php#refsect1-function.json-decode-returnvalues
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.
Then PHP will throw an error if it is not an error - which is what I would want to happen in this case. The column assigned this cast should always contain something that can be decoded to an array.
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.
That is bad. Throws an exception web DB column is nullable (and item is null).
FormEntry Factory class was causing errors on line #66. This was happening because in Laravel, a column cast to an array only allows mutation of the entire array, rather than one property. Details here: laravel/framework#36245
This PR implements an opt-in
AsArrayObject
andAsCollection
custom cast.Background
Of course, Laravel already includes an ability to cast a JSON / TEXT column that contains JSON to an array or collection like so:
However, this does have some downsides. First, the following code is impossible using the simple
array
cast:Many developers probably expect this to work, but it doesn't. It is impossible to mutate a specific property of the primitive array returned by this cast. You must mutate the entire array:
AsArrayObject + AsCollection
However, these new casts utilize Eloquent's custom cast feature which implements more intelligent management and caching of objects. The
AsArrayObject
cast will cast the underlying JSON string to a PHPArrayObject
instance. This class is included in the standard library of PHP and allows an object to behave like an array. Such an approach makes the following possible:However, it should be noted that an
ArrayObject
can not be fed into array functions likearray_map
, so you must use$user->options->toArray()
to access the raw underlying array if you wish to use the array in this way. You may also use$user->options->collect()
to get aCollection
instance from theArrayObject
.Similar benefits are derived from the
AsCollection
cast - this cast is similar to the existingcollection
class, but because of the better object caching and management of custom casts, you are able to mutate singular properties on the collection or even push to the collection.Final Thoughts
The existing
array
andcollection
casts would not be removed from the framework. However, it may be wise to primarily document these new casts (if they are accepted) in the future as they are a bit more robust and developer friendly.