|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Ubiquity\orm; |
|
4
|
|
|
|
|
5
|
|
|
use Ubiquity\db\Database; |
|
6
|
|
|
use Ubiquity\log\Logger; |
|
7
|
|
|
use Ubiquity\orm\parser\ManyToManyParser; |
|
8
|
|
|
use Ubiquity\db\SqlUtils; |
|
9
|
|
|
use Ubiquity\orm\parser\Reflexion; |
|
10
|
|
|
use Ubiquity\orm\traits\DAOUpdatesTrait; |
|
11
|
|
|
use Ubiquity\orm\traits\DAORelationsTrait; |
|
12
|
|
|
use Ubiquity\orm\parser\ConditionParser; |
|
13
|
|
|
use Ubiquity\orm\traits\DAOUQueries; |
|
14
|
|
|
use Ubiquity\orm\traits\DAOCoreTrait; |
|
15
|
|
|
|
|
16
|
|
|
/** |
|
17
|
|
|
* Gateway class between database and object model |
|
18
|
|
|
* @author jc |
|
19
|
|
|
* @version 1.1.1 |
|
20
|
|
|
* @package orm |
|
21
|
|
|
*/ |
|
22
|
|
|
class DAO { |
|
23
|
|
|
use DAOCoreTrait,DAOUpdatesTrait,DAORelationsTrait,DAOUQueries; |
|
24
|
|
|
|
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* @var Database |
|
28
|
|
|
*/ |
|
29
|
|
|
public static $db; |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* Loads member associated with $instance by a ManyToOne relationship |
|
33
|
|
|
* @param object $instance |
|
34
|
|
|
* @param string $member |
|
35
|
|
|
* @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"] |
|
36
|
|
|
* @param boolean $useCache |
|
37
|
|
|
*/ |
|
38
|
|
|
public static function getManyToOne($instance, $member, $included=false,$useCache=NULL) { |
|
39
|
|
|
$fieldAnnot=OrmUtils::getMemberJoinColumns($instance, $member); |
|
40
|
|
|
if($fieldAnnot!==null){ |
|
41
|
|
|
$annotationArray=$fieldAnnot[1]; |
|
42
|
|
|
$member=$annotationArray["member"]; |
|
43
|
|
|
$value=Reflexion::getMemberValue($instance, $member); |
|
44
|
|
|
$key=OrmUtils::getFirstKey($annotationArray["className"]); |
|
45
|
|
|
$kv=array ($key => $value ); |
|
46
|
|
|
$obj=self::getOne($annotationArray["className"], $kv, $included, $useCache); |
|
|
|
|
|
|
47
|
|
|
if ($obj !== null) { |
|
48
|
|
|
Logger::info("DAO", "Loading the member " . $member . " for the object " . \get_class($instance),"getManyToOne"); |
|
49
|
|
|
$accesseur="set" . ucfirst($member); |
|
50
|
|
|
if (method_exists($instance, $accesseur)) { |
|
51
|
|
|
$instance->$accesseur($obj); |
|
52
|
|
|
$instance->_rest[$member]=$obj->_rest; |
|
53
|
|
|
return $obj; |
|
54
|
|
|
} |
|
55
|
|
|
} |
|
56
|
|
|
} |
|
57
|
|
|
} |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* Assign / load the child records in the $member member of $instance. |
|
61
|
|
|
* @param object $instance |
|
62
|
|
|
* @param string $member Member on which a oneToMany annotation must be present |
|
63
|
|
|
* @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"] |
|
64
|
|
|
* @param boolean $useCache |
|
65
|
|
|
* @param array $annot used internally |
|
66
|
|
|
*/ |
|
67
|
|
|
public static function getOneToMany($instance, $member, $included=true,$useCache=NULL, $annot=null) { |
|
68
|
|
|
$ret=array (); |
|
69
|
|
|
$class=get_class($instance); |
|
70
|
|
|
if (!isset($annot)) |
|
71
|
|
|
$annot=OrmUtils::getAnnotationInfoMember($class, "#oneToMany", $member); |
|
72
|
|
|
if ($annot !== false) { |
|
73
|
|
|
$fkAnnot=OrmUtils::getAnnotationInfoMember($annot["className"], "#joinColumn", $annot["mappedBy"]); |
|
74
|
|
|
if ($fkAnnot !== false) { |
|
75
|
|
|
$fkv=OrmUtils::getFirstKeyValue($instance); |
|
76
|
|
|
$ret=self::_getAll($annot["className"], ConditionParser::simple($fkAnnot["name"] . "= ?",$fkv), $included, $useCache); |
|
77
|
|
|
self::setToMember($member, $instance, $ret, $class, "getOneToMany"); |
|
78
|
|
|
} |
|
79
|
|
|
} |
|
80
|
|
|
return $ret; |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
/** |
|
84
|
|
|
* @param object $instance |
|
85
|
|
|
* @param string $member |
|
86
|
|
|
* @param array $array |
|
87
|
|
|
* @param string $mappedBy |
|
88
|
|
|
*/ |
|
89
|
|
|
public static function affectsOneToManyFromArray($instance, $member, $array=null, $mappedBy=null) { |
|
90
|
|
|
$ret=array (); |
|
91
|
|
|
$class=get_class($instance); |
|
92
|
|
|
if (!isset($mappedBy)){ |
|
93
|
|
|
$annot=OrmUtils::getAnnotationInfoMember($class, "#oneToMany", $member); |
|
94
|
|
|
$mappedBy=$annot["mappedBy"]; |
|
95
|
|
|
} |
|
96
|
|
|
if ($mappedBy !== false) { |
|
97
|
|
|
$fkv=OrmUtils::getFirstKeyValue($instance); |
|
98
|
|
|
self::_getOneToManyFromArray($ret, $array, $fkv, $mappedBy); |
|
99
|
|
|
self::setToMember($member, $instance, $ret, $class, "getOneToMany"); |
|
100
|
|
|
} |
|
101
|
|
|
return $ret; |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
/** |
|
105
|
|
|
* Assigns / loads the child records in the $member member of $instance. |
|
106
|
|
|
* If $ array is null, the records are loaded from the database |
|
107
|
|
|
* @param object $instance |
|
108
|
|
|
* @param string $member Member on which a ManyToMany annotation must be present |
|
109
|
|
|
* @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"] |
|
110
|
|
|
* @param array $array optional parameter containing the list of possible child records |
|
111
|
|
|
* @param boolean $useCache |
|
112
|
|
|
*/ |
|
113
|
|
|
public static function getManyToMany($instance, $member,$included=false,$array=null,$useCache=NULL){ |
|
114
|
|
|
$ret=[]; |
|
115
|
|
|
$class=get_class($instance); |
|
116
|
|
|
$parser=new ManyToManyParser($instance, $member); |
|
117
|
|
|
if ($parser->init()) { |
|
118
|
|
|
if (is_null($array)) { |
|
119
|
|
|
$accessor="get" . ucfirst($parser->getMyPk()); |
|
120
|
|
|
$condition=" INNER JOIN `" . $parser->getJoinTable() . "` on `".$parser->getJoinTable()."`.`".$parser->getFkField()."`=`".$parser->getTargetEntityTable()."`.`".$parser->getPk()."` WHERE `".$parser->getJoinTable()."`.`". $parser->getMyFkField() . "`= ?"; |
|
121
|
|
|
$ret=self::_getAll($parser->getTargetEntityClass(),ConditionParser::simple($condition, $instance->$accessor()),$included,$useCache); |
|
122
|
|
|
}else{ |
|
123
|
|
|
$ret=self::getManyToManyFromArray($instance, $array, $class, $parser); |
|
124
|
|
|
} |
|
125
|
|
|
self::setToMember($member, $instance, $ret, $class, "getManyToMany"); |
|
126
|
|
|
} |
|
127
|
|
|
return $ret; |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
/** |
|
131
|
|
|
* @param object $instance |
|
132
|
|
|
* @param array $array |
|
133
|
|
|
* @param boolean $useCache |
|
134
|
|
|
*/ |
|
135
|
|
|
public static function affectsManyToManys($instance,$array=NULL,$useCache=NULL){ |
|
136
|
|
|
$metaDatas=OrmUtils::getModelMetadata(\get_class($instance)); |
|
137
|
|
|
$manyToManyFields=$metaDatas["#manyToMany"]; |
|
138
|
|
|
if(\sizeof($manyToManyFields)>0){ |
|
139
|
|
|
foreach ($manyToManyFields as $member){ |
|
140
|
|
|
self::getManyToMany($instance, $member,false,$array,$useCache); |
|
141
|
|
|
} |
|
142
|
|
|
} |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* Returns an array of $className objects from the database |
|
147
|
|
|
* @param string $className class name of the model to load |
|
148
|
|
|
* @param string $condition Part following the WHERE of an SQL statement |
|
149
|
|
|
* @param boolean|array $included if true, loads associate members with associations, if array, example : ["client.*","commands"] |
|
150
|
|
|
* @param array|null $parameters |
|
151
|
|
|
* @param boolean $useCache use the active cache if true |
|
152
|
|
|
* @return array |
|
153
|
|
|
*/ |
|
154
|
|
|
public static function getAll($className, $condition='', $included=true,$parameters=null,$useCache=NULL) { |
|
155
|
|
|
return self::_getAll($className, new ConditionParser($condition,null,$parameters),$included,$useCache); |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
public static function paginate($className,$page=1,$rowsPerPage=20,$condition=null,$included=true){ |
|
159
|
|
|
if(!isset($condition)){ |
|
160
|
|
|
$condition="1=1"; |
|
161
|
|
|
} |
|
162
|
|
|
return self::getAll($className,$condition." LIMIT ".$rowsPerPage." OFFSET ".(($page-1)*$rowsPerPage),$included); |
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
public static function getRownum($className,$ids){ |
|
166
|
|
|
$tableName=OrmUtils::getTableName($className); |
|
167
|
|
|
self::parseKey($ids,$className); |
|
168
|
|
|
$condition=SqlUtils::getCondition($ids,$className); |
|
169
|
|
|
$keys=implode(",", OrmUtils::getKeyFields($className)); |
|
170
|
|
|
return self::$db->queryColumn("SELECT num FROM (SELECT *, @rownum:=@rownum + 1 AS num FROM `{$tableName}`, (SELECT @rownum:=0) r ORDER BY {$keys}) d WHERE ".$condition); |
|
171
|
|
|
} |
|
172
|
|
|
|
|
173
|
|
|
/** |
|
174
|
|
|
* Returns the number of objects of $className from the database respecting the condition possibly passed as parameter |
|
175
|
|
|
* @param string $className complete classname of the model to load |
|
176
|
|
|
* @param string $condition Part following the WHERE of an SQL statement |
|
177
|
|
|
* @param array|null $parameters The query parameters |
|
178
|
|
|
* @return int count of objects |
|
179
|
|
|
*/ |
|
180
|
|
|
public static function count($className, $condition='',$parameters=null) { |
|
181
|
|
|
$tableName=OrmUtils::getTableName($className); |
|
182
|
|
|
if ($condition != '') |
|
183
|
|
|
$condition=" WHERE " . $condition; |
|
184
|
|
|
return self::$db->prepareAndFetchColumn("SELECT COUNT(*) FROM `" . $tableName ."`". $condition,$parameters); |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
/** |
|
188
|
|
|
* Returns an instance of $className from the database, from $keyvalues values of the primary key |
|
189
|
|
|
* @param String $className complete classname of the model to load |
|
190
|
|
|
* @param Array|string $keyValues primary key values or condition |
|
191
|
|
|
* @param boolean|array $included if true, charges associate members with association |
|
192
|
|
|
* @param array|null $parameters the request parameters |
|
193
|
|
|
* @param boolean $useCache use cache if true |
|
194
|
|
|
* @return object the instance loaded or null if not found |
|
195
|
|
|
*/ |
|
196
|
|
|
public static function getOne($className, $keyValues, $included=true,$parameters=null,$useCache=NULL) { |
|
197
|
|
|
$conditionParser=new ConditionParser(); |
|
198
|
|
|
if(!isset($parameters)){ |
|
199
|
|
|
$conditionParser->addKeyValues($keyValues,$className); |
|
200
|
|
|
}else{ |
|
201
|
|
|
$conditionParser->setCondition($keyValues); |
|
|
|
|
|
|
202
|
|
|
$conditionParser->setParams($parameters); |
|
203
|
|
|
} |
|
204
|
|
|
return self::_getOne($className, $conditionParser, $included, $useCache); |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
|
|
208
|
|
|
/** |
|
209
|
|
|
* Establishes the connection to the database using the past parameters |
|
210
|
|
|
* @param string $dbType |
|
211
|
|
|
* @param string $dbName |
|
212
|
|
|
* @param string $serverName |
|
213
|
|
|
* @param string $port |
|
214
|
|
|
* @param string $user |
|
215
|
|
|
* @param string $password |
|
216
|
|
|
* @param array $options |
|
217
|
|
|
* @param boolean $cache |
|
218
|
|
|
*/ |
|
219
|
|
|
public static function connect($dbType,$dbName, $serverName="127.0.0.1", $port="3306", $user="root", $password="", $options=[],$cache=false) { |
|
220
|
|
|
self::$db=new Database($dbType,$dbName, $serverName, $port, $user, $password, $options,$cache); |
|
221
|
|
|
try { |
|
222
|
|
|
self::$db->connect(); |
|
223
|
|
|
} catch (\Exception $e) { |
|
224
|
|
|
Logger::error("DAO", $e->getMessage()); |
|
225
|
|
|
throw $e; |
|
226
|
|
|
} |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* Returns true if the connection to the database is established |
|
231
|
|
|
* @return boolean |
|
232
|
|
|
*/ |
|
233
|
|
|
public static function isConnected(){ |
|
234
|
|
|
return self::$db!==null && (self::$db instanceof Database) && self::$db->isConnected(); |
|
235
|
|
|
} |
|
236
|
|
|
} |
|
237
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.