From 43cf5e15b9a597625453618ecb6d46674b6fc4d8 Mon Sep 17 00:00:00 2001 From: Luke Downing Date: Sun, 10 May 2020 18:17:56 +0100 Subject: [PATCH 1/4] Adds the `craft` and `craftOne` methods. --- CHANGELOG.md | 4 ++++ README.md | 8 ++++++++ src/Factory.php | 28 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 643b6a4..1ac7602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 4.1.0 +Adds support for quick create syntax, by using the `craft` and `craftOne` methods. This allows for a simpler +syntax when you only need to quickly create a model and don't need to add complex relationship mapping. + # 4.0.1 Adds backwards-compatible support for `snake_case` relationship methods. Poser will check to see if a `snake_case` method exists on the `Model` and call it if so, instead of the default `camelCase`. diff --git a/README.md b/README.md index 8970a6f..cab72eb 100644 --- a/README.md +++ b/README.md @@ -594,6 +594,14 @@ instead call the relationship method statically, like so: `UserFactory::withCust Creates a new instance of the factory, but informs the factory that you will be creating multiple models. Use this to instantiate the class when you wish to create multiple entries in the database. +#### `::craft(int $count, ...$attributes)` +Allows you to create multiple models, persist them to the database, and return the resulting collection, all in one +method call. A very useful shortcut when you don't need complex relationship mapping. You may pass in the count of +models you wish to create, along with attributes that should be given to those models. + +#### `::craftOne(array $attributes = null)` +Similar to `::craft`, but for a single model instance. It will return the model instead of a collection. + #### `->create(...$attributes)` or `(...$attributes)` Similar to the Laravel factory `create` command, this will create the models, persisting them to the database. You may pass an associative array of column names with desired values, which will be applied to the diff --git a/src/Factory.php b/src/Factory.php index d704f00..e20b5b0 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -63,6 +63,34 @@ public static function times(int $count) return $factory; } + /** + * Immediately builds, persists and returns a model of the Factory type, + * optionally with the given parameters. + * + * @param array $attributes + * @return Model + */ + public static function craftOne(array $attributes = []) + { + return self::craft(1, $attributes); + } + + /** + * Immediately builds, persists an returns the number of requested models + * of the Factory type, optionally with the given parameters or parameter sets. + * + * @param int $count + * @param mixed ...$attributes + * @return \Illuminate\Database\Eloquent\Collection|Model|Model[]|Collection + */ + public static function craft(int $count, ...$attributes) + { + $factory = self::times($count); + $factory->withAttributes(...$attributes); + + return $factory->create(); + } + public function __construct() { $this->testCaseCaller = new TestCaseCaller(); From 0c95c7788b02449bc9cfa1f848c51f9fc2e1b2f0 Mon Sep 17 00:00:00 2001 From: Luke Downing Date: Sun, 17 May 2020 19:49:31 +0100 Subject: [PATCH 2/4] Updates the `craft` method to be able to handle both use cases. Removes `craftOne`. --- CHANGELOG.md | 2 +- README.md | 4 ++-- src/Factory.php | 51 ++++++++++++++++++++++--------------------------- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac7602..352d454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # 4.1.0 -Adds support for quick create syntax, by using the `craft` and `craftOne` methods. This allows for a simpler +Adds support for quick create syntax, by using the `craft` method. This allows for a simpler syntax when you only need to quickly create a model and don't need to add complex relationship mapping. # 4.0.1 diff --git a/README.md b/README.md index cab72eb..b1d4c1e 100644 --- a/README.md +++ b/README.md @@ -599,8 +599,8 @@ Allows you to create multiple models, persist them to the database, and return t method call. A very useful shortcut when you don't need complex relationship mapping. You may pass in the count of models you wish to create, along with attributes that should be given to those models. -#### `::craftOne(array $attributes = null)` -Similar to `::craft`, but for a single model instance. It will return the model instead of a collection. +#### `::craft(array $attributes = null)` +If you only need to craft one model, you can omit the count. It will return the model instead of a collection. #### `->create(...$attributes)` or `(...$attributes)` Similar to the Laravel factory `create` command, this will create the models, persisting them to the database. diff --git a/src/Factory.php b/src/Factory.php index e20b5b0..74c6eac 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -4,6 +4,7 @@ namespace Lukeraymonddowning\Poser; use Closure; +use Illuminate\Support\Arr; use ReflectionClass; use ReflectionMethod; use Mockery\Exception; @@ -64,29 +65,23 @@ public static function times(int $count) } /** - * Immediately builds, persists and returns a model of the Factory type, - * optionally with the given parameters. + * For those times where you don't need super complex relationship mapping, and just want to quickly build a model + * or collection of models. * - * @param array $attributes - * @return Model - */ - public static function craftOne(array $attributes = []) - { - return self::craft(1, $attributes); - } - - /** - * Immediately builds, persists an returns the number of requested models - * of the Factory type, optionally with the given parameters or parameter sets. + * @param mixed ...$parameters If you need to build multiple models, the first parameter should be desired count, + * with any other parameters forming your attribute sets. If you're building a single model, you may omit the count. * - * @param int $count - * @param mixed ...$attributes * @return \Illuminate\Database\Eloquent\Collection|Model|Model[]|Collection */ - public static function craft(int $count, ...$attributes) + public static function craft(...$parameters) { - $factory = self::times($count); - $factory->withAttributes(...$attributes); + $factory = self::new(); + + if (!empty($parameters) && is_int($parameters[0])) { + $factory->count = Arr::pull($parameters, 0); + } + + $factory->withAttributes(...$parameters); return $factory->create(); } @@ -348,8 +343,8 @@ public function afterCreating(Closure $closure) * Given an array of attribute sets, returns the desired set if available, else the first one available * either through looping or retrieving the first one, or an empty array. * - * @param array $attributes The array of arrays from which to extract an attribute set. - * @param int $desiredIndex The ideal index of the attribute set you would like + * @param array $attributes The array of arrays from which to extract an attribute set. + * @param int $desiredIndex The ideal index of the attribute set you would like * @return array|mixed */ protected function getDesiredAttributeData(array $attributes, int $desiredIndex) @@ -363,7 +358,7 @@ protected function getDesiredAttributeData(array $attributes, int $desiredIndex) /** * @param string $functionName - * @param array $arguments + * @param array $arguments * @return bool True if the relationship was handled, or false if it couldn't be handled. */ protected function handleRelationship(string $functionName, array $arguments) @@ -376,7 +371,7 @@ protected function handleRelationship(string $functionName, array $arguments) * Prepares a `with[RelationshipName]` by parsing it and storing it until the factory calls `create()`. * * @param string $functionName The name of the function that was called by the user. - * @param array $arguments The arguments that were passed to the function. + * @param array $arguments The arguments that were passed to the function. * @return bool True if the relationship was handled, else false. */ protected function handleWithRelationship(string $functionName, array $arguments) @@ -390,7 +385,7 @@ protected function handleWithRelationship(string $functionName, array $arguments * Prepares a `for[RelationshipName]` by parsing it and storing it until the factory calls `create()`. * * @param string $functionName The name of the function that was called by the user. - * @param array $arguments The arguments that were passed to the function. + * @param array $arguments The arguments that were passed to the function. * @return bool True if the relationship was handled, else false. */ protected function handleForRelationship(string $functionName, array $arguments) @@ -454,8 +449,8 @@ protected function isInIgnoreList(string $relationshipMethodName) } /** - * @throws ReflectionException * @return Collection + * @throws ReflectionException */ protected function getDefaultMethods(): Collection { @@ -509,9 +504,9 @@ function ($prefix) use ($functionName) { * created. * * @param string $functionName The name of the relationship method that was called by the user. - * @param array $arguments Any arguments passed to the relationship method. - * @throws ArgumentsNotSatisfiableException + * @param array $arguments Any arguments passed to the relationship method. * @return mixed Usually a Poser Factory, but could be a Model or Collection of Models. + * @throws ArgumentsNotSatisfiableException */ protected function buildRelationshipData(string $functionName, array $arguments) { @@ -551,8 +546,8 @@ protected function factoryShouldBeHandledManually(array $arguments) * For example, `withCustomers()` should return the fully qualified `CustomerFactory`. * * @param string $methodName The name of the method that was called by the user. - * @throws ArgumentsNotSatisfiableException * @return string The Poser factory class name that matches the function name. + * @throws ArgumentsNotSatisfiableException */ protected function getFactoryNameFromMethodNameOrFail(string $methodName) { @@ -583,7 +578,7 @@ class_basename($this), $methodName, * Constructs and returns fully qualified Poser factory name. * * @param string $relationshipMethodName The relationship method found on the Laravel Model. - * @param string $suffix A suffix that should be applied to the Poser Factory name. + * @param string $suffix A suffix that should be applied to the Poser Factory name. * @return string The constructed fully qualified Poser factory name. */ protected function getFactoryName(string $relationshipMethodName, string $suffix = "") From 53b3f50b6628e125d7bc3dbde1eca6a5f3741f9c Mon Sep 17 00:00:00 2001 From: Luke Downing Date: Sun, 17 May 2020 21:57:03 +0100 Subject: [PATCH 3/4] The last parameter in the `craft` method may be the count, instead of the first, if desired. --- src/Factory.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index 74c6eac..3b4971a 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -68,8 +68,9 @@ public static function times(int $count) * For those times where you don't need super complex relationship mapping, and just want to quickly build a model * or collection of models. * - * @param mixed ...$parameters If you need to build multiple models, the first parameter should be desired count, - * with any other parameters forming your attribute sets. If you're building a single model, you may omit the count. + * @param mixed ...$parameters If you need to build multiple models, the first or last parameter should be the + * desired count, with any other parameters forming your attribute sets. + * If you're building a single model, you may omit the count. * * @return \Illuminate\Database\Eloquent\Collection|Model|Model[]|Collection */ @@ -77,10 +78,18 @@ public static function craft(...$parameters) { $factory = self::new(); - if (!empty($parameters) && is_int($parameters[0])) { + if (empty($parameters)) { + return $factory->create(); + } + + if (is_int($parameters[0])) { $factory->count = Arr::pull($parameters, 0); } + if (is_int(Arr::last($parameters))) { + $factory->count = Arr::pull($parameters, count($parameters) - 1); + } + $factory->withAttributes(...$parameters); return $factory->create(); From 2bfd34de1abd82a55a555ff3598f59c8ff1c1f38 Mon Sep 17 00:00:00 2001 From: Luke Downing Date: Sun, 17 May 2020 21:58:55 +0100 Subject: [PATCH 4/4] Updated documentation. --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b1d4c1e..0cc8eb7 100644 --- a/README.md +++ b/README.md @@ -599,8 +599,11 @@ Allows you to create multiple models, persist them to the database, and return t method call. A very useful shortcut when you don't need complex relationship mapping. You may pass in the count of models you wish to create, along with attributes that should be given to those models. +#### `::craft(...$attributes, int $count)` +Alternate syntax for `craft` as described above, which more closely matches `factory` method baked into Laravel. + #### `::craft(array $attributes = null)` -If you only need to craft one model, you can omit the count. It will return the model instead of a collection. +If you only need to craft one model, you can omit the count. It will return a single model instead of a collection. #### `->create(...$attributes)` or `(...$attributes)` Similar to the Laravel factory `create` command, this will create the models, persisting them to the database.