Completed
Push — master ( 6e0d04...74be15 )
by Wanderson
02:31
created

DAO::fetch()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 3
Metric Value
c 3
b 0
f 3
dl 0
loc 11
rs 9.4285
nc 2
cc 2
eloc 9
nop 2
1
<?php
2
3
namespace Win\DesignPattern;
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 $selectedCollumns;
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
		$this->selectedCollumns = '*';
34
	}
35
36
	/**
37
	 * Define uma conexão manualmente
38
	 * @param \PDO $pdo
39
	 */
40
	public function setPDO($pdo) {
41
		$this->pdo = $pdo;
42
	}
43
44
	/**
45
	 * Define quais colunas serão consultadas nos comandos SELECT
46
	 * @param string $collumns
47
	 */
48
	public function selectedCollumns($collumns) {
49
		$this->selectedCollumns = $collumns;
50
	}
51
52
	/**
53
	 * Salva o registro
54
	 * @param object $obj
55
	 */
56
	public function save($obj) {
57
		$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...
58
		if (!$this->objExists()) {
59
			$this->insert();
60
			$this->obj->setId($this->pdo->lastInsertId());
61
		} else {
62
			$this->update();
63
		}
64
	}
65
66
	/** Insere o registro */
67
	protected function insert() {
68
		$mapRow = $this->mapRow($this->obj);
69
		$keys = array_keys($mapRow);
70
		$values = array_values($mapRow);
71
		$params = str_split(str_repeat('?', count($keys)));
72
73
		$sql = 'INSERT INTO ' . static::TABLE . ' (' . implode(',', $keys) . ') VALUES (' . implode(', ', $params) . ') ';
74
		$stmt = $this->pdo->prepare($sql);
75
		$stmt->execute($values);
76
	}
77
78
	/** Atualiza o registro */
79
	protected function update() {
80
		$mapRow = $this->mapRow($this->obj);
81
		$keys = array_keys($mapRow);
82
		$values = array_values($mapRow);
83
		$params = [];
84
		foreach ($keys as $key):
85
			$params[] = $key . ' = ?';
86
		endforeach;
87
		$values[] = $this->obj->getId();
88
89
		$sql = 'UPDATE ' . static::TABLE . ' SET ' . implode(', ', $params) . ' WHERE id = ? ';
90
		$stmt = $this->pdo->prepare($sql);
91
		$stmt->execute($values);
92
	}
93
94
	/**
95
	 * Exclui o registro
96
	 * @param object $obj
97
	 */
98
	public function delete($obj) {
99
		$this->deleteById($obj->getId());
100
	}
101
102
	/**
103
	 * Exclui o registro por id
104
	 * @param int $id
105
	 */
106
	public function deleteById($id) {
107
		$sql = 'DELETE FROM ' . static::TABLE . ' WHERE id = :id';
108
		$stmt = $this->pdo->prepare($sql);
109
		$stmt->bindValue(':id', $id);
110
		$stmt->execute();
111
	}
112
113
	/**
114
	 * Busca o objeto pelo id
115
	 * @param int $id
116
	 */
117
	public function fetchById($id) {
118
		return $this->fetchByField('id', $id);
119
	}
120
121
	/**
122
	 * Busca o objeto por um campo/atributo específico
123
	 * @param string $name Nome do atributo
124
	 * @param mixed $value Valor do atributo
125
	 */
126
	public function fetchByField($name, $value) {
127
		return $this->fetch([$name . ' = ?' => $value]);
128
	}
129
130
	/**
131
	 * Busca o objeto
132
	 * @param string[] $filter Array de filtros
133
	 * @param string $option [Order by, Limit, etc]
134
	 */
135
	public function fetch($filter, $option = '') {
136
		if (!is_array($filter)):
137
			throw new \Exception("Filter: '{$filter}' must be a array");
138
		endif;
139
		$sql = $sql = $this->selectSQL() . ' ' . $this->whereSQL($filter) . ' ' . $option;
140
		$stmt = $this->pdo->prepare($sql);
141
		$stmt->execute(array_values($filter));
142
143
		$result = $stmt->fetch();
144
		return $this->mapObject($result);
145
	}
146
147
	/**
148
	 * Retorna todos os registros
149
	 *
150
	 * <code>
151
	 * $dao->fetchAll( ['id = ?' => 10]);
152
	 * </code>
153
	 * @param string[] $filter Array de filtros
154
	 * @param string $option [Order by, Limit, etc]
155
	 */
156
	public function fetchAll($filter = [], $option = '') {
157
		if (!is_array($filter)):
158
			throw new \Exception("Filter: '{$filter}' must be a array");
159
		endif;
160
161
		$sql = $this->selectSQL() . ' ' . $this->whereSQL($filter) . ' ' . $option;
162
		$stmt = $this->pdo->prepare($sql);
163
		$stmt->execute(array_values($filter));
164
165
		$results = $stmt->fetchAll();
166
		$array = [];
167
		foreach ($results as $result):
168
			$array[] = $this->mapObject($result);
169
		endforeach;
170
		return $array;
171
	}
172
173
	/**
174
	 * Retorna comando SELECT
175
	 * @return string
176
	 * @example "SELECT * FROM user"
177
	 */
178
	protected function selectSQL() {
179
		return 'SELECT ' . $this->selectedCollumns . ' FROM ' . static::TABLE;
180
	}
181
182
	/**
183
	 * Retorna comando WHERE
184
	 * @param string[] $filter
185
	 * @return string
186
	 */
187
	private function whereSQL(&$filter) {
188
		$keys = array_keys($filter);
189
		return ($keys) ? 'WHERE ' . implode(' AND ', $keys) : '';
190
	}
191
192
	/**
193
	 * Retorna True se objeto existir
194
	 * @return boolean
195
	 */
196
	protected function objExists() {
197
		return ($this->obj->getId() > 0);
198
	}
199
200
	/** Define como Página 404 se o objeto não existir */
201
	public function validateObject() {
202
		if (!$this->objExists()) {
203
			Application::app()->pageNotFound();
204
		}
205
	}
206
207
}
208