1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by PhpStorm. |
4
|
|
|
* User: VITALYIEGOROV |
5
|
|
|
* Date: 30.11.15 |
6
|
|
|
* Time: 16:38 |
7
|
|
|
*/ |
8
|
|
|
namespace samsonframework\orm; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Database entity manager. |
12
|
|
|
* @package samsonframework\orm |
13
|
|
|
*/ |
14
|
|
|
class Manager extends Database implements ManagerInterface |
15
|
|
|
{ |
16
|
|
|
/** @var string Entity identifier */ |
17
|
|
|
protected $entityName; |
18
|
|
|
|
19
|
|
|
/** @var string Entity primary field name */ |
20
|
|
|
protected $primaryFieldName; |
21
|
|
|
|
22
|
|
|
/** @var array Collection of entity field names and their types */ |
23
|
|
|
protected $attributes = array(); |
24
|
|
|
|
25
|
|
|
/** @var \PDO Database driver */ |
26
|
|
|
protected $driver; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Manager constructor. |
30
|
|
|
* |
31
|
|
|
* @param string $entityName Entity name |
32
|
|
|
* @param array $attributes Key-value collection with field name => type |
33
|
|
|
* @param \PDO $driver database low-level driver |
34
|
|
|
*/ |
35
|
|
|
public function __construct($entityName, $attributes, $driver) |
36
|
|
|
{ |
37
|
|
|
$this->entityName = $entityName; |
38
|
|
|
$this->attributes = $attributes; |
39
|
|
|
$this->driver = $driver; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
View Code Duplication |
public function execute($sql) |
|
|
|
|
43
|
|
|
{ |
44
|
|
|
$result = array(); |
45
|
|
|
|
46
|
|
|
if (isset($this->driver)) { |
47
|
|
|
// Store timestamp |
48
|
|
|
$tsLast = microtime(true); |
49
|
|
|
|
50
|
|
|
try { |
51
|
|
|
// Perform database query |
52
|
|
|
$result = $this->driver->prepare($sql)->execute(); |
53
|
|
|
} catch (\PDOException $e) { |
54
|
|
|
echo("\n" . $sql . '-' . $e->getMessage()); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
// Store queries count |
58
|
|
|
$this->count++; |
59
|
|
|
|
60
|
|
|
// Count elapsed time |
61
|
|
|
$this->elapsed += microtime(true) - $tsLast; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
return $result; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Get query for database entity to work with. |
69
|
|
|
* |
70
|
|
|
* @return QueryInterface Query for building database request |
71
|
|
|
*/ |
72
|
|
|
public function query() |
73
|
|
|
{ |
74
|
|
|
return new Query($this->entityName, $this); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Get new entity instance. |
79
|
|
|
* |
80
|
|
|
* @return RecordInterface New database manager entity instance |
81
|
|
|
*/ |
82
|
|
|
public function instance() |
83
|
|
|
{ |
84
|
|
|
return new $this->entityName($this); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Create new database entity record. |
89
|
|
|
* @param RecordInterface $entity Entity record for creation |
90
|
|
|
* @return RecordInterface Created database entity record with new primary identifier |
91
|
|
|
*/ |
92
|
|
|
public function create(RecordInterface $entity) |
93
|
|
|
{ |
94
|
|
|
$fields = $this->getFields($entity); |
95
|
|
|
|
96
|
|
|
$this->execute('INSERT INTO `' . $this->entityName . '` (`' |
97
|
|
|
. implode('`,`', array_keys($fields)) . '`) VALUES (' . implode(',', $fields) . ')' |
98
|
|
|
); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Read database entity records from QueryInterface. |
103
|
|
|
* |
104
|
|
|
* @param QueryInterface $query For retrieving records |
105
|
|
|
* @return RecordInterface[] Collection of read database entity records |
106
|
|
|
*/ |
107
|
|
|
public function read(QueryInterface $query) |
108
|
|
|
{ |
109
|
|
|
// TODO: Implement read() method. |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Update database entity record. |
114
|
|
|
* |
115
|
|
|
* @param RecordInterface $entity Entity record for updating |
116
|
|
|
*/ |
117
|
|
|
public function update(RecordInterface $entity) |
118
|
|
|
{ |
119
|
|
|
// Generate entity fields update command |
120
|
|
|
$fields = array(); |
121
|
|
|
foreach ($this->getFields($entity) as $fieldName => $fieldValue) { |
122
|
|
|
$fields[] = '`'.$this->entityName.'`.`'.$fieldName.'` = "'.$fieldValue.'"'; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
$this->execute('UPDATE `' . $this->entityName . '` SET ' |
126
|
|
|
. implode(',', $fields) |
127
|
|
|
. ' WHERE `' . $this->entityName . '`.`' . $this->primaryFieldName . '`="' |
128
|
|
|
. $this->quote($entity->id) . '"'); |
|
|
|
|
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
/** |
132
|
|
|
* Delete database record from database. |
133
|
|
|
* |
134
|
|
|
* @param RecordInterface $entity Entity record for removing |
135
|
|
|
*/ |
136
|
|
|
public function delete(RecordInterface $entity) |
137
|
|
|
{ |
138
|
|
|
$this->execute('DELETE FROM `' . $this->entityName . '` WHERE ' |
139
|
|
|
. $this->primaryFieldName . ' = "' . $this->quote($entity->id) . '"' |
|
|
|
|
140
|
|
|
); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Convert RecordInterface instance to collection of its field name => value. |
145
|
|
|
* |
146
|
|
|
* @param RecordInterface $object Database record instance to convert |
147
|
|
|
* @return array Collection of key => value with SQL fields statements |
148
|
|
|
*/ |
149
|
|
|
protected function &getFields(RecordInterface &$object = null) |
150
|
|
|
{ |
151
|
|
|
$collection = array(); |
152
|
|
|
foreach ($this->attributes as $attribute => $type) { |
153
|
|
|
if ($type == 'timestamp') { |
154
|
|
|
continue; |
155
|
|
|
} elseif ($this->primaryFieldName == $attribute) { |
156
|
|
|
continue; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
$collection[$attribute] = $this->quote($object->$attribute); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
return $collection; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Quote variable for security reasons. |
167
|
|
|
* |
168
|
|
|
* @param string $value |
169
|
|
|
* @return string Quoted value |
170
|
|
|
*/ |
171
|
|
|
protected function quote($value) |
172
|
|
|
{ |
173
|
|
|
return $this->driver->quote($value); |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
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.