Laravel透视表工厂报错:Call to a member function __call() on null
问题分析与解决
错误Call to a member function __call() on null出现在调用OrderProduct::factory()->create()时,核心原因是OrderProduct工厂未正确关联对应模型,或OrderProduct模型未正确创建/配置。
1. 确保OrderProduct模型存在并配置正确
在app/Models/目录下创建(或检查)OrderProduct.php,确保填充字段和表名正确:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class OrderProduct extends Model { // 允许批量赋值的字段 protected $fillable = ['order_id', 'product_id', 'quantity', 'price']; // 如果你的透视表名不是默认的`order_products`(比如是`order_product`),需手动指定 // protected $table = 'order_product'; }
2. 修复OrderProductFactory的模型绑定
打开Database/Factories/OrderProductFactory.php,必须指定对应的模型类:
<?php namespace Database\Factories; use App\Models\OrderProduct; use Illuminate\Database\Eloquent\Factories\Factory; class OrderProductFactory extends Factory { // 关键:绑定对应的模型 protected $model = OrderProduct::class; public function definition(): array { return [ 'order_id' => \App\Models\Order::factory(), 'product_id' => \App\Models\Product::factory(), 'quantity' => $this->faker->numberBetween(1, 10), 'price' => $this->faker->randomFloat(2, 5, 100), ]; } }
3. 确认Order与Product模型的多对多关联配置
因为透视表包含额外字段(quantity、price),需要在关联中指定使用OrderProduct模型并声明这些字段:
Order模型:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Order extends Model { // ...其他代码 public function products() { return $this->belongsToMany(Product::class) ->using(OrderProduct::class) ->withPivot('quantity', 'price'); } }
Product模型:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Product extends Model { // ...其他代码 public function orders() { return $this->belongsToMany(Order::class) ->using(OrderProduct::class) ->withPivot('quantity', 'price'); } }
4. 简化测试代码(可选优化)
你可以利用Eloquent关联直接创建关联数据,无需手动构造OrderProduct数据:
public function testCalculateOrderTotal(): void { $address = Address::factory()->create(); $client = Client::factory()->create(['address_id' => $address->id]); $order = Order::factory()->create(['client_id' => $client->id]); // 通过关联创建带额外字段的透视表数据 $order->products()->attach([ Product::factory()->create()->id => ['quantity' => 2, 'price' => 100.00], Product::factory()->create()->id => ['quantity' => 1, 'price' => 150.00], ]); $orderProducts = $order->products->map(fn($product) => $product->pivot); $this->orderProductRepository ->shouldReceive('findByOrder') ->with($order->id) ->once() ->andReturn(collect($orderProducts)); $expectedTotal = (2 * 100.00) + (1 * 150.00); $total = $this->orderProductService->calculateOrderTotal($order->id); $this->assertIsFloat($total); $this->assertEquals($expectedTotal, $total); }
做完以上步骤后,重新执行测试命令即可解决报错。
内容的提问来源于stack exchange,提问作者barbgluz
相关产品推荐
相关产品推荐

