Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Factory Muffin Laravel Package

league/factory-muffin

Factory Muffin helps you rapidly create test objects in PHP with simple, reusable model factories (inspired by factory_girl). Define models and generate instances for fixtures and unit tests; optional Faker integration is available via factory-muffin-faker.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require league/factory-muffin --dev
    

    Add to composer.json under require-dev to ensure it’s only installed in testing environments.

  2. Basic Usage:

    use League\FactoryMuffin\Factory;
    use League\FactoryMuffin\FakerProvider;
    
    // Define a factory for a User model
    $factory = new Factory();
    $factory->for(User::class)
        ->create(function (FakerProvider $faker) {
            return new User([
                'name' => $faker->name,
                'email' => $faker->unique()->safeEmail,
            ]);
        });
    
    // Generate a user
    $user = $factory->create(User::class);
    
  3. First Use Case: Use FactoryMuffin to generate test data for unit/integration tests. Replace hardcoded test data with dynamic, realistic objects.


Implementation Patterns

Workflows

  1. Factory Definition:

    • Group factories by domain (e.g., UserFactory, PostFactory) in a dedicated Factories directory.
    • Use traits or base factories to avoid repetition:
      trait BaseFactory {
          protected function commonAttributes(FakerProvider $faker) {
              return ['created_at' => $faker->dateTimeThisYear];
          }
      }
      
  2. Relationships:

    • Chain factories to build nested objects:
      $factory->for(Post::class)
          ->create(function (FakerProvider $faker) {
              return new Post([
                  'title' => $faker->sentence,
                  'user_id' => $factory->create(User::class)->id,
              ]);
          });
      
  3. State Management:

    • Use state() to define reusable configurations:
      $factory->for(User::class)
          ->state('admin', function (FakerProvider $faker) {
              return ['role' => 'admin'];
          });
      $admin = $factory->state(User::class, 'admin');
      
  4. Testing Integration:

    • Instantiate factories in phpunit.xml or a TestCase bootstrap:
      class TestCase extends \Tests\TestCase {
          protected $factory;
      
          protected function setUp(): void {
              $this->factory = new Factory();
              // Register factories here
          }
      }
      

Integration Tips

  • Laravel Synergy: Combine with Laravel’s DatabaseTransactions trait for seamless test rollbacks:

    use Illuminate\Foundation\Testing\DatabaseTransactions;
    
    class UserTest extends TestCase {
        use DatabaseTransactions;
    
        public function test_user_creation() {
            $user = $this->factory->create(User::class);
            // Assertions...
        }
    }
    
  • Faker Customization: Extend FakerProvider for domain-specific data:

    $factory->for(User::class)
        ->create(function (FakerProvider $faker) {
            $faker->addProvider(new CustomFakerProvider());
            return new User(['email' => $faker->customEmail]);
        });
    

Gotchas and Tips

Pitfalls

  1. State Clashes:

    • Overwriting states silently. Use unique state names or validate before applying:
      $factory->state(User::class, 'admin')->state(User::class, 'admin'); // Silent failure
      
  2. Circular Dependencies:

    • Factories referencing each other (e.g., User needs Post, Post needs User) cause infinite loops. Use lazy loading or mocks for circular relationships.
  3. Faker Seed Collisions:

    • Unique constraints (e.g., unique()->email) may fail if the same seed is reused. Use Faker::unique(true) or reset the seed per test.
  4. Static Analysis:

    • IDE autocompletion may not recognize dynamic factory methods. Use PHPDoc annotations:
      /**
       * @return User
       */
      public function createUser() { ... }
      

Debugging

  • Verify Factory Registration: Check if factories are registered before use:

    if (!$factory->has(User::class)) {
        throw new \RuntimeException('User factory not registered!');
    }
    
  • Inspect Generated Data: Use var_dump() or dd() to debug factory outputs:

    $user = $factory->create(User::class);
    dd($user->toArray());
    
  • Clear States: Reset states between tests to avoid pollution:

    $factory->clearStates(User::class);
    

Extension Points

  1. Custom Providers: Extend FakerProvider for domain-specific data:

    class AppFakerProvider extends FakerProvider {
        public function password() {
            return $this->faker->password(8, '!@#$%^&*');
        }
    }
    
  2. After Creation Hooks: Use afterCreate() to modify objects post-creation:

    $factory->for(User::class)
        ->afterCreate(function (User $user) {
            $user->update(['last_login' => now()]);
        });
    
  3. Factory Inheritance: Extend base factories for shared logic:

    class BaseModelFactory {
        public function createWithTimestamps(FakerProvider $faker) {
            return ['created_at' => $faker->dateTimeThisYear];
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport