66use Illuminate \Contracts \Filesystem \FileNotFoundException ;
77use Illuminate \Database \Eloquent \Relations \Relation ;
88use Illuminate \Filesystem \Filesystem ;
9+ use Illuminate \Support \Str ;
910use Symfony \Component \Console \Input \InputOption ;
1011use Symfony \Component \Console \Input \InputArgument ;
1112use Symfony \Component \Console \Output \OutputInterface ;
@@ -185,6 +186,8 @@ protected function generateFactories($loadModels, $ignore = '')
185186
186187 $ this ->getPropertiesFromTable ($ model );
187188
189+ $ this ->getPropertiesFromMethods ($ model );
190+
188191 $ output .= $ this ->createFactory ($ name );
189192 $ ignore [] = $ name ;
190193 } catch (\Exception $ e ) {
@@ -256,6 +259,49 @@ protected function getPropertiesFromTable($model)
256259 }
257260 }
258261
262+
263+ /**
264+ * @param \Illuminate\Database\Eloquent\Model $model
265+ */
266+ protected function getPropertiesFromMethods ($ model )
267+ {
268+ $ methods = get_class_methods ($ model );
269+ if ($ methods ) {
270+ foreach ($ methods as $ method ) {
271+ if (!method_exists ('Illuminate\Database\Eloquent\Model ' , $ method ) && !Str::startsWith ($ method , 'get ' )) {
272+ //Use reflection to inspect the code, based on Illuminate/Support/SerializableClosure.php
273+ $ reflection = new \ReflectionMethod ($ model , $ method );
274+ $ file = new \SplFileObject ($ reflection ->getFileName ());
275+ $ file ->seek ($ reflection ->getStartLine () - 1 );
276+ $ code = '' ;
277+ while ($ file ->key () < $ reflection ->getEndLine ()) {
278+ $ code .= $ file ->current ();
279+ $ file ->next ();
280+ }
281+ $ code = trim (preg_replace ('/\s\s+/ ' , '' , $ code ));
282+ $ begin = strpos ($ code , 'function( ' );
283+ $ code = substr ($ code , $ begin , strrpos ($ code , '} ' ) - $ begin + 1 );
284+ foreach (array (
285+ 'belongsTo ' ,
286+ ) as $ relation ) {
287+ $ search = '$this-> ' . $ relation . '( ' ;
288+ if ($ pos = stripos ($ code , $ search )) {
289+ //Resolve the relation's model to a Relation object.
290+ $ relationObj = $ model ->$ method ();
291+ if ($ relationObj instanceof Relation) {
292+ $ relatedModel = '\\' . get_class ($ relationObj ->getRelated ());
293+ $ relatedObj = new $ relatedModel ;
294+
295+ $ property = $ relationObj ->getForeignKey ();
296+ $ this ->setProperty ($ property ,'factory( ' .get_class ($ relationObj ->getRelated ()).'::class)->create()-> ' .$ relatedObj ->getKeyName ());
297+ }
298+ }
299+ }
300+ }
301+ }
302+ }
303+ }
304+
259305 /**
260306 * @param string $name
261307 * @param string|null $type
@@ -271,6 +317,10 @@ protected function setProperty($name, $type = null)
271317 $ this ->properties [$ name ]['type ' ] = $ type ;
272318 }
273319
320+ if (Str::startsWith ($ type ,'factory( ' )) {
321+ $ this ->properties [$ name ]['faker ' ] = true ;
322+ }
323+
274324 $ fakeableTypes = [
275325 'string ' => '$faker->word ' ,
276326 'text ' => '$faker->text ' ,
0 commit comments