Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

t0berius's avatar

laravel factory access state from definition() method

I would explain what I'm thinking to archieve.

OrderFactory:

    public function definition()
    {
        //how to check here if the physical() method is set?
        if (){
            ...add another detail if item is physical...
            ...run this code
        }

    }
    
    public function physical(): Factory
    {
       //???set a value or something to determine if it's set why factory was called, NOT using the default way to "override" attributes
    }

Is there a way to use states, being able to check if a state is "set" inside the definition method of a model factory?

Update

Using the has() method, as suggested by GPT is not possible:

public function definition()
{
    if($this->has('physical'))
}
0 likes
5 replies
tisuchi's avatar

@t0berius How about this?

class OrderFactory extends Factory
{
    protected $isPhysical = false;

    public function definition()
    {
        if ($this->isPhysical) {
            //
        }

        return [
            //
        ];
    }
    
    public function physical(): self
    {
        return $this->state(function (array $attributes) {
            return [
                //
            ];
        })->configure(function() {
            $this->isPhysical = true;
            return $this;
        });
    }
}
t0berius's avatar

@tisuchi

Using this code and calling it like:

Order::factory()->physical()->count(1)->create()

returns no:

OrderFactory

public function definition()
{
    if($this->isPhysical)
        dd("ya");
    else
        dd("no");
}
xgecemx's avatar

Here are a few ways to check if a state is set inside the definition() method in Laravel model factories: use Illuminate\Database\Eloquent\Factories\Factory;

class OrderFactory extends Factory { /** * Indicates if the model is physical. * * @var bool */ protected $isPhysical = false;

/**
 * Define the model's default state.
 *
 * @return array
 */
public function definition()
{
    $data = [
        // your default attributes here...
    ];

    if ($this->isPhysical) {
        $data = array_merge($data, [
            // your additional attributes for physical items here...
        ]);
    }

    return $data;
}

/**
 * Indicate that the model is physical.
 *
 * @return $this
 */
public function physical()
{
    $this->isPhysical = true;
    return $this;
}

} To use the factory, if you want a physical order from https://www.typecalendar.com/doctors-note.html

Order::factory()->physical()->create();

cwhite's avatar

The idea of setting an $isPhysical property inside a state and then checking for it in definition() is never going to work---the definition() method is called before any states (see Factory::getRawAttributes()).

I would use an after{Making,Creating} hook to accomplish what you're trying to achieve instead of stuffing a bunch of logic inside your definition() method.

alucic's avatar

@cwhite I just tested this and your statement is not true. dump('physical') in physical() and dump('definition'); in definition() and it prints first physical then definition

Order::factory()->physical()->create();

Please or to participate in this conversation.