@@ -79,6 +79,13 @@ trait IncludesModels
7979 */
8080 protected $ includePaths = [];
8181
82+ /**
83+ * Whether Eloquent relations are camel cased.
84+ *
85+ * @var bool
86+ */
87+ protected $ camelCaseRelations = true ;
88+
8289 /**
8390 * Add eager loading to the query.
8491 *
@@ -145,7 +152,38 @@ protected function convertIncludePath($path)
145152 }
146153
147154 return collect (explode ('. ' , $ path ))->map (function ($ segment ) {
148- return Str:: camelize ($ segment );
155+ return $ this -> modelRelationForField ($ segment );
149156 })->implode ('. ' );
150157 }
158+
159+ /**
160+ * Convert a JSON API field name to an Eloquent model relation name.
161+ *
162+ * According to the PSR1 spec, method names on classes MUST be camel case.
163+ * However, there seem to be some Laravel developers who snake case
164+ * relationship methods on their models, so that the method name matches
165+ * the snake case format of attributes (column values).
166+ *
167+ * The `$camelCaseRelations` property controls the behaviour of this
168+ * conversion:
169+ *
170+ * - If `true`, a field name of `user-history` or `user_history` will
171+ * expect the Eloquent model relation method to be `userHistory`.
172+ * - If `false`, a field name of `user-history` or `user_history` will
173+ * expect the Eloquent model relation method to be `user_history`. I.e.
174+ * if PSR1 is not being followed, the best guess is that method names
175+ * are snake case.
176+ *
177+ * If the developer has different conversion logic, they should overload
178+ * this method and implement it themselves.
179+ *
180+ * @param string $field
181+ * the JSON API field name.
182+ * @return string
183+ * the expected relation name on the Eloquent model.
184+ */
185+ protected function modelRelationForField ($ field )
186+ {
187+ return $ this ->camelCaseRelations ? Str::camelize ($ field ) : Str::underscore ($ field );
188+ }
151189}
0 commit comments