Skip to content

[12.x] Feat: ability to explicitly exclude factory relationships #56396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: 12.x
Choose a base branch
from

Conversation

Lakshan-Madushanka
Copy link

The withoutParents method is definitely a useful method but it's still missing some crucial capabilities. It's actually quite common for a table to have multiple relationship columns, where only some are nullable. In most cases, at least one relationship is mandatory.

For example: imagine an Employee model that has relationships with both Department and Allowance models. Interns aren’t assigned to any department until they complete a grace period, but they must have allowances(no one works for free).

In this case, I need to create an employee (intern) record without creating a department, but with an allowance. Unfortunately, withoutParents can’t handle this; it’s all or nothing. That makes it insufficient for this kind of use case.

However, with this new enhancement we can define which relationships should be excluded and withoutParents method will be completed. I understand concerns about framework bloat, but I reckon this functionality will be useful to others too. And the best part: I implemented it without introducing any new method except just a small internal variable and withoutParents accept optional array to define the relationships that should be excluded.

Employee factory

  public function definition(): array
  {
      return [
          'name'                  =>  fake()->name(),
          'age'                     =>  rand(1, 60),
          'department_id'   =>  Department::factory(),
          'allowance_id'      =>  Allowance::factory(),
      ];
  }

Create a employee with a allowance without a department

  Employee::factory()
    ->withoutParents([Department::class])
    ->create()

@cosmastech
Copy link
Contributor

Does this work with morphable relationships?

@Lakshan-Madushanka
Copy link
Author

@cosmastech yes, test case uses a polymorphic relationship beside it should work for all the relationships that factory supports.

@taylorotwell
Copy link
Member

Why not added to the newInstance method?

@taylorotwell taylorotwell marked this pull request as draft July 24, 2025 17:33
@Lakshan-Madushanka
Copy link
Author

Lakshan-Madushanka commented Jul 24, 2025

@taylorotwell, I got your point that way the state of $excludeRelationships will be preserved throughout the lifecycle which should be the expected behavior. Sorry for missing it. This would've led to another issue but you're so meticulous🙏.

I've added a commit for this so re-review this please.

@Lakshan-Madushanka Lakshan-Madushanka marked this pull request as ready for review July 24, 2025 22:14
@taylorotwell
Copy link
Member

What if a model has multiple relationships of the same model type... think assigned_by_user_id... assigned_to_user_id on the same model.

@taylorotwell taylorotwell marked this pull request as draft July 24, 2025 23:32
@Lakshan-Madushanka
Copy link
Author

Lakshan-Madushanka commented Jul 25, 2025

At first, I considered excluding relations based on attribute names, but I didn’t choose that approach as it felt inconsistent with the method name. I can think of two possible solutions:

  1. Allow passing attribute names directly to the original withoutParents(['assigned_by_user_id']) method. If we do this, should we also support passing the model itself (withoutParents([User::class])) ?

  2. Introduce a new method like withoutParentsFor(['assigned_by_user_id']) (only accept attr names) for more explicit control.

@withgem
Copy link

withgem commented Jul 25, 2025

first solution is good to me. Second one is a little mess and redundant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants