Skip to content

Commit 959174c

Browse files
committed
restructure model class and tests
Signed-off-by: Derek Smart <derek@grindaga.com>
1 parent b80a105 commit 959174c

File tree

8 files changed

+467
-172
lines changed

8 files changed

+467
-172
lines changed

src/Model.php

Lines changed: 0 additions & 44 deletions
This file was deleted.

src/PHPRed.php

Lines changed: 0 additions & 78 deletions
This file was deleted.

src/PHPRed/Model.php

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
<?php
2+
namespace PHPRed\Models;
3+
4+
abstract class Model
5+
{
6+
protected $mysql;
7+
protected $alias;
8+
protected $data;
9+
public $model;
10+
public $table;
11+
public $primaryKey;
12+
public $foreignKey;
13+
public $fields;
14+
public $requiredFields;
15+
public $uniqueFields;
16+
public $hasMany;
17+
public $belongsTo;
18+
public $hasAndBelongsToMany;
19+
20+
public function __construct(\MysqliDb $mysql)
21+
{
22+
$this->mysql = $mysql;
23+
$this->alias = $this->table . ' ' . $this->model;
24+
if (!$this->fields) {
25+
$this->fields = [];
26+
}
27+
}
28+
29+
protected function filterByFields(array $results, array $fields) : array
30+
{
31+
if (!$fields) {
32+
return $results;
33+
}
34+
$filtered = [];
35+
foreach ($results as $result) {
36+
foreach ($result as $key => $value) {
37+
if (!in_array($key, $fields) && !is_array($value)) {
38+
unset($result[$key]);
39+
}
40+
}
41+
array_push($filtered, $result);
42+
}
43+
return $filtered;
44+
}
45+
46+
protected function validate(array $data)
47+
{
48+
$this->validateRequiredFields($data);
49+
$this->validateUniqueFields($data);
50+
}
51+
52+
protected function validateRequiredFields(array $data)
53+
{
54+
if ($this->requiredFields) {
55+
foreach ($this->requiredFields as $requiredField) {
56+
if (!array_key_exists($requiredField, $data)) {
57+
throw new \InvalidArgumentException(
58+
$requiredField . ' is required for ' . $this->model . '.'
59+
);
60+
}
61+
}
62+
}
63+
}
64+
65+
protected function validateUniqueFields(array $data)
66+
{
67+
if ($this->uniqueFields) {
68+
foreach ($this->uniqueFields as $uniqueField) {
69+
$check = $this->getBySearch([$uniqueField => $data[$uniqueField]]);
70+
if ($check) {
71+
throw new \InvalidArgumentException(
72+
$uniqueField . ' must be unique for ' . $this->model . '.'
73+
);
74+
}
75+
}
76+
}
77+
}
78+
79+
protected function attachRelated()
80+
{
81+
$this->attachHasMany();
82+
$this->attachBelongsTo();
83+
$this->attachHABTM();
84+
}
85+
86+
protected function attachHasMany()
87+
{
88+
$this->attachByMethod('hasMany');
89+
}
90+
91+
protected function attachBelongsTo()
92+
{
93+
$this->attachByMethod('belongsTo');
94+
}
95+
96+
protected function attachByMethod(string $method)
97+
{
98+
if ($this->$method) {
99+
foreach ($this->$method as $attachModel) {
100+
$attachModel = __NAMESPACE__ . '\\' . $attachModel;
101+
$attach = new $attachModel($this->mysql);
102+
foreach ($this->data as $key => $model) {
103+
switch ($method) {
104+
case 'hasMany':
105+
$this->data[$key][$attach->model] = $attach->getBySearch(
106+
[$this->foreignKey => $model[$this->primaryKey]]
107+
);
108+
break;
109+
case 'belongsTo':
110+
$this->data[$key][$attach->model] = $attach->getBySearch(
111+
[$attach->primaryKey => $model[$attach->foreignKey]]
112+
);
113+
break;
114+
}
115+
}
116+
}
117+
}
118+
}
119+
120+
protected function getJoinTable(array $tables) : string
121+
{
122+
sort($tables);
123+
return $tables[0] . '_' . $tables[1];
124+
}
125+
126+
protected function setHABTMFields(string $model, array $fields) : array
127+
{
128+
$joined = [];
129+
foreach ($fields as $field) {
130+
array_push($joined, $model . '.' . $field);
131+
}
132+
return $joined;
133+
}
134+
135+
protected function attachHABTM()
136+
{
137+
if ($this->hasAndBelongsToMany) {
138+
foreach ($this->hasAndBelongsToMany as $habtmModel) {
139+
$habtmModel = __NAMESPACE__ . '\\' . $habtmModel;
140+
$habtm = new $habtmModel($this->mysql);
141+
foreach ($this->data as $key => $model) {
142+
$alias = $habtm->table . ' ' . $habtm->model;
143+
$joinTable = $this->getJoinTable([$habtm->table,$this->table]);
144+
$join = $habtm->model . '.' . $habtm->primaryKey . ' = ' . $joinTable . ' . ' . $habtm->foreignKey;
145+
$this->mysql->join($alias, $join, 'LEFT');
146+
$this->mysql->where($joinTable . '.' . $this->foreignKey, $model[$this->primaryKey]);
147+
$this->data[$key][$habtm->model] = $this->mysql->get(
148+
$joinTable . ' ' . $joinTable,
149+
null,
150+
$this->setHABTMFields($habtm->model, $habtm->fields)
151+
);
152+
}
153+
}
154+
}
155+
}
156+
157+
public function getAll() : array
158+
{
159+
$this->data = $this->mysql->get($this->alias);
160+
$this->attachRelated();
161+
return $this->filterByFields($this->data, $this->fields);
162+
}
163+
164+
public function getById(int $modelId) : array
165+
{
166+
$this->mysql->where($this->primaryKey, $modelId);
167+
$this->data = $this->mysql->get($this->alias);
168+
$this->attachRelated();
169+
$result = $this->filterByFields($this->data, $this->fields);
170+
return $result[0];
171+
}
172+
173+
public function getBySearch(array $search) : array
174+
{
175+
foreach ($search as $key => $value) {
176+
$this->mysql->where($this->model . '.' . $key, $value);
177+
}
178+
$this->data = $this->mysql->get($this->alias);
179+
return $this->filterByFields($this->data, $this->fields);
180+
}
181+
182+
public function insert(array $data) : array
183+
{
184+
$this->validate($data);
185+
$this->mysql->startTransaction();
186+
if (!$this->mysql->insert($this->table, $data)) {
187+
$this->mysql->rollback();
188+
throw new \InvalidArgumentException(
189+
'Failed to create ' . $this->model . '.' . $this->mysql->getLastError()
190+
);
191+
}
192+
$data['id'] = $this->mysql->getInsertId();
193+
$this->mysql->commit();
194+
return $data;
195+
}
196+
197+
public function updateById(int $modelId, array $data) : array
198+
{
199+
$this->validate($data);
200+
$this->mysql->startTransaction();
201+
$this->mysql->where($this->primaryKey, $modelId);
202+
if (!$this->mysql->update($this->table, $data)) {
203+
$this->mysql->rollback();
204+
throw new \InvalidArgumentException(
205+
'Failed to update ' . $this->model . '.' . $this->mysql->getLastError()
206+
);
207+
}
208+
$this->mysql->commit();
209+
return $data;
210+
}
211+
212+
public function deleteById(int $modelId)
213+
{
214+
$this->mysql->startTransaction();
215+
$this->mysql->where($this->primaryKey, $modelId);
216+
if (!$this->mysql->delete($this->table)) {
217+
$this->mysql->rollback();
218+
throw new \InvalidArgumentException(
219+
'Failed to delete ' . $this->model . '.' . $this->mysql->getLastError()
220+
);
221+
}
222+
$this->mysql->commit();
223+
}
224+
}

tests/bootstrap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<?php
22
require(__DIR__."/../vendor/autoload.php");
33
require(__DIR__."/../src/autoload.php");
4+
require(__DIR__."/mocks/autoload.php");

tests/mocks/Pipe.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
namespace PHPRed\Models;
3+
4+
class Pipe extends Model
5+
{
6+
public function __construct(\MysqliDb $mysql)
7+
{
8+
$this->model = 'Pipe';
9+
$this->table = 'pipes';
10+
$this->primaryKey = 'id';
11+
$this->foreignKey = 'pipe_id';
12+
$this->fields = ['id', 'name', 'pipe_name'];
13+
$this->requiredFields = ['name', 'pipe_name'];
14+
$this->uniqueFields = ['name', 'pipe_name'];
15+
$this->hasMany = ['PipeUser'];
16+
$this->hasAndBelongsToMany = ['Service'];
17+
18+
parent::__construct($mysql);
19+
}
20+
}

0 commit comments

Comments
 (0)