Skip to content

Commit 6a806a5

Browse files
committed
Add option to join a table in Finder
1 parent afbac7a commit 6a806a5

File tree

3 files changed

+212
-0
lines changed

3 files changed

+212
-0
lines changed

src/Finder.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use ActiveCollab\DatabaseConnection\ConnectionInterface;
55
use ActiveCollab\DatabaseConnection\Result\Result;
6+
use Doctrine\Common\Inflector\Inflector;
67
use InvalidArgumentException;
78

89
/**
@@ -44,6 +45,11 @@ class Finder
4445
* @var integer|null
4546
*/
4647
private $limit;
48+
49+
/**
50+
* @var string
51+
*/
52+
private $join;
4753

4854
/**
4955
* @param PoolInterface $pool
@@ -118,6 +124,45 @@ public function &limit($offset, $limit)
118124
return $this;
119125
}
120126

127+
/**
128+
* @param string $type
129+
* @param string $field_name
130+
* @return $this
131+
*/
132+
public function &join($type, $field_name = null)
133+
{
134+
return $this->joinTable($this->pool->getTypeTable($type), $field_name);
135+
}
136+
137+
/**
138+
* @param string $table_name
139+
* @param string $field_name
140+
* @return $this
141+
*/
142+
public function &joinTable($table_name, $field_name = null)
143+
{
144+
$join_table = $this->connection->escapeTableName($table_name);
145+
$join_field = $this->connection->escapeFieldname($field_name ? $field_name : $this->getJoinFieldNameFromType());
146+
147+
$this->join = "LEFT JOIN $join_table ON {$this->getEscapedTableName()}.`id` = $join_table.$join_field";
148+
149+
return $this;
150+
}
151+
152+
/**
153+
* @return string
154+
*/
155+
private function getJoinFieldNameFromType()
156+
{
157+
if (($pos = strrpos($this->getType(), '\\')) === false) {
158+
$type = $this->getType();
159+
} else {
160+
$type = substr($this->getType(), $pos + 1);
161+
}
162+
163+
return Inflector::tableize($type) . '_id';
164+
}
165+
121166
// ---------------------------------------------------
122167
// Execution
123168
// ---------------------------------------------------
@@ -131,6 +176,10 @@ public function count()
131176
{
132177
$sql = "SELECT COUNT(`id`) AS 'row_count' FROM " . $this->getEscapedTableName();
133178

179+
if ($this->join) {
180+
$sql .= " $this->join";
181+
}
182+
134183
if ($this->conditions) {
135184
$sql .= " WHERE $this->conditions";
136185
}
@@ -251,6 +300,10 @@ private function getSelectFieldsSql($escaped_field_names)
251300
{
252301
$result = "SELECT $escaped_field_names FROM " . $this->getEscapedTableName();
253302

303+
if ($this->join) {
304+
$result .= " $this->join";
305+
}
306+
254307
if ($this->conditions) {
255308
$result .= " WHERE $this->conditions";
256309
}

src/FinderInterface.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ interface FinderInterface
1212
*/
1313
public function getType();
1414

15+
// ---------------------------------------------------
16+
// Configuration
17+
// ---------------------------------------------------
18+
1519
/**
1620
* Set finder conditions
1721
*
@@ -34,6 +38,24 @@ public function &orderBy($order_by);
3438
*/
3539
public function &limit($offset, $limit);
3640

41+
/**
42+
* @param string $type
43+
* @param string $field_name
44+
* @return $this
45+
*/
46+
public function &join($type, $field_name = null);
47+
48+
/**
49+
* @param string $table_name
50+
* @param string $field_name
51+
* @return $this
52+
*/
53+
public function &joinTable($table_name, $field_name = null);
54+
55+
// ---------------------------------------------------
56+
// Execution
57+
// ---------------------------------------------------
58+
3759
/**
3860
* Return number of records that match the given criteria
3961
*

test/src/FindJoinTest.php

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
namespace ActiveCollab\DatabaseObject\Test;
3+
4+
use ActiveCollab\DatabaseObject\Test\Base\WritersTypeTestCase;
5+
use ActiveCollab\DatabaseObject\Test\Fixtures\Writers\Writer;
6+
use ActiveCollab\DatabaseConnection\Result\ResultInterface;
7+
use ActiveCollab\DatabaseConnection\Result\Result;
8+
use ActiveCollab\DatabaseObject\Finder;
9+
use ActiveCollab\DateValue\DateValue;
10+
11+
/**
12+
* @package ActiveCollab\DatabaseObject\Test
13+
*/
14+
class FindJoinTest extends WritersTypeTestCase
15+
{
16+
/**
17+
* Set up test environment
18+
*/
19+
public function setUp()
20+
{
21+
parent::setUp();
22+
23+
if ($this->connection->tableExists('writer_groups')) {
24+
$this->connection->dropTable('writer_groups');
25+
}
26+
27+
$create_table = $this->connection->execute("CREATE TABLE `writer_groups` (
28+
`writer_id` int(11) NOT NULL DEFAULT '0',
29+
`group_id` int(11) NOT NULL DEFAULT '0',
30+
PRIMARY KEY (`writer_id`, `group_id`)
31+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;");
32+
33+
$this->assertTrue($create_table);
34+
35+
$this->connection->execute('INSERT INTO `writer_groups` (`writer_id`, `group_id`) VALUES (?, ?), (?, ?), (?, ?)', 1, 1, 2, 1, 3, 2);
36+
37+
$this->assertEquals(2, $this->connection->count('writer_groups', ['group_id = ?', 1], '*'));
38+
$this->assertEquals(1, $this->connection->count('writer_groups', ['group_id = ?', 2], '*'));
39+
}
40+
41+
/**
42+
* Tear down test environment
43+
*/
44+
public function tearDown()
45+
{
46+
if ($this->connection->tableExists('writer_groups')) {
47+
$this->connection->dropTable('writer_groups');
48+
}
49+
50+
parent::tearDown();
51+
}
52+
53+
/**
54+
* Test count all
55+
*/
56+
public function testCount()
57+
{
58+
$this->assertEquals(3, $this->pool->find(Writer::class)->count());
59+
$this->assertEquals(2, $this->pool->find(Writer::class)->joinTable('writer_groups')->where('writer_groups.group_id = ?', 1)->count());
60+
$this->assertEquals(1, $this->pool->find(Writer::class)->joinTable('writer_groups')->where('writer_groups.group_id = ?', 2)->count());
61+
}
62+
63+
/**
64+
* Test find all writers from the database
65+
*/
66+
public function testFindAll()
67+
{
68+
/** @var Result $result */
69+
$result = $this->pool->find(Writer::class)->all();
70+
71+
$this->assertInstanceOf(Result::class, $result);
72+
$this->assertCount(3, $result);
73+
74+
/** @var Result $result */
75+
$result = $this->pool->find(Writer::class)->joinTable('writer_groups')->where('writer_groups.group_id = ?', 1)->all();
76+
77+
$this->assertInstanceOf(Result::class, $result);
78+
$this->assertCount(2, $result);
79+
80+
/** @var Result $result */
81+
$result = $this->pool->find(Writer::class)->joinTable('writer_groups')->where('writer_groups.group_id = ?', 2)->all();
82+
83+
$this->assertInstanceOf(Result::class, $result);
84+
$this->assertCount(1, $result);
85+
}
86+
87+
/**
88+
* Test find first record
89+
*/
90+
public function testFindFirst()
91+
{
92+
/** @var Writer $should_be_leo */
93+
$should_be_tolstoy = $this->pool->find(Writer::class)->orderBy('`id`')->first();
94+
95+
$this->assertInstanceOf(Writer::class, $should_be_tolstoy);
96+
$this->assertTrue($should_be_tolstoy->isLoaded());
97+
$this->assertEquals('Leo Tolstoy', $should_be_tolstoy->getName());
98+
99+
/** @var Writer $should_be_tolstoy */
100+
$should_be_tolstoy = $this->pool->find(Writer::class)->orderBy('`id`')->joinTable('writer_groups')->where('writer_groups.group_id = ?', 1)->first();
101+
102+
$this->assertInstanceOf(Writer::class, $should_be_tolstoy);
103+
$this->assertTrue($should_be_tolstoy->isLoaded());
104+
$this->assertEquals('Leo Tolstoy', $should_be_tolstoy->getName());
105+
106+
/** @var Writer $should_be_dostoyevsky */
107+
$should_be_dostoyevsky = $this->pool->find(Writer::class)->orderBy('`id`')->joinTable('writer_groups')->where('writer_groups.group_id = ?', 2)->first();
108+
109+
$this->assertInstanceOf(Writer::class, $should_be_dostoyevsky);
110+
$this->assertTrue($should_be_dostoyevsky->isLoaded());
111+
$this->assertEquals('Fyodor Dostoyevsky', $should_be_dostoyevsky->getName());
112+
}
113+
114+
/**
115+
* Test find all ID-s
116+
*/
117+
public function testFindAllIds()
118+
{
119+
$ids = $this->pool->find(Writer::class)->orderBy('id')->ids();
120+
121+
$this->assertInternalType('array', $ids);
122+
$this->assertCount(3, $ids);
123+
$this->assertEquals([1, 2, 3], $ids);
124+
125+
$ids = $this->pool->find(Writer::class)->orderBy('id')->joinTable('writer_groups')->where('writer_groups.group_id = ?', 1)->ids();
126+
127+
$this->assertInternalType('array', $ids);
128+
$this->assertCount(2, $ids);
129+
$this->assertEquals([1, 2], $ids);
130+
131+
$ids = $this->pool->find(Writer::class)->orderBy('id')->joinTable('writer_groups')->where('writer_groups.group_id = ?', 2)->ids();
132+
133+
$this->assertInternalType('array', $ids);
134+
$this->assertCount(1, $ids);
135+
$this->assertEquals([3], $ids);
136+
}
137+
}

0 commit comments

Comments
 (0)