From 9f2ffc211c535b47f1cbd4d32b9d4c8ad52c1a1e Mon Sep 17 00:00:00 2001 From: Ryan Rigby <16025441+rrigby@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:50:24 +1000 Subject: [PATCH] Add withOneByJoin method Add tests --- src/Definition.php | 21 ++++++++++++ tests/Fixtures.sql | 11 ++++++ tests/MappingTest.php | 79 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) diff --git a/src/Definition.php b/src/Definition.php index 2aace3f..707b5e2 100644 --- a/src/Definition.php +++ b/src/Definition.php @@ -134,6 +134,27 @@ public function withMany(Definition $definition, string $name, string $foreignCo return $this; } + /** + * Adds a one-to-one relationship through a joined table. + * + * @param Definition $definition + * @param string $name + * @param string $foreignColumn + * @param string $localColumn + * @param string $joinTable + * @param string $joinForeignColumn + * @param string $joinLocalColumn + * @return Definition + */ + public function withOneByJoin(Definition $definition, string $name, string $foreignColumn, string $localColumn, string $joinTable, string $joinForeignColumn, string $joinLocalColumn) + { + $property = new Property($name, false, $definition, $localColumn, $foreignColumn); + $property->join($joinTable, $joinLocalColumn, $joinForeignColumn); + + $this->properties[] = $property; + return $this; + } + /** * Adds a one-to-many relationship through a joined table. * diff --git a/tests/Fixtures.sql b/tests/Fixtures.sql index 059477b..f0707fc 100644 --- a/tests/Fixtures.sql +++ b/tests/Fixtures.sql @@ -14,6 +14,9 @@ CREATE TABLE discounts (id INTEGER PRIMARY KEY, order_id INTEGER, description TE DROP TABLE IF EXISTS orders_fulfillments; CREATE TABLE orders_fulfillments (order_id INTEGER, employee_id INTEGER); +DROP TABLE IF EXISTS employees; +CREATE TABLE employees (id INTEGER PRIMARY KEY, name TEXT); + -- Seed database INSERT INTO customers (id, name) VALUES (1, 'John Doe'), @@ -34,3 +37,11 @@ INSERT INTO items (id, order_id, description, amount) VALUES INSERT INTO discounts (id, order_id, description, amount) VALUES (1, 2, '$10', 10); + +INSERT INTO employees (id, name) VALUES +(1, 'Alice'), +(2, 'Bob'); + +INSERT INTO orders_fulfillments (order_id, employee_id) VALUES +(1, 1), +(2, 2); diff --git a/tests/MappingTest.php b/tests/MappingTest.php index b7d31dc..245bc78 100644 --- a/tests/MappingTest.php +++ b/tests/MappingTest.php @@ -560,6 +560,51 @@ public function testFindOneWithDirectAndSecondaryLeft() $this->assertEquals(400, $customer['orders'][0]['items'][1]['amount']); } + public function testFindAllWithOneByJoin() + { + $orders = $this->getWithOneByJoinMapping()->findAll(); + + $this->assertCount(3, $orders); + + $this->assertEquals('Alice', $orders[0]['employee']['name']); + $this->assertEquals('Bob', $orders[1]['employee']['name']); + $this->assertNull($orders[2]['employee']); + } + + public function testFindOneWithOneByJoin() + { + $order = $this->getWithOneByJoinMapping()->eq('id', 2)->findOne(); + + $this->assertNotNull($order); + $this->assertEquals(2, $order['id']); + $this->assertEquals('Bob', $order['employee']['name']); + } + + public function testFindAllWithManyByJoin() + { + $employees = $this->getWithManyByJoinMapping()->findAll(); + + $this->assertCount(2, $employees); + + $this->assertEquals('Alice', $employees[0]['name']); + $this->assertCount(1, $employees[0]['orders']); + $this->assertEquals('2018-01-01', $employees[0]['orders'][0]['date_created']); + + $this->assertEquals('Bob', $employees[1]['name']); + $this->assertCount(1, $employees[1]['orders']); + $this->assertEquals('2018-01-02', $employees[1]['orders'][0]['date_created']); + } + + public function testFindOneWithManyByJoin() + { + $employee = $this->getWithManyByJoinMapping()->eq('id', 1)->findOne(); + + $this->assertNotNull($employee); + $this->assertEquals('Alice', $employee['name']); + $this->assertCount(1, $employee['orders']); + $this->assertEquals('2018-01-01', $employee['orders'][0]['date_created']); + } + /** * Returns a new mapping for testing. * @@ -599,6 +644,40 @@ public function getMapping() ]); } + /** + * Returns a mapping using withOneByJoin for testing. + * + * @return Mapping + */ + public function getWithOneByJoinMapping() + { + $employee = (new Definition('employees')) + ->withColumns('id', 'name'); + + $order = (new Definition('orders')) + ->withColumns('id', 'date_created') + ->withOneByJoin($employee, 'employee', 'id', 'id', 'orders_fulfillments', 'employee_id', 'order_id'); + + return new Mapping($this->db, $order); + } + + /** + * Returns a mapping using withManyByJoin for testing. + * + * @return Mapping + */ + public function getWithManyByJoinMapping() + { + $order = (new Definition('orders')) + ->withColumns('id', 'date_created'); + + $employee = (new Definition('employees')) + ->withColumns('id', 'name') + ->withManyByJoin($order, 'orders', 'id', 'id', 'orders_fulfillments', 'order_id', 'employee_id'); + + return new Mapping($this->db, $employee); + } + /** * Returns a new mapping for testing. *