From d71dfdfc521c640736e41bf7943163c053939d47 Mon Sep 17 00:00:00 2001 From: Dan Krieger Date: Thu, 4 Aug 2022 10:03:51 -0700 Subject: [PATCH 1/3] Remove repeated calls to getCasts() in same method --- .../Database/Eloquent/Concerns/HasAttributes.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index d5f8225cf1bc..e26c77f1e239 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -1491,11 +1491,13 @@ protected function isEncryptedCastable($key) */ protected function isClassCastable($key) { - if (! array_key_exists($key, $this->getCasts())) { + $casts = $this->getCasts(); + + if (! array_key_exists($key, $casts)) { return false; } - $castType = $this->parseCasterClass($this->getCasts()[$key]); + $castType = $this->parseCasterClass($casts[$key]); if (in_array($castType, static::$primitiveCastTypes)) { return false; @@ -1516,11 +1518,13 @@ protected function isClassCastable($key) */ protected function isEnumCastable($key) { - if (! array_key_exists($key, $this->getCasts())) { + $casts = $this->getCasts(); + + if (! array_key_exists($key, $casts)) { return false; } - $castType = $this->getCasts()[$key]; + $castType = $casts[$key]; if (in_array($castType, static::$primitiveCastTypes)) { return false; From c156e136f77940766980f913b4885a4bf99f2633 Mon Sep 17 00:00:00 2001 From: Dan Krieger Date: Thu, 4 Aug 2022 10:04:07 -0700 Subject: [PATCH 2/3] Switch strncmp to starts_with_str Marginally faster, better readability, and matches similar functions --- src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index e26c77f1e239..0db8a0c2481e 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -882,8 +882,8 @@ protected function isCustomDateTimeCast($cast) */ protected function isImmutableCustomDateTimeCast($cast) { - return strncmp($cast, 'immutable_date:', 15) === 0 || - strncmp($cast, 'immutable_datetime:', 19) === 0; + return str_starts_with($cast, 'immutable_date:') || + str_starts_with($cast, 'immutable_datetime:'); } /** From 424e8cfe7e36e3162d9a6b369cda38587f4b77cd Mon Sep 17 00:00:00 2001 From: Dan Krieger Date: Thu, 4 Aug 2022 10:26:55 -0700 Subject: [PATCH 3/3] Add castTypeCache getCastType is called a lot when processing models with defined casts and contributes to a significant number of overall calls. Caching the results of the key conversion can result in significant performance improvement when processing large numbers of models. --- .../Eloquent/Concerns/HasAttributes.php | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index 0db8a0c2481e..557a36b90448 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -165,6 +165,13 @@ trait HasAttributes */ protected static $setAttributeMutatorCache = []; + /** + * The cache of the converted cast types. + * + * @var array + */ + protected static $castTypeCache = []; + /** * The encrypter instance that is used to encrypt attributes. * @@ -818,19 +825,23 @@ protected function getEnumCastableAttributeValue($key, $value) */ protected function getCastType($key) { - if ($this->isCustomDateTimeCast($this->getCasts()[$key])) { - return 'custom_datetime'; - } + $castType = $this->getCasts()[$key]; - if ($this->isImmutableCustomDateTimeCast($this->getCasts()[$key])) { - return 'immutable_custom_datetime'; + if (isset(static::$castTypeCache[$castType])) { + return static::$castTypeCache[$castType]; } - if ($this->isDecimalCast($this->getCasts()[$key])) { - return 'decimal'; + if ($this->isCustomDateTimeCast($castType)) { + $convertedCastType = 'custom_datetime'; + } elseif ($this->isImmutableCustomDateTimeCast($castType)) { + $convertedCastType = 'immutable_custom_datetime'; + } elseif ($this->isDecimalCast($castType)) { + $convertedCastType = 'decimal'; + } else { + $convertedCastType = trim(strtolower($castType)); } - return trim(strtolower($this->getCasts()[$key])); + return static::$castTypeCache[$castType] = $convertedCastType; } /**