Skip to content

Commit f223f92

Browse files
committed
- Experimental support for a TableGateway
1 parent e37d11c commit f223f92

File tree

3 files changed

+250
-6
lines changed

3 files changed

+250
-6
lines changed

src/Builder/RunnableSelect.php

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
<?php
22
namespace Kir\MySQL\Builder;
33

4+
use Closure;
5+
use Generator;
6+
use IteratorAggregate;
47
use Kir\MySQL\Builder\Helpers\FieldTypeProvider;
58
use Kir\MySQL\Builder\Helpers\FieldValueConverter;
69
use Kir\MySQL\Builder\Helpers\LazyRowGenerator;
10+
use Traversable;
711

812
/**
913
*/
10-
class RunnableSelect extends Select {
14+
class RunnableSelect extends Select implements IteratorAggregate {
1115
/** @var array */
1216
private $values = array();
1317
/** @var bool */
@@ -52,10 +56,10 @@ public function setPreserveTypes($preserveTypes = true) {
5256
}
5357

5458
/**
55-
* @param \Closure $callback
59+
* @param Closure $callback
5660
* @return array[]
5761
*/
58-
public function fetchRows(\Closure $callback = null) {
62+
public function fetchRows(Closure $callback = null) {
5963
return $this->createTempStatement(function (QueryStatement $statement) use ($callback) {
6064
$data = $statement->fetchAll(\PDO::FETCH_ASSOC);
6165
if($this->preserveTypes) {
@@ -72,10 +76,10 @@ public function fetchRows(\Closure $callback = null) {
7276
}
7377

7478
/**
75-
* @param \Closure $callback
76-
* @return array[]|\Generator
79+
* @param Closure $callback
80+
* @return array[]|Generator
7781
*/
78-
public function fetchRowsLazy(\Closure $callback = null) {
82+
public function fetchRowsLazy(Closure $callback = null) {
7983
if(version_compare(PHP_VERSION, '5.5', '<')) {
8084
return $this->fetchRows($callback);
8185
}
@@ -202,4 +206,11 @@ private function createStatement() {
202206
}
203207
return $statement;
204208
}
209+
210+
/**
211+
* @return Traversable|array[]|Generator
212+
*/
213+
public function getIterator() {
214+
return $this->fetchRowsLazy();
215+
}
205216
}

src/TableGateway.php

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<?php
2+
namespace Kir\MySQL;
3+
4+
use Exception;
5+
use Kir\MySQL\Builder\DBExpr;
6+
use Kir\MySQL\TableGateway\SelectResult;
7+
8+
/**
9+
* @internal
10+
*/
11+
class TableGateway {
12+
/** @var Database */
13+
private $db;
14+
/** @var array */
15+
private $primaryKeys;
16+
/** @var array */
17+
private $options;
18+
/** @var string */
19+
private $tableName;
20+
21+
/**
22+
* @param Database $db
23+
* @param string $tableName
24+
* @param array $primaryKeys
25+
* @param array $options
26+
*/
27+
public function __construct(Database $db, $tableName, array $primaryKeys, array $options = []) {
28+
$this->db = $db;
29+
$this->primaryKeys = array_values($primaryKeys);
30+
$options = array_merge(['allow-delete-all' => false], $options);
31+
$options = array_merge(['calc-found-rows' => false], $options);
32+
$options = array_merge(['preserve-types' => true], $options);
33+
$this->options = $options;
34+
$this->tableName = (string) $tableName;
35+
}
36+
37+
/**
38+
* @param array $data
39+
* @param array $options
40+
* @return SelectResult
41+
*/
42+
public function select(array $data = [], array $options = []) {
43+
$select = $this->db->select()
44+
->from('t', $this->tableName);
45+
if(array_key_exists('select-fields', $options) && is_array($options['select-fields'])) {
46+
$select->fields($options['select-fields']);
47+
}
48+
if(array_key_exists('calc-found-rows', $options)) {
49+
$select->setCalcFoundRows($options['calc-found-rows']);
50+
}
51+
if(array_key_exists('preserve-types', $options)) {
52+
$select->setPreserveTypes($options['preserve-types']);
53+
}
54+
if(array_key_exists('select-distinct', $options)) {
55+
$select->distinct($options['select-distinct']);
56+
}
57+
foreach($data as $fieldName => $value) {
58+
if($value instanceof DBExpr) {
59+
$select->where($value);
60+
} else {
61+
$select->where(sprintf("%s=?", $this->db->quoteField($fieldName)), $value);
62+
}
63+
}
64+
if(array_key_exists('debug', $options)) {
65+
$select->debug($options['debug']);
66+
}
67+
return new SelectResult($select, $options);
68+
}
69+
70+
/**
71+
* @param array $data
72+
* @param array $options
73+
* @return int
74+
*/
75+
public function insert(array $data, array $options = []) {
76+
$options = array_merge($this->options, $options);
77+
$insert = $this->db->insert()
78+
->into($this->tableName);
79+
if(array_key_exists('mask', $options) && is_array($options['mask'])) {
80+
$insert->setMask(array_values($options['mask']));
81+
}
82+
if(count($this->primaryKeys) === 1) {
83+
$insert->setKey($this->primaryKeys[0]);
84+
}
85+
if(array_key_exists('defaults', $options)) {
86+
$data = array_merge($options['defaults'], $data);
87+
}
88+
if(array_key_exists('insert-defaults', $options)) {
89+
$data = array_merge($options['insert-defaults'], $data);
90+
}
91+
if(array_key_exists('insert-ignore', $options)) {
92+
$insert->setIgnore($options['insert-ignore']);
93+
}
94+
$insert->addAll($data);
95+
if(array_key_exists('debug', $options)) {
96+
$insert->debug($options['debug']);
97+
}
98+
return $insert->run();
99+
}
100+
101+
/**
102+
* @param array $data
103+
* @param array $options
104+
* @return int
105+
*/
106+
public function upsert(array $data, array $options = []) {
107+
$options = array_merge($this->options, $options);
108+
$insert = $this->db->insert()
109+
->into($this->tableName);
110+
if(array_key_exists('mask', $options) && is_array($options['mask'])) {
111+
$insert->setMask(array_values($options['mask']));
112+
}
113+
if(count($this->primaryKeys) === 1) {
114+
$insert->setKey($this->primaryKeys[0]);
115+
}
116+
if(array_key_exists('defaults', $options)) {
117+
$data = array_merge($options['defaults'], $data);
118+
}
119+
if(array_key_exists('insert-defaults', $options)) {
120+
$data = array_merge($options['insert-defaults'], $data);
121+
}
122+
$keyData = array_intersect_key($data, array_combine($this->primaryKeys, $this->primaryKeys));
123+
$insert->addAll($keyData);
124+
$valueData = array_diff_key($data, array_combine($this->primaryKeys, $this->primaryKeys));
125+
$insert->addOrUpdateAll($valueData);
126+
if(array_key_exists('debug', $options)) {
127+
$insert->debug($options['debug']);
128+
}
129+
return $insert->run();
130+
}
131+
132+
/**
133+
* @param array $data
134+
* @param array $options
135+
* @return int
136+
*/
137+
public function update(array $data, array $options = []) {
138+
$options = array_merge($this->options, $options);
139+
$update = $this->db->update()
140+
->table($this->tableName);
141+
if(array_key_exists('mask', $options) && is_array($options['mask'])) {
142+
$update->setMask(array_values($options['mask']));
143+
}
144+
if(array_key_exists('defaults', $options)) {
145+
$data = array_merge($options['defaults'], $data);
146+
}
147+
if(array_key_exists('update-defaults', $options)) {
148+
$data = array_merge($options['update-defaults'], $data);
149+
}
150+
$keyData = array_intersect_key($data, array_combine($this->primaryKeys, $this->primaryKeys));
151+
foreach($keyData as $fieldName => $value) {
152+
$update->where(sprintf("%s=?", $this->db->quoteField($fieldName)), $value);
153+
}
154+
$valueData = array_diff_key($data, array_combine($this->primaryKeys, $this->primaryKeys));
155+
$update->setAll($valueData);
156+
if(array_key_exists($options, 'debug')) {
157+
$update->debug($options['debug']);
158+
}
159+
return $update->run();
160+
}
161+
162+
/**
163+
* @param array $data
164+
* @param array $options
165+
* @return int
166+
* @throws Exception
167+
*/
168+
public function delete(array $data = null, array $options = []) {
169+
if(!is_array($data)) {
170+
throw new Exception('Missing data parameter');
171+
}
172+
$options = array_merge($this->options, $options);
173+
$delete = $this->db->delete()
174+
->from($this->tableName);
175+
if(array_key_exists('delete-defaults', $options)) {
176+
$data = array_merge($options['delete-defaults'], $data);
177+
}
178+
$keyData = array_intersect_key($data, array_combine($this->primaryKeys, $this->primaryKeys));
179+
if(count($keyData) !== count($this->primaryKeys) && !$options['allow-delete-all']) {
180+
throw new Exception("You try to delete all data from {$this->tableName} which is not allowed by configuration");
181+
}
182+
foreach($keyData as $fieldName => $value) {
183+
$delete->where(sprintf("%s=?", $this->db->quoteField($fieldName)), $value);
184+
}
185+
if(array_key_exists($options, 'debug')) {
186+
$delete->debug($options['debug']);
187+
}
188+
return $delete->run();
189+
}
190+
}

src/TableGateway/SelectResult.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
namespace Kir\MySQL\TableGateway;
3+
4+
use IteratorAggregate;
5+
use Kir\MySQL\Builder\RunnableSelect;
6+
use Traversable;
7+
8+
class SelectResult implements IteratorAggregate {
9+
/** @var RunnableSelect */
10+
private $select;
11+
/** @var array */
12+
private $options;
13+
14+
/**
15+
* @param RunnableSelect $select
16+
* @param array $options
17+
*/
18+
public function __construct(RunnableSelect $select, array $options = []) {
19+
$this->select = $select;
20+
$this->options = $options;
21+
}
22+
23+
/**
24+
* @return RunnableSelect
25+
*/
26+
public function query() {
27+
return $this->select;
28+
}
29+
30+
/**
31+
* @return int
32+
*/
33+
public function getFoundRows() {
34+
return $this->getFoundRows();
35+
}
36+
37+
/**
38+
* @return Traversable|array[]
39+
*/
40+
public function getIterator() {
41+
return $this->select->getIterator();
42+
}
43+
}

0 commit comments

Comments
 (0)