diff --git a/src/HasParent.php b/src/HasParent.php index f2a33a9..7e9a188 100644 --- a/src/HasParent.php +++ b/src/HasParent.php @@ -70,10 +70,11 @@ public function getClassNameForRelationships() public function getMorphClass() { - if ($this->parentHasHasChildrenTrait() && in_array(static::class, $this->getChildTypes())) { + if ($this->parentHasHasChildrenTrait()) { $parentClass = $this->getParentClass(); return (new $parentClass)->getMorphClass(); } + return parent::getMorphClass(); } diff --git a/tests/Features/PolymorphismTest.php b/tests/Features/PolymorphismTest.php index 827a4f3..6f297ff 100644 --- a/tests/Features/PolymorphismTest.php +++ b/tests/Features/PolymorphismTest.php @@ -11,163 +11,79 @@ class PolymorphismTest extends TestCase { /** @test */ - public function morph_by_many() + public function parts_can_access_vehicles_with_morphed_by_many() { - Vehicle::create()->parts()->create([]); - Car::create()->parts()->create([]); + Vehicle::create()->parts()->create(); + Car::create()->parts()->create(); - $parts = Part::with('vehicles')->get(); + $parts = Part::all(); $vehicle = $parts->first()->vehicles->first(); - $this->assertInstanceOf(Vehicle::class, $vehicle); - $car = $parts->last()->vehicles->first(); + + $this->assertInstanceOf(Vehicle::class, $vehicle); $this->assertInstanceOf(Car::class, $car); - /** @var Part $part */ $part = Part::create(); $part->vehicles()->attach($vehicle); $part->vehicles()->attach($car); - $part = Part::find($part->getKey()); + $part->refresh(); $this->assertTrue($vehicle->is($part->vehicles()->first())); - $this->assertInstanceOf(Vehicle::class, $part->vehicles()->first()); - $this->assertTrue($car->is($part->vehicles()->get()->pop())); + $this->assertInstanceOf(Vehicle::class, $part->vehicles()->first()); $this->assertInstanceOf(Car::class, $part->vehicles()->get()->pop()); } /** @test */ - public function can_query_where_has_one() + public function can_query_where_has_from_child_to_morphed() { - $_1 = Part::create(['type' => 'tire']); - $_2 = Part::create(['type' => 'wing']); - $_3 = Part::create(['type' => 'engine']); - $_4 = Part::create(['type' => 'seat']); - $_5 = Part::create(['type' => 'some metal thing']); - $_6 = Part::create(['type' => 'i dont know car parts w/e']); - - /** @var Car $car */ - $car = Car::create([]); - /** @var Vehicle $vehicle */ - $vehicle = Vehicle::create([]); - - $car->parts()->attach($_1); - $car->parts()->attach($_2); - $car->parts()->attach($_3); - - $vehicle->parts()->attach($_4); - $vehicle->parts()->attach($_5); - $vehicle->parts()->attach($_6); - - $this->assertNull(Car::query()->whereHas('parts', function ($query) { - $query->where('type', 'seat'); - })->first()); - - $checker = Vehicle::query()->whereHas('parts', function ($query) { + $notCar = Vehicle::create(); + $car = Car::create(); + + $notCar->parts()->attach(Part::create(['type' => 'wing'])); + $car->parts()->attach(Part::create(['type' => 'tire'])); + + $shouldNotBeCar = Car::query()->whereHas('parts', function ($query) { + $query->where('type', 'wing'); + })->first(); + + $shouldBeCar = Vehicle::query()->whereHas('parts', function ($query) { $query->where('type', 'tire'); })->first(); - $this->assertNotNull($checker); - $this->assertTrue($car->is($checker)); - $this->assertInstanceOf(Car::class, $checker); + $this->assertNull($shouldNotBeCar); + $this->assertTrue($car->is($shouldBeCar)); + $this->assertInstanceOf(Car::class, $shouldBeCar); } /** @test */ - public function can_query_where_has_two() + public function can_query_deeply_from_morphed_to_parental_models_via_where_has() { - /** @var Part $part */ - Part::create(); - Part::create(); - $part = Part::create(); - Part::create(); - $otherPart = Part::create(); - Part::create(); - /** @var Car $car */ - $car = Car::create([]); - /** @var Vehicle $vehicle */ - $vehicle = Vehicle::create([]); - $part->vehicles()->create([]); - $part->vehicles()->attach($vehicle); - $part->vehicles()->attach($car); + Part::create()->vehicles()->attach($car = Car::create()); + $car->passengers()->create(['name' => 'Robert']); - $otherPart->vehicles()->create([]); - $otherPart->vehicles()->create([]); - $otherPart->vehicles()->create([]); - $otherPart->vehicles()->attach($vehicle); + $part = Part::whereHas('vehicles.passengers', function ($query) { + $query->where('name', 'Robert'); + })->first(); - $car->passengers()->create(['name' => 'Robert']); - $car->passengers()->create(['name' => 'Joe']); - $car->passengers()->create(['name' => 'John']); - $vehicle->passengers()->create(['name' => 'Bob']); - $vehicle->passengers()->create(['name' => 'Karl']); - - $checker = Part::query() - ->whereHas('vehicles.passengers', function ($query) { - $query->where('name', 'Robert'); - }) - ->first(); - - $this->assertTrue($part->is($checker)); - - $checker = Part::query() - ->whereHas('vehicles.passengers', function ($query) { - $query->where('name', 'Robert'); - }) - ->with(['vehicles.passengers' => function ($query) { - $query->where('name', 'Robert'); - }]) - ->first(); - - $this->assertTrue($car->is($checker->vehicles()->first())); - $this->assertEquals('Robert', $checker->vehicles()->first()->passengers()->first()->name); + $this->assertTrue($car->is($part->vehicles()->first())); + $this->assertEquals('Robert', $part->vehicles()->first()->passengers()->value('name')); } /** @test */ - public function can_query_where_has_three() + public function can_query_deeply_from_parental_models_to_morphed_via_where_has() { - /** @var Car $car */ $car = Car::create(); - /** @var Vehicle $vehicle */ - $vehicle = Vehicle::create(); - - $joe = Passenger::create(['name' => 'joe', 'vehicle_id' => $car->id]); - Passenger::create(['name' => 'john', 'vehicle_id' => $vehicle->id]); - Passenger::create(['name' => 'carl', 'vehicle_id' => $car->id]); - Passenger::create(['name' => 'tony', 'vehicle_id' => $vehicle->id]); - Passenger::create(['name' => 'robert', 'vehicle_id' => $car->id]); - + $passenger = $car->passengers()->create(['name' => 'joe']); $car->parts()->create(['type' => 'tire']); - $car->parts()->create(['type' => 'some']); - $car->parts()->create(['type' => 'type']); - $vehicle->parts()->create(['type' => 'and']); - $vehicle->parts()->create(['type' => 'some']); - $vehicle->parts()->create(['type' => 'other']); - - // This already works today, but it's pretty ugly - $passenger = Passenger::query()->where(function ($query) { - $query->orWhereHas('car.parts', function ($query) { - $query->where('type', 'tire'); - })->orWhereHas('vehicle.parts', function ($query) { - $query->where('type', 'tire'); - }); - })->first(); - - $this->assertNotNull($passenger); - $this->assertTrue($joe->is($passenger)); - $this->assertTrue($car->is($passenger->vehicle)); - $this->assertInstanceOf(Car::class, $passenger->vehicle); - - unset($passenger); - // This works with the new version $passenger = Passenger::query()->whereHas('vehicle.parts', function ($query) { $query->where('type', 'tire'); })->first(); - $this->assertNotNull($passenger); - $this->assertTrue($joe->is($passenger)); + $this->assertTrue($passenger->is($passenger)); $this->assertTrue($car->is($passenger->vehicle)); $this->assertInstanceOf(Car::class, $passenger->vehicle); }