@@ -62,7 +62,13 @@ public function objectToDatabase(Table $table, Column $column, mixed $value, boo
6262 } else {
6363 $ nestedTable = $ this ->registry ->get ($ column ->itemType );
6464 $ jsonArray = [];
65+ if (!is_iterable ($ value )) {
66+ throw new ConverterException ("Expected iterable value for array type " );
67+ }
6568 foreach ($ value as $ item ) {
69+ if (!is_object ($ item )) {
70+ throw new ConverterException ("Expected object in array value " );
71+ }
6672 $ jsonArray [] = $ jsonObject = new stdClass ();
6773 foreach ($ nestedTable ->columns as $ nestedColumn ) {
6874 $ jsonObject ->{$ nestedColumn ->name } = $ this ->objectToDatabase (
@@ -87,6 +93,9 @@ public function objectToDatabase(Table $table, Column $column, mixed $value, boo
8793 $ returnValue = $ value ->name ;
8894 }
8995 } else if (null !== ($ nestedTable = $ this ->registry ->maybeGet ($ valueType ->getName ()))) {
96+ if (!is_object ($ value )) {
97+ throw new ConverterException ("Expected object value for nested type " );
98+ }
9099 $ jsonObject = new stdClass ();
91100 foreach ($ nestedTable ->columns as $ nestedColumn ) {
92101 $ jsonObject ->{$ nestedColumn ->name } = $ this ->objectToDatabase (
@@ -133,14 +142,30 @@ public function databaseToObject(Table $table, Column $column, mixed $value, boo
133142 if (in_array ($ valueType ->getName (), ["int " , "float " , "string " , "bool " ], true )) {
134143 $ returnValue = $ value ;
135144 } else if ($ valueType ->getName () === "object " ) {
145+ if (!is_string ($ value )) {
146+ throw new ConverterException ("Expected string value for JSON decoding " );
147+ }
148+ /** @var string $value */
136149 $ returnValue = $ decode ? json_decode ($ value ) : $ value ;
137150 } else if ($ valueType ->getName () === "array " ) {
138151 if ($ column ->itemType === null ) {
152+ if (!is_string ($ value )) {
153+ throw new ConverterException ("Expected string value for JSON decoding " );
154+ }
155+ /** @var string $value */
139156 $ returnValue = $ decode ? json_decode ($ value ) : $ value ;
140157 } else {
141158 $ nestedTable = $ this ->registry ->get ($ column ->itemType );
142159 $ array = [];
143- foreach ($ decode ? json_decode ($ value ) : $ value as $ jsonObject ) {
160+ if ($ decode && !is_string ($ value )) {
161+ throw new ConverterException ("Expected string value for JSON decoding " );
162+ }
163+ /** @var string $value */
164+ $ decodedValue = $ decode ? json_decode ($ value ) : $ value ;
165+ if (!is_iterable ($ decodedValue )) {
166+ throw new ConverterException ("Expected iterable value for array type " );
167+ }
168+ foreach ($ decodedValue as $ jsonObject ) {
144169 $ nestedObject = $ nestedTable ->reflection ->newInstanceWithoutConstructor ();
145170 foreach ($ nestedTable ->columns as $ nestedColumn ) {
146171 $ nestedColumn ->reflection ->setValue (
@@ -160,14 +185,17 @@ public function databaseToObject(Table $table, Column $column, mixed $value, boo
160185 } else if (in_array ($ valueType ->getName (), [DateTime::class, DateTimeImmutable::class], true )) {
161186 /** @var class-string<DateTime|DateTimeImmutable> $className */
162187 $ className = $ valueType ->getName ();
188+ if (!is_string ($ value )) {
189+ throw new ConverterException ("Expected string value for DateTime conversion " );
190+ }
163191 $ returnValue = $ className ::createFromFormat ($ this ->dateTimeFormat , $ value , $ this ->dateTimeZone );
164192 if ($ returnValue === false ) {
165193 try {
166194 $ returnValue = new $ className ($ value , $ this ->dateTimeZone );
167195 } catch (\Exception $ e ) {
168196 throw new ConverterException (sprintf (
169197 "Could not parse datetime value [%s] for property [%s:: \$%s]. " ,
170- $ value ,
198+ ( string ) $ value ,
171199 $ table ->reflection ->getName (),
172200 $ column ->reflection ->getName ()
173201 ));
@@ -181,6 +209,9 @@ public function databaseToObject(Table $table, Column $column, mixed $value, boo
181209 if ($ enumReflection ->isBacked ()) {
182210 // Backed enum - use from() method
183211 /** @var class-string<BackedEnum> $className */
212+ if (!is_int ($ value ) && !is_string ($ value )) {
213+ throw new ConverterException ("Expected int or string value for backed enum " );
214+ }
184215 $ returnValue = $ className ::from ($ value );
185216 } else {
186217 // Unit enum - find case by name
@@ -193,16 +224,21 @@ public function databaseToObject(Table $table, Column $column, mixed $value, boo
193224 }
194225 }
195226 if ($ returnValue === null ) {
227+ $ valueStr = is_scalar ($ value ) ? (string ) $ value : get_debug_type ($ value );
196228 throw new ConverterException (sprintf (
197229 "Could not find enum case [%s] for enum [%s] in property [%s:: \$%s]. " ,
198- $ value ,
230+ $ valueStr ,
199231 $ className ,
200232 $ table ->reflection ->getName (),
201233 $ column ->reflection ->getName ()
202234 ));
203235 }
204236 }
205237 } else if (null !== ($ nestedTable = $ this ->registry ->maybeGet ($ valueType ->getName ()))) {
238+ if ($ decode && !is_string ($ value )) {
239+ throw new ConverterException ("Expected string value for JSON decoding " );
240+ }
241+ /** @var string $value */
206242 $ jsonObject = $ decode ? json_decode ($ value ) : $ value ;
207243 $ nestedObject = $ nestedTable ->reflection ->newInstanceWithoutConstructor ();
208244 foreach ($ nestedTable ->columns as $ nestedColumn ) {
0 commit comments