简体   繁体   中英

Laravel factory for a relationship with multiple columns

Creating factories for a project I'm working on, I have a problem creating a belongsTo relationship.

In my Cards table, I have 2 columns referencing the same relation: Card->order->id and Card->order->ref (don't ask me why, I don't even know).

So, in my CardFactory I need to be able to use the same instance of Order for both $card->order_ref and $card->order_id . Using factory states, I did create the following state:

public function sold(int $userId) : Factory
{
    $createdOrder = Order::factory()->forUser($userId)->create();

    return $this->state(function (array $attributes) use ($createdOrder) {
        return [
            'state' => Card::STATE_SOLD,
            'sold' => Carbon::now()->subDay(),
            'addedincart' => Carbon::now()->subDay()->subHour(),
            'selling_date' => Carbon::now()->subDay(),
            'order_id' => $createdOrder->id,
            'order_ref' => $createdOrder->ref,
        ];
    });
}

my OrderFactory.php :

class OrderFactory extends Factory {
public function definition() : array
{
    return [
        'ref' => $this->faker->randomNumber(9) ,
        'state' => 5,
        'clientname' => $this->faker->name(),
        'email' => $this->faker->email(),
        'phone' => $this->faker->phoneNumber(),
        'address' => null,
        'shippingaddress' => NULL,
        'total' => $this->faker->randomFloat(2, 50, 700),
        'method' => 'creditcard',
        'user_id' => null,
        'tracking' => NULL,
        'response' => json_encode(["someFields" => "someValues"]),
        'paid_on' => now(),
        'sent_on' => now(),
        'review_sent' => '1',
        'deliverymethod' => 'email',
        'deliverycosts' => '0.00',
        'coupon_id' => NULL,
        'discount' => '0.00',
        'explanation' => NULL,
        'refund_amount' => NULL,
        'refunded_at' => NULL,
        'shipping_status' => NULL,
        'original_cards' => '[1, 2]',
        'cancel_reason' => NULL,
        'private_comment' => NULL,
        'loyalty' => '30',
        'ip' => '00.00.00.00',
        'cb' => 'someCb',
        'geoip' => NULL,
        'ecards_sent' => '1',
        'blocked_by' => NULL,
        'partner' => NULL,
        'original_giftcards' => '',
        'giftcards_sent' => '0',
        'api_data' => NULL,
        'original_products' => NULL,
        'delivered_at' => now(),
        'invoice_send_at' => NULL,
        'type' => 'cards',
        'redeem_id' => '0',
    ];
}

public function forUser(int $id) : Factory
{
    return $this->state(function (array $attributes) use ($id) {
        return [
            'user_id' => $id,
        ];
    });
}

}

and in my CardSeeder.php :

public function run()
{
    $user = User::query()->where("email", "myAddress@gmail.com")->first();
    
    Card::factory()->sold($user->id)->count(15)->create();
    Card::factory()->selling()->count(15)->create();
}

The problem is, for each sold state created, the same $createdOrder->id is used.

How could I, for each row, use a different order?

AS docs https://laravel.com/docs/9.x/database-testing#defining-relationships-within-factories

Describe:

If the relationship's columns depend on the factory that defines it you may assign a closure to an attribute. The closure will receive the factory's evaluated attribute array.

so if you want genereate new instance of relation, u must create it inside closure:

public function sold(int $userId) : Factory 
{ 

return $this->state(function (array $attributes) use ($userId) {
    $order=null;
    return [
        'state' => Card::STATE_SOLD,
        'sold' => Carbon::now()->subDay(),
        'addedincart' => Carbon::now()->subDay()->subHour(),
        'selling_date' => Carbon::now()->subDay(),
        'order_id' => function()use(&$order,$userId){
           $order = Order::factory()->forUser($userId)->create();
           return $order->id;
        },
        'order_ref' => function()use(&$order){
              return $order->ref;
        },
    ];
});

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM