Completed
Push — master ( aeb1e8...e32bea )
by Wanderson
02:48
created

DAO::selectedCollumns()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
rs 10
nc 1
cc 1
eloc 2
nop 1
1
<?php
2
3
namespace Win\DAO;
4
5
use Win\Mvc\Application;
6
use Win\Connection\MySQL;
7
8
/**
9
 * Data Access Object
10
 */
11
abstract class DAO implements DAOInterface {
12
13
	/** @var \PDO */
14
	protected $pdo;
15
16
	/** @var string[] */
17
	protected $selectCollumns = ['*'];
18
19
	/**
20
	 * Retorna um objeto a partir da linha da tabela
21
	 * @param array[] $row
22
	 */
23
	abstract protected function mapObject($row);
24
25
	/** Retorna a linha da tabela a partir de um objeto
26
	 * @param object $obj
27
	 */
28
	abstract protected function mapRow($obj);
29
30
	/** Inicia o DAO */
31
	public function __construct() {
32
		$this->pdo = MySQL::instance()->getPDO();
33
	}
34
35
	/**
36
	 * Define uma conexão manualmente
37
	 * @param \PDO $pdo
38
	 */
39
	public function setPDO($pdo) {
40
		$this->pdo = $pdo;
41
	}
42
43
	/**
44
	 * Define quais colunas serão consultadas nos comandos SELECT
45
	 * @param string[] $collumns
46
	 */
47
	public function setSelectCollumns(array $collumns) {
48
		$this->selectCollumns = $collumns;
49
	}
50
51
	/**
52
	 * Adiciona nova coluna no select
53
	 * @param string $collumn
54
	 */
55
	public function addSelectCollumn($collumn) {
56
		if (!in_array($collumn, $this->selectCollumns)) {
57
			$this->selectCollumns[] = $collumn;
58
		}
59
	}
60
61
	/**
62
	 * Salva o registro
63
	 * @param object $obj
64
	 */
65
	public function save($obj) {
66
		$this->obj = $obj;
0 ignored issues
show
Bug introduced by
The property obj does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
67
		if (!$this->objExists()) {
68
			$this->insert();
69
			if ($this->pdo) {
70
				$this->obj->setId($this->pdo->lastInsertId());
71
			}
72
		} else {
73
			$this->update();
74
		}
75
	}
76
77
	/** Insere o registro */
78
	protected function insert() {
79
		$mapRow = $this->mapRow($this->obj);
80
		$keys = array_keys($mapRow);
81
		$values = array_values($mapRow);
82
		$params = str_split(str_repeat('?', count($keys)));
83
84
		$sql = 'INSERT INTO ' . static::TABLE . ' (' . implode(',', $keys) . ') VALUES (' . implode(', ', $params) . ') ';
85
		if ($this->pdo) {
86
			$stmt = $this->pdo->prepare($sql);
87
			$stmt->execute($values);
88
		}
89
	}
90
91
	/** Atualiza o registro */
92
	protected function update() {
93
		$mapRow = $this->mapRow($this->obj);
94
		$keys = array_keys($mapRow);
95
		$values = array_values($mapRow);
96
		$params = [];
97
		foreach ($keys as $key):
98
			$params[] = $key . ' = ?';
99
		endforeach;
100
		$values[] = $this->obj->getId();
101
102
		$sql = 'UPDATE ' . static::TABLE . ' SET ' . implode(', ', $params) . ' WHERE id = ? ';
103
		if ($this->pdo) {
104
			$stmt = $this->pdo->prepare($sql);
105
			$stmt->execute($values);
106
		}
107
	}
108
109
	/**
110
	 * Exclui o registro
111
	 * @param object $obj
112
	 */
113
	public function delete($obj) {
114
		$this->deleteById($obj->getId());
115
	}
116
117
	/**
118
	 * Exclui o registro por id
119
	 * @param int $id
120
	 */
121
	public function deleteById($id) {
122
		$sql = 'DELETE FROM ' . static::TABLE . ' WHERE id = :id';
123
		if ($this->pdo) {
124
			$stmt = $this->pdo->prepare($sql);
125
			$stmt->bindValue(':id', $id);
126
			$stmt->execute();
127
		}
128
	}
129
130
	/**
131
	 * Busca o objeto pelo id
132
	 * @param int $id
133
	 */
134
	public function fetchById($id) {
135
		return $this->fetchByField('id', $id);
136
	}
137
138
	/**
139
	 * Busca o objeto por um campo/atributo específico
140
	 * @param string $name Nome do atributo
141
	 * @param mixed $value Valor do atributo
142
	 */
143
	public function fetchByField($name, $value) {
144
		return $this->fetch([$name . ' = ?' => $value]);
145
	}
146
147
	/**
148
	 * Busca o objeto
149
	 * @param string[] $filter Array de filtros
150
	 * @param string $option [Order by, Limit, etc]
151
	 */
152
	public function fetch($filter, $option = '') {
153
		if (!is_array($filter)):
154
			throw new \Exception("Filter: '{$filter}' must be a array");
155
		endif;
156
		$sql = $sql = $this->selectSQL() . ' ' . $this->whereSQL($filter) . ' ' . $option;
157
		$result = [];
158
		if ($this->pdo) {
159
			$stmt = $this->pdo->prepare($sql);
160
			$stmt->execute(array_values($filter));
161
162
			$result = $stmt->fetch();
163
		}
164
		return $this->mapObject($result);
165
	}
166
167
	/**
168
	 * Retorna todos os registros
169
	 *
170
	 * <code>
171
	 * $dao->fetchAll( ['id = ?' => 10]);
172
	 * </code>
173
	 * @param string[] $filter Array de filtros
174
	 * @param string $option [Order by, Limit, etc]
175
	 */
176
	public function fetchAll($filter = [], $option = '') {
177
		$array = [];
178
		if (!is_array($filter)):
179
			throw new \Exception("Filter: '{$filter}' must be a array");
180
		endif;
181
182
		$sql = $this->selectSQL($this->selectCollumns) . ' ' . $this->whereSQL($filter) . ' ' . $option;
183 View Code Duplication
		if ($this->pdo) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
184
			$stmt = $this->pdo->prepare($sql);
185
			$stmt->execute(array_values($filter));
186
187
			$results = $stmt->fetchAll();
188
			foreach ($results as $result):
189
				$array[] = $this->mapObject($result);
190
			endforeach;
191
		}
192
		return $array;
193
	}
194
195
	/**
196
	 * Retorna comando SELECT
197
	 * @param string $selectCollumns
198
	 * @return string
199
	 * @example "SELECT * FROM user"
200
	 */
201
	protected function selectSQL($selectCollumns = ['*']) {
202
		return 'SELECT ' . implode(', ', $selectCollumns) . ' FROM ' . static::TABLE;
203
	}
204
205
	/**
206
	 * Retorna comando WHERE
207
	 * @param string[] $filter
208
	 * @return string
209
	 */
210
	private function whereSQL(&$filter) {
211
		$keys = array_keys($filter);
212
		return ($keys) ? 'WHERE ' . implode(' AND ', $keys) : '';
213
	}
214
215
	/**
216
	 * Retorna o total de registros
217
	 * @param string[] $filter Array de filtros
218
	 * @return int
219
	 */
220
	public function numRows($filter = []) {
221
		$total = 0;
222
		if (!is_array($filter)):
223
			throw new \Exception("Filter: '{$filter}' must be a array");
224
		endif;
225
226
		$sql = 'SELECT count(*) as total FROM ' . static::TABLE . ' ' . $this->whereSQL($filter);
227 View Code Duplication
		if ($this->pdo) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
228
			$stmt = $this->pdo->prepare($sql);
229
			$stmt->execute(array_values($filter));
230
231
			$result = $stmt->fetch();
232
			$total = $result['total'];
233
		}
234
		return $total;
235
	}
236
237
	/**
238
	 * Retorna True se objeto existir
239
	 * @return boolean
240
	 */
241
	protected function objExists() {
242
		return ($this->obj->getId() > 0);
243
	}
244
245
	/** Define como Página 404 se o objeto não existir */
246
	public function validateObject() {
247
		if (!$this->objExists()) {
248
			Application::app()->pageNotFound();
249
		}
250
	}
251
252
}
253