10000 [6.x] Added creation of custom Cast classes for Eloquent by andrey-helldar · Pull Request #30958 · laravel/framework · GitHub
[go: up one dir, main page]

Skip to content

[6.x] Added creation of custom Cast classes for Eloquent #30958

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

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4d4c098
[6.x] The `hasAttributes` trait is divided into two: `hasAttributes` …
Dec 27, 2019
1dfd194
[6.x] Added creation of custom Cast classes for Eloquent
Dec 27, 2019
3920b01
[6.x] Added make console command of custom Cast
Dec 27, 2019
67e2562
Updated codestyle
Dec 27, 2019
3914f73
Fixed docblocks
Dec 28, 2019
ec1ba01
Fixed docblock
Dec 28, 2019
f67cb97
Fixed transfer of null value to custom castes
Dec 28, 2019
38b62f9
Fixed getting values for custom castes
Dec 28, 2019
f7689b4
Added verification and storage of initialized instances of custom castes
Dec 28, 2019
0503111
Fixed null-casting test
Dec 28, 2019
99f4ded
Fixed procedure for checking NULL values
Dec 28, 2019
27eb546
Added test for checking NULL values
Dec 28, 2019
4b8a2d1
Fixed `return null` style-ci errors
Dec 28, 2019
0954ebf
Fixed cast.stub file for the custom Cast console command creating
Dec 28, 2019
ad8adbc
Changed the variable name from snake_case to camelCase.
Dec 29, 2019
6fa8bd1
Updated docblocks
Dec 29, 2019
febda92
Updated make:cast command description
Dec 29, 2019
d5ddc3b
Updated test for DateTime custom case testing
Dec 29, 2019
ce3985a
Added the ability to store the key and the original value in custom c…
Dec 29, 2019
e578d21
The `get` and `set` methods are renamed `fromDatabase` and `toDatabas…
Dec 29, 2019
92db2cd
The `hasAttributes` trait split has been canceled
Dec 29, 2019
eb397ef
Small fixed code in the `hasAttributes` trait
Dec 29, 2019
064353a
`array_key_exists` function replaced with faster `isset`
Dec 30, 2019
3e51364
Replaced class instance creation method
Dec 30, 2019
493e4d7
Added method call skipped when canceling the separation of traits
Dec 30, 2019
13ceace
The principle of creating a container has been changed
Dec 30, 2019
3446cbe
Added a docblock for the `registerCastMakeCommand` method
Dec 30, 2019
d62cd8d
Storage of custom Cast instances transferred to the global static arr…
Dec 30, 2019
14720d4
Updated docblock
Dec 30, 2019
b8adc68
Replaced `new $cast` by Container make method
Dec 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[6.x] The hasAttributes trait is divided into two: hasAttributes
…and `hasCasts`
  • Loading branch information
Andrey Helldar committed Dec 27, 2019
commit 4d4c098ffe8fdf309898a09a4f4a9c4b451c35d6
257 changes: 0 additions & 257 deletions src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
use Carbon\CarbonInterface;
use DateTimeInterface;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\JsonEncodingException;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection as BaseCollection;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Str;
use LogicException;
Expand Down Expand Up @@ -37,13 +35,6 @@ trait HasAttributes
*/
protected $changes = [];

/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [];

/**
* The attributes that should be mutated to dates.
*
Expand Down Expand Up @@ -163,47 +154,6 @@ protected function addMutatedAttributesToArray(array $attributes, array $mutated
return $attributes;
}

/**
* Add the casted attributes to the attributes array.
*
* @param array $attributes
* @param array $mutatedAttributes
* @return array
*/
protected function addCastAttributesToArray(array $attributes, array $mutatedAttributes)
{
foreach ($this->getCasts() as $key => $value) {
if (! array_key_exists($key, $attributes) || in_array($key, $mutatedAttributes)) {
continue;
}

// Here we will cast the attribute. Then, if the cast is a date or datetime cast
// then we will serialize the date for the array. This will convert the dates
// to strings based on the date format specified for these Eloquent models.
$attributes[$key] = $this->castAttribute(
$key, $attributes[$key]
);

// If the attribute cast was a date or a datetime, we will serialize the date as
// a string. This allows the developers to customize how dates are serialized
// into an array without affecting how they are persisted into the storage.
if ($attributes[$key] &&
($value === 'date' || $value === 'datetime')) {
$attributes[$key] = $this->serializeDate($attributes[$key]);
}

if ($attributes[$key] && $this->isCustomDateTimeCast($value)) {
$attributes[$key] = $attributes[$key]->format(explode(':', $value, 2)[1]);
}

if ($attributes[$key] instanceof Arrayable) {
$attributes[$key] = $attributes[$key]->toArray();
}
}

return $attributes;
}

/**
* Get an attribute array of all arrayable attributes.
*
Expand Down Expand Up @@ -468,95 +418,6 @@ protected function mutateAttributeForArray($key, $value)
return $value instanceof Arrayable ? $value->toArray() : $value;
}

/**
* Cast an attribute to a native PHP type.
*
* @param string $key
* @param mixed $value
* @return mixed
*/
protected function castAttribute($key, $value)
{
if (is_null($value)) {
return $value;
}

switch ($this->getCastType($key)) {
case 'int':
case 'integer':
return (int) $value;
case 'real':
case 'float':
case 'double':
return $this->fromFloat($value);
case 'decimal':
return $this->asDecimal($value, explode(':', $this->getCasts()[$key], 2)[1]);
case 'string':
return (string) $value;
case 'bool':
case 'boolean':
return (bool) $value;
case 'object':
return $this->fromJson($value, true);
case 'array':
case 'json':
return $this->fromJson($value);
case 'collection':
return new BaseCollection($this->fromJson($value));
case 'date':
return $this->asDate($value);
case 'datetime':
case 'custom_datetime':
return $this->asDateTime($value);
case 'timestamp':
return $this->asTimestamp($value);
default:
return $value;
}
}

/**
* Get the type of cast for a model attribute.
*
* @param string $key
* @return string
*/
protected function getCastType($key)
{
if ($this->isCustomDateTimeCast($this->getCasts()[$key])) {
return 'custom_datetime';
}

if ($this->isDecimalCast($this->getCasts()[$key])) {
return 'decimal';
}

return trim(strtolower($this->getCasts()[$key]));
}

/**
* Determine if the cast type is a custom date time cast.
*
* @param string $cast
* @return bool
*/
protected function isCustomDateTimeCast($cast)
{
return strncmp($cast, 'date:', 5) === 0 ||
strncmp($cast, 'datetime:', 9) === 0;
}

/**
* Determine if the cast type is a decimal cast.
*
* @param string $cast
* @return bool
*/
protected function isDecimalCast($cast)
{
return strncmp($cast, 'decimal:', 8) === 0;
}

/**
* Set a given attribute on the model.
*
Expand Down Expand Up @@ -619,18 +480,6 @@ protected function setMutatedAttributeValue($key, $value)
return $this->{'set'.Str::studly($key).'Attribute'}($value);
}

/**
* Determine if the given attribute is a date or date castable.
*
* @param string $key
* @return bool
*/
protected function isDateAttribute($key)
{
return in_array($key, $this->getDates(), true) ||
$this->isDateCastable($key);
}

/**
* Set a given JSON attribute on the model.
*
Expand Down Expand Up @@ -676,26 +525,6 @@ protected function getArrayAttributeByKey($key)
$this->fromJson($this->attributes[$key]) : [];
}

/**
* Cast the given attribute to JSON.
*
* @param string $key
* @param mixed $value
* @return string
*/
protected function castAttributeAsJson($key, $value)
{
$value = $this->asJson($value);

if ($value === false) {
throw JsonEncodingException::forAttribute(
$this, $key, json_last_error_msg()
);
}

return $value;
}

/**
* Encode the given value as JSON.
*
Expand Down Expand Up @@ -899,58 +728,6 @@ public function setDateFormat($format)
return $this;
}

/**
* Determine whether an attribute should be cast to a native type.
*
* @param string $key
* @param array|string|null $types
* @return bool
*/
public function hasCast($key, $types = null)
{
if (array_key_exists($key, $this->getCasts())) {
return $types ? in_array($this->getCastType($key), (array) $types, true) : true;
}

return false;
}

/**
* Get the casts array.
*
* @return array
*/
public function getCasts()
{
if ($this->getIncrementing()) {
return array_merge([$this->getKeyName() => $this->getKeyType()], $this->casts);
}

return $this->casts;
}

/**
* Determine whether a value is Date / DateTime castable for inbound manipulation.
*
* @param string $key
* @return bool
*/
protected function isDateCastable($key)
{
return $this->hasCast($key, ['date', 'datetime']);
}

/**
* Determine whether a value is JSON castable for inbound manipulation.
*
* @param string $key
* @return bool
*/
protected function isJsonCastable($key)
{
return $this->hasCast($key, ['array', 'json', 'object', 'collection']);
}

/**
* Get all of the current attributes on the model.
*
Expand Down Expand Up @@ -1153,40 +930,6 @@ public function getChanges()
return $this->changes;
}

/**
* Determine if the new and old values for a given key are equivalent.
*
* @param string $key
* @param mixed $current
* @return bool
*/
public function originalIsEquivalent($key, $current)
{
if (! array_key_exists($key, $this->original)) {
return false;
}

$original = $this->getOriginal($key);

if ($current === $original) {
return true;
} elseif (is_null($current)) {
return false;
} elseif ($this->isDateAttribute($key)) {
return $this->fromDateTime($current) ===
$this->fromDateTime($original);
} elseif ($this->hasCast($key, ['object', 'collection'])) {
return $this->castAttribute($key, $current) ==
$this->castAttribute($key, $original);
} elseif ($this->hasCast($key)) {
return $this->castAttribute($key, $current) ===
$this->castAttribute($key, $original);
}

return is_numeric($current) && is_numeric($original)
&& strcmp((string) $current, (string) $original) === 0;
}

/**
* Append attributes to query when building a query.
*
Expand Down
Loading
0