-
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,6 +129,13 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa | |
*/ | ||
protected $dates = array(); | ||
|
||
/** | ||
* Attributes that are to be casted to a different type. | ||
* | ||
* @var array | ||
*/ | ||
protected $cast = array(); | ||
|
||
/** | ||
* The relationships that should be touched on save. | ||
* | ||
|
@@ -2164,14 +2171,14 @@ public function attributesToArray() | |
{ | ||
$attributes = $this->getArrayableAttributes(); | ||
|
||
// If an attribute is a date, we will cast it to a string after converting it | ||
// to a DateTime / Carbon instance. This is so we will get some consistent | ||
// formatting while accessing attributes vs. arraying / JSONing a model. | ||
foreach ($this->getDates() as $key) | ||
// PLACEHOLDER FOR TAYLOR COMMENT | ||
// Iterate the castable fields, and if the field is present | ||
// cast the attribute and replace within the array. | ||
foreach ($this->getCasts() as $key => $type) | ||
{ | ||
if ( ! isset($attributes[$key])) continue; | ||
|
||
$attributes[$key] = (string) $this->asDateTime($attributes[$key]); | ||
$attributes[$key] = $this->castAttribute($type, $attributes[$key]); | ||
} | ||
|
||
// We want to spin through all the mutated attributes for this model and call | ||
|
@@ -2337,14 +2344,36 @@ protected function getAttributeValue($key) | |
return $this->mutateAttribute($key, $value); | ||
} | ||
|
||
// If the attribute is listed as a date, we will convert it to a DateTime | ||
// instance on retrieval, which makes it quite convenient to work with | ||
// date fields without having to create a mutator for each property. | ||
elseif (in_array($key, $this->getDates())) | ||
// PLACEHOLDER FOR TAYLOR COMMENT | ||
// If the field is present in the castable array, then | ||
// retrieve the intended type, and return the casted | ||
// value. | ||
elseif (array_key_exists($key, $casts = $this->getCasts())) | ||
{ | ||
if ($value) return $this->castAttribute($casts[$key], $value); | ||
} | ||
|
||
return $value; | ||
} | ||
|
||
/** | ||
* Cast an attribute to a new type. | ||
* | ||
* @param string $type | ||
* @param mixed $value | ||
* @return mixed | ||
*/ | ||
protected function castAttribute($type, $value) | ||
{ | ||
$type = strtolower($type); | ||
|
||
if ($type === 'date') | ||
{ | ||
if ($value) return $this->asDateTime($value); | ||
} | ||
|
||
if ($value !== null) settype($value, $type); | ||
|
||
return $value; | ||
} | ||
|
||
|
@@ -2440,14 +2469,22 @@ public function setAttribute($key, $value) | |
return $this->{$method}($value); | ||
} | ||
|
||
// If an attribute is listed as a "date", we'll convert it from a DateTime | ||
// instance into a form proper for storage on the database tables using | ||
// the connection grammar's date format. We will auto set the values. | ||
elseif (in_array($key, $this->getDates())) | ||
// PLACEHOLDER FOR TAYLOR COMMENT | ||
// If the attribute being set is held within the castable array | ||
// then cast before setting the attribute. Date types are handled | ||
// seperately due to being complex objects. | ||
elseif (array_key_exists($key, $casts = $this->getCasts())) | ||
{ | ||
if ($value) | ||
{ | ||
$value = $this->fromDateTime($value); | ||
if ($casts[$key] === 'date') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is already handled in |
||
{ | ||
$value = $this->fromDateTime($value); | ||
} | ||
else | ||
{ | ||
$value = $this->castAttribute($casts[$key], $value); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -2466,15 +2503,25 @@ public function hasSetMutator($key) | |
} | ||
|
||
/** | ||
* Get the attributes that should be converted to dates. | ||
* Get the attributes that should be cast upon retrieval. | ||
* | ||
* @return array | ||
*/ | ||
public function getDates() | ||
public function getCasts() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't this be done once in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was replicating what was there for the |
||
{ | ||
$defaults = array(static::CREATED_AT, static::UPDATED_AT); | ||
// PLACEHOLDER FOR TAYLOR COMMENT | ||
// This block allows for backwards compatibility with $dates by | ||
// merging values present in the original date array with our | ||
// defaults. | ||
$originals = array(); | ||
foreach ($this->dates as $key) | ||
{ | ||
$originals[$key] = 'date'; | ||
} | ||
|
||
$defaults = array(static::CREATED_AT => 'date', static::UPDATED_AT => 'date'); | ||
|
||
return array_merge($this->dates, $defaults); | ||
return array_merge($this->cast, $originals, $defaults); | ||
} | ||
|
||
/** | ||
|
@@ -2667,7 +2714,7 @@ public function getDirty() | |
$dirty[$key] = $value; | ||
} | ||
elseif ($value !== $this->original[$key] && | ||
! $this->originalIsNumericallyEquivalent($key)) | ||
! $this->originalIsNumericallyEquivalent($key)) | ||
{ | ||
$dirty[$key] = $value; | ||
} | ||
|
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 won't change
0
tofalse
.