2
2
3
3
namespace Illuminate \Database \Eloquent \Concerns ;
4
4
5
+ use Illuminate \Container \Container ;
6
+ use Illuminate \Contracts \Container \BindingResolutionException ;
7
+ use Illuminate \Contracts \Database \Eloquent \Castable ;
5
8
use Illuminate \Contracts \Support \Arrayable ;
6
9
use Illuminate \Database \Eloquent \JsonEncodingException ;
7
10
use Illuminate \Support \Collection ;
@@ -25,11 +28,13 @@ trait HasCasts
25
28
*/
26
29
public function hasCast ($ key , $ types = null )
27
30
{
28
- if (array_key_exists ($ key , $ this ->getCasts ())) {
29
- return $ types ? in_array ( $ this -> getCastType ( $ key ), ( array ) $ types , true ) : true ;
31
+ if (! array_key_exists ($ key , $ this ->getCasts ())) {
32
+ return false ;
30
33
}
31
34
32
- return false ;
35
+ return $ types
36
+ ? in_array ($ this ->getCastType ($ key ), (array ) $ types , true )
37
+ : true ;
33
38
}
34
39
35
40
/**
@@ -39,11 +44,14 @@ public function hasCast($key, $types = null)
39
44
*/
40
45
public function getCasts ()
41
46
{
42
- if ($ this ->getIncrementing ()) {
43
- return array_merge ([$ this ->getKeyName () => $ this ->getKeyType ()], $ this ->casts );
44
- }
47
+ return $ this ->getIncrementing ()
48
+ ? array_merge ([$ this ->getKeyName () => $ this ->getKeyType ()], $ this ->casts )
49
+ : $ this ->casts ;
50
+ }
45
51
46
- return $ this ->casts ;
52
+ public function getCast ($ key )
53
+ {
54
+ return $ this ->getCasts ()[$ key ];
47
55
}
48
56
49
57
/**
@@ -52,6 +60,8 @@ public function getCasts()
52
60
* @param string $key
53
61
* @param mixed $current
54
62
*
63
+ * @throws BindingResolutionException
64
+ *
55
65
* @return bool
56
66
*/
57
67
public function originalIsEquivalent ($ key , $ current )
@@ -87,6 +97,8 @@ public function originalIsEquivalent($key, $current)
87
97
* @param array $attributes
88
98
* @param array $mutatedAttributes
89
99
*
100
+ * @throws BindingResolutionException
101
+ *
90
102
* @return array
91
103
*/
92
104
protected function addCastAttributesToArray (array $ attributes , array $ mutatedAttributes )
@@ -106,12 +118,11 @@ protected function addCastAttributesToArray(array $attributes, array $mutatedAtt
106
118
// If the attribute cast was a date or a datetime, we will serialize the date as
107
119
// a string. This allows the developers to customize how dates are serialized
108
120
// into an array without affecting how they are persisted into the storage.
109
- if ($ attributes [$ key ] &&
110
- ($ value === 'date ' || $ value === 'datetime ' )) {
121
+ if (($ value === 'date ' || $ value === 'datetime ' )) {
111
122
$ attributes [$ key ] = $ this ->serializeDate ($ attributes [$ key ]);
112
123
}
113
124
114
- if ($ attributes [ $ key ] && $ this ->isCustomDateTimeCast ($ value )) {
125
+ if ($ this ->isCustomDateTimeCast ($ value )) {
115
126
$ attributes [$ key ] = $ attributes [$ key ]->format (explode (': ' , $ value , 2 )[1 ]);
116
127
}
117
128
@@ -129,9 +140,11 @@ protected function addCastAttributesToArray(array $attributes, array $mutatedAtt
129
140
* @param string $key
130
141
* @param mixed $value
131
142
*
143
+ * @throws BindingResolutionException
144
+ *
132
145
* @return mixed
133
146
*/
134
- protected function castAttribute ($ key , $ value )
147
+ protected function castAttribute ($ key , $ value = null )
135
148
{
136
149
if (is_null ($ value )) {
137
150
return $ value ;
@@ -146,7 +159,7 @@ protected function castAttribute($key, $value)
146
159
case 'double ' :
147
160
return $ this ->fromFloat ($ value );
148
161
case 'decimal ' :
149
- return $ this ->asDecimal ($ value , explode (': ' , $ this ->getCasts ()[ $ key] , 2 )[1 ]);
162
+ return $ this ->asDecimal ($ value , explode (': ' , $ this ->getCast ( $ key) , 2 )[1 ]);
150
163
case 'string ' :
151
164
return (string ) $ value ;
152
165
case 'bool ' :
@@ -167,7 +180,9 @@ protected function castAttribute($key, $value)
167
180
case 'timestamp ' :
168
181
return $ this ->asTimestamp ($ value );
169
182
default :
170
- return $ value ;
183
+ return $ this ->isCustomCastable ($ key )
184
+ ? $ this ->fromCustomCastable ($ key , $ value )
185
+ : $ value ;
171
186
}
172
187
}
173
188
@@ -180,15 +195,17 @@ protected function castAttribute($key, $value)
180
195
*/
181
196
protected function getCastType ($ key )
182
197
{
183
- if ($ this ->isCustomDateTimeCast ($ this ->getCasts ()[$ key ])) {
198
+ $ cast = $ this ->getCast ($ key );
199
+
200
+ if ($ this ->isCustomDateTimeCast ($ cast )) {
184
201
return 'custom_datetime ' ;
185
202
}
186
203
187
- if ($ this ->isDecimalCast ($ this -> getCasts ()[ $ key ] )) {
204
+ if ($ this ->isDecimalCast ($ cast )) {
188
205
return 'decimal ' ;
189
206
}
190
207
191
- return trim (strtolower ($ this -> getCasts ()[ $ key ] ));
208
+ return trim (strtolower ($ cast ));
192
209
}
193
210
194
211
/**
@@ -250,6 +267,21 @@ protected function isDateAttribute($key)
250
267
$ this ->isDateCastable ($ key );
251
268
}
252
269
270
+ /**
271
+ * Is the checked value a custom Cast.
272
+ *
273
+ * @param string $key
274
+ *
275
+ * @return bool
276
+ */
277
+ protected function isCustomCastable ($ key )
278
+ {
279
+ return is_subclass_of (
280
+ $ this ->getCast ($ key ),
281
+ Castable::class
282
+ );
283
+ }
284
+
253
285
/**
254
286
* Determine whether a value is Date / DateTime castable for inbound manipulation.
255
287
*
@@ -273,4 +305,34 @@ protected function isJsonCastable($key)
273
305
{
274
306
return $ this ->hasCast ($ key , ['array ' , 'json ' , 'object ' , 'collection ' ]);
275
307
}
308
+
309
+ /**
310
+ * Getting the execution result from a user Cast object.
311
+ *
312
+ * @param string $key
313
+ * @param null $value
314
+ *
315
+ * @throws BindingResolutionException
316
+ *
317
+ * @return mixed
318
+ */
319
+ protected function fromCustomCastable ($ key , $ value = null )
320
+ {
321
+ return $ this
322
+ ->normalizeHandlerToCallable ($ key )
323
+ ->handle ($ value );
324
+ }
325
+
326
+ /**
327
+ * @param string $key
328
+ *
329
+ * @throws BindingResolutionException
330
+ *
331
+ * @return Castable
332
+ */
333
+ protected function normalizeHandlerToCallable ($ key )
334
+ {
335
+ return Container::getInstance ()
336
+ ->make ($ this ->getCast ($ key ));
337
+ }
276
338
}
0 commit comments