|
1
|
|
|
<?php |
|
2
|
|
|
namespace micro\orm; |
|
3
|
|
|
use micro\db\SqlUtils; |
|
4
|
|
|
use micro\db\Database; |
|
5
|
|
|
use micro\log\Logger; |
|
6
|
|
|
use micro\orm\parser\ManyToManyParser; |
|
7
|
|
|
use micro\orm\parser\Reflexion; |
|
8
|
|
|
|
|
9
|
|
|
/** |
|
10
|
|
|
* Classe passerelle entre base de données et modèle objet |
|
11
|
|
|
* @author jc |
|
12
|
|
|
* @version 1.0.0.5 |
|
13
|
|
|
* @package orm |
|
14
|
|
|
*/ |
|
15
|
|
|
class DAO { |
|
16
|
|
|
public static $db; |
|
17
|
|
|
|
|
18
|
|
|
private static function getCondition($keyValues){ |
|
19
|
|
|
$retArray=array(); |
|
20
|
|
|
if(is_array($keyValues)){ |
|
21
|
|
|
foreach ($keyValues as $key=>$value){ |
|
22
|
|
|
$retArray[]="`".$key."` = '".$value."'"; |
|
23
|
|
|
} |
|
24
|
|
|
$condition=implode(" AND ", $retArray); |
|
25
|
|
|
}else |
|
26
|
|
|
$condition=$keyValues; |
|
27
|
|
|
return $condition; |
|
28
|
|
|
} |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* Charge les membres associés à $instance par une relation de type ManyToOne |
|
32
|
|
|
* @param object $instance |
|
33
|
|
|
* @param mixed $value |
|
34
|
|
|
* @param array $annotationArray |
|
35
|
|
|
* @param boolean $useCache |
|
36
|
|
|
*/ |
|
37
|
|
|
private static function getOneManyToOne($instance,$value,$annotationArray,$useCache=NULL){ |
|
38
|
|
|
$class=get_class($instance); |
|
39
|
|
|
$member=$annotationArray["member"]; |
|
40
|
|
|
$key=OrmUtils::getFirstKey($annotationArray["className"]); |
|
41
|
|
|
$kv=array($key=>$value); |
|
42
|
|
|
$obj=self::getOne($annotationArray["className"], $kv,false,false,$useCache); |
|
43
|
|
|
if($obj!==null){ |
|
44
|
|
|
Logger::log("getOneManyToOne", "Chargement de ".$member." pour l'objet ".$class); |
|
45
|
|
|
$accesseur="set".ucfirst($member); |
|
46
|
|
|
if(method_exists($instance,$accesseur)){ |
|
47
|
|
|
$instance->$accesseur($obj); |
|
48
|
|
|
return; |
|
49
|
|
|
} |
|
50
|
|
|
} |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* Affecte/charge les enregistrements fils dans le membre $member de $instance. |
|
55
|
|
|
* Si $array est null, les fils sont chargés depuis la base de données |
|
56
|
|
|
* @param object $instance |
|
57
|
|
|
* @param string $member Membre sur lequel doit être présent une annotation OneToMany |
|
58
|
|
|
* @param array $array paramètre facultatif contenant la liste des fils possibles |
|
59
|
|
|
* @param boolean $useCache |
|
60
|
|
|
* @param array $annot used internally |
|
61
|
|
|
*/ |
|
62
|
|
|
public static function getOneToMany($instance,$member,$array=null,$useCache=NULL,$annot=null){ |
|
63
|
|
|
$ret=array(); |
|
64
|
|
|
$class=get_class($instance); |
|
65
|
|
|
if(!isset($annot)) |
|
66
|
|
|
$annot=OrmUtils::getAnnotationInfoMember($class,"#oneToMany", $member); |
|
67
|
|
|
if($annot!==false){ |
|
68
|
|
|
$fkAnnot=OrmUtils::getAnnotationInfoMember($annot["className"], "#joinColumn",$annot["mappedBy"]); |
|
69
|
|
|
if($fkAnnot!==false){ |
|
70
|
|
|
$fkv=OrmUtils::getFirstKeyValue($instance); |
|
71
|
|
|
if(is_null($array)){ |
|
72
|
|
|
$ret=self::getAll($annot["className"],$fkAnnot["name"]."='".$fkv."'",true,false,$useCache); |
|
73
|
|
|
}else{ |
|
74
|
|
|
self::getOneToManyFromArray($ret, $array, $fkv, $annot); |
|
75
|
|
|
} |
|
76
|
|
|
self::setToMember($member, $instance, $ret, $class, "getOneToMany"); |
|
77
|
|
|
} |
|
78
|
|
|
} |
|
79
|
|
|
return $ret; |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
private static function getOneToManyFromArray(&$ret,$array,$fkv,$annot){ |
|
83
|
|
|
$elementAccessor="get".ucfirst($annot["mappedBy"]); |
|
84
|
|
|
foreach ($array as $element){ |
|
85
|
|
|
$elementRef=$element->$elementAccessor(); |
|
86
|
|
|
if(!is_null($elementRef)){ |
|
87
|
|
|
$idElementRef=OrmUtils::getFirstKeyValue($elementRef); |
|
88
|
|
|
if($idElementRef==$fkv) |
|
89
|
|
|
$ret[]=$element; |
|
90
|
|
|
} |
|
91
|
|
|
} |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
private static function setToMember($member,$instance,$value,$class,$part){ |
|
95
|
|
|
$accessor="set".ucfirst($member); |
|
96
|
|
|
if(method_exists($instance,$accessor)){ |
|
97
|
|
|
Logger::log($part, "Affectation de ".$member." pour l'objet ".$class); |
|
98
|
|
|
$instance->$accessor($value); |
|
99
|
|
|
}else{ |
|
100
|
|
|
Logger::warn($part, "L'accesseur ".$accessor." est manquant pour ".$class); |
|
101
|
|
|
} |
|
102
|
|
|
} |
|
103
|
|
|
/** |
|
104
|
|
|
* @param object $instance |
|
105
|
|
|
* @param ManyToManyParser $parser |
|
106
|
|
|
* @return PDOStatement |
|
107
|
|
|
*/ |
|
108
|
|
|
private static function getSQLForJoinTable($instance,ManyToManyParser $parser){ |
|
109
|
|
|
$accessor="get".ucfirst($parser->getPk()); |
|
110
|
|
|
$sql="SELECT * FROM `".$parser->getJoinTable()."` WHERE `".$parser->getMyFkField()."`='".$instance->$accessor()."'"; |
|
111
|
|
|
Logger::log("ManyToMany", "Exécution de ".$sql); |
|
112
|
|
|
return self::$db->query($sql); |
|
113
|
|
|
} |
|
114
|
|
|
/** |
|
115
|
|
|
* Affecte/charge les enregistrements fils dans le membre $member de $instance. |
|
116
|
|
|
* Si $array est null, les fils sont chargés depuis la base de données |
|
117
|
|
|
* @param object $instance |
|
118
|
|
|
* @param string $member Membre sur lequel doit être présent une annotation ManyToMany |
|
119
|
|
|
* @param array $array paramètre facultatif contenant la liste des fils possibles |
|
120
|
|
|
* @param boolean $useCache |
|
121
|
|
|
*/ |
|
122
|
|
|
public static function getManyToMany($instance,$member,$array=null,$useCache=NULL){ |
|
123
|
|
|
$ret=array(); |
|
124
|
|
|
$class=get_class($instance); |
|
125
|
|
|
$parser=new ManyToManyParser($instance, $member); |
|
126
|
|
|
if($parser->init()){ |
|
127
|
|
|
if(is_null($array)){ |
|
128
|
|
|
$joinTableCursor=self::getSQLForJoinTable($instance,$parser); |
|
129
|
|
|
foreach($joinTableCursor as $row){ |
|
130
|
|
|
$fkv=$row[$parser->getFkField()]; |
|
131
|
|
|
$tmp=self::getOne($parser->getTargetEntity(),"`".$parser->getPk()."`='".$fkv."'",false,false,$useCache); |
|
132
|
|
|
array_push($ret,$tmp); |
|
133
|
|
|
} |
|
134
|
|
|
} |
|
135
|
|
|
else{ |
|
136
|
|
|
self::getManyToManyFromArray($ret, $instance, $array, $class, $parser); |
|
137
|
|
|
} |
|
138
|
|
|
self::setToMember($member, $instance, $ret, $class, "getManyToMany"); |
|
139
|
|
|
} |
|
140
|
|
|
return $ret; |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
private static function getManyToManyFromArray(&$ret,$instance,$array,$class,$parser){ |
|
144
|
|
|
$continue=true; |
|
145
|
|
|
$accessorToMember="get".ucfirst($parser->getInversedBy()); |
|
146
|
|
|
$myPkAccessor="get".ucfirst($parser->getMyPk()); |
|
147
|
|
|
|
|
148
|
|
|
if(!method_exists($instance, $myPkAccessor)){ |
|
149
|
|
|
Logger::warn("ManyToMany", "L'accesseur au membre clé primaire ".$myPkAccessor." est manquant pour ".$class); |
|
150
|
|
|
} |
|
151
|
|
|
if(count($array)>0) |
|
152
|
|
|
$continue=method_exists($array[0], $accessorToMember); |
|
153
|
|
|
if($continue){ |
|
154
|
|
|
foreach($array as $targetEntityInstance){ |
|
155
|
|
|
$instances=$targetEntityInstance->$accessorToMember(); |
|
156
|
|
|
if(is_array($instances)){ |
|
157
|
|
|
foreach ($instances as $inst){ |
|
158
|
|
|
if($inst->$myPkAccessor()==$instance->$myPkAccessor()) |
|
159
|
|
|
array_push($ret, $targetEntityInstance); |
|
160
|
|
|
} |
|
161
|
|
|
} |
|
162
|
|
|
} |
|
163
|
|
|
}else{ |
|
164
|
|
|
Logger::warn("ManyToMany", "L'accesseur au membre ".$parser->getInversedBy()." est manquant pour ".$parser->getTargetEntity()); |
|
165
|
|
|
} |
|
166
|
|
|
} |
|
167
|
|
|
/** |
|
168
|
|
|
* Retourne un tableau d'objets de $className depuis la base de données |
|
169
|
|
|
* @param string $className nom de la classe du model à charger |
|
170
|
|
|
* @param string $condition Partie suivant le WHERE d'une instruction SQL |
|
171
|
|
|
* @param boolean $loadManyToOne |
|
172
|
|
|
* @param boolean $loadOneToMany |
|
173
|
|
|
* @param boolean $useCache |
|
174
|
|
|
* @return array |
|
175
|
|
|
*/ |
|
176
|
|
|
public static function getAll($className,$condition='',$loadManyToOne=true,$loadOneToMany=false,$useCache=NULL){ |
|
177
|
|
|
$objects=array(); |
|
178
|
|
|
$invertedJoinColumns=null; $oneToManyFields=null; |
|
179
|
|
|
$tableName=OrmUtils::getTableName($className); |
|
180
|
|
|
$metaDatas=OrmUtils::getModelMetadata($className); |
|
181
|
|
|
if($loadManyToOne && isset($metaDatas["#invertedJoinColumn"])) |
|
182
|
|
|
$invertedJoinColumns=$metaDatas["#invertedJoinColumn"]; |
|
183
|
|
|
if($loadOneToMany && isset($metaDatas["#oneToMany"])){ |
|
184
|
|
|
$oneToManyFields=$metaDatas["#oneToMany"]; |
|
185
|
|
|
} |
|
186
|
|
|
if($condition!='') |
|
187
|
|
|
$condition=" WHERE ".$condition; |
|
188
|
|
|
$query=self::$db->prepareAndExecute("SELECT * FROM ".$tableName.$condition,$useCache); |
|
189
|
|
|
Logger::log("getAll","SELECT * FROM ".$tableName.$condition); |
|
190
|
|
|
foreach ($query as $row){ |
|
191
|
|
|
$o=self::loadObjectFromRow($row, $className, $invertedJoinColumns, $oneToManyFields,$useCache); |
|
192
|
|
|
$objects[]=$o; |
|
193
|
|
|
} |
|
194
|
|
|
return $objects; |
|
195
|
|
|
} |
|
196
|
|
|
|
|
197
|
|
|
private static function loadObjectFromRow($row,$className,$invertedJoinColumns,$oneToManyFields,$useCache=NULL){ |
|
198
|
|
|
$o=new $className(); |
|
199
|
|
|
foreach ($row as $k=>$v){ |
|
200
|
|
|
$accesseur="set".ucfirst($k); |
|
201
|
|
|
if(method_exists($o,$accesseur)){ |
|
202
|
|
|
$o->$accesseur($v); |
|
203
|
|
|
} |
|
204
|
|
|
if(isset($invertedJoinColumns) && isset($invertedJoinColumns[$k])) { |
|
205
|
|
|
self::getOneManyToOne($o,$v, $invertedJoinColumns[$k],$useCache); |
|
206
|
|
|
} |
|
207
|
|
|
} |
|
208
|
|
|
if(isset($oneToManyFields)){ |
|
209
|
|
|
foreach ($oneToManyFields as $k=>$annot){ |
|
210
|
|
|
self::getOneToMany($o, $k,null,$useCache,$annot); |
|
211
|
|
|
} |
|
212
|
|
|
} |
|
213
|
|
|
return $o; |
|
214
|
|
|
} |
|
215
|
|
|
/** |
|
216
|
|
|
* Retourne le nombre d'objets de $className depuis la base de données respectant la condition éventuellement passée en paramètre |
|
217
|
|
|
* @param string $className nom de la classe du model à charger |
|
218
|
|
|
* @param string $condition Partie suivant le WHERE d'une instruction SQL |
|
219
|
|
|
*/ |
|
220
|
|
|
public static function count($className,$condition=''){ |
|
221
|
|
|
$tableName=OrmUtils::getTableName($className); |
|
222
|
|
|
if($condition!='') |
|
223
|
|
|
$condition=" WHERE ".$condition; |
|
224
|
|
|
return self::$db->query("SELECT COUNT(*) FROM ".$tableName.$condition)->fetchColumn(); |
|
225
|
|
|
} |
|
226
|
|
|
|
|
227
|
|
|
/** |
|
228
|
|
|
* Retourne une instance de $className depuis la base de données, à partir des valeurs $keyValues de la clé primaire |
|
229
|
|
|
* @param String $className nom de la classe du model à charger |
|
230
|
|
|
* @param Array|string $keyValues valeurs des clés primaires ou condition |
|
231
|
|
|
* @param boolean $useCache |
|
232
|
|
|
*/ |
|
233
|
|
|
public static function getOne($className,$keyValues,$loadManyToOne=true,$loadOneToMany=false,$useCache=NULL){ |
|
234
|
|
|
if(!is_array($keyValues)){ |
|
235
|
|
|
if(strrpos($keyValues,"=")===false){ |
|
236
|
|
|
$keyValues="`".OrmUtils::getFirstKey($className)."`='".$keyValues."'"; |
|
237
|
|
|
}elseif ($keyValues=="") |
|
238
|
|
|
$keyValues=""; |
|
239
|
|
|
} |
|
240
|
|
|
$condition=self::getCondition($keyValues); |
|
241
|
|
|
$retour=self::getAll($className,$condition,$loadManyToOne,$loadOneToMany,$useCache); |
|
242
|
|
|
if(sizeof($retour)<1) |
|
243
|
|
|
return null; |
|
244
|
|
|
else |
|
245
|
|
|
return $retour[0]; |
|
246
|
|
|
return $retour; |
|
|
|
|
|
|
247
|
|
|
|
|
248
|
|
|
} |
|
249
|
|
|
|
|
250
|
|
|
/** |
|
251
|
|
|
* Supprime $instance dans la base de données |
|
252
|
|
|
* @param Classe $instance instance à supprimer |
|
253
|
|
|
*/ |
|
254
|
|
|
public static function remove($instance){ |
|
255
|
|
|
$tableName=OrmUtils::getTableName(get_class($instance)); |
|
256
|
|
|
$keyAndValues=OrmUtils::getKeyFieldsAndValues($instance); |
|
257
|
|
|
$sql="DELETE FROM ".$tableName." WHERE ".SqlUtils::getWhere($keyAndValues); |
|
258
|
|
|
Logger::log("delete", $sql); |
|
259
|
|
|
$statement=self::$db->prepareStatement($sql); |
|
260
|
|
|
foreach ($keyAndValues as $key=>$value){ |
|
261
|
|
|
self::$db->bindValueFromStatement($statement,$key,$value); |
|
262
|
|
|
} |
|
263
|
|
|
return $statement->execute(); |
|
264
|
|
|
} |
|
265
|
|
|
|
|
266
|
|
|
/** |
|
267
|
|
|
* Insère $instance dans la base de données |
|
268
|
|
|
* @param object $instance instance à insérer |
|
269
|
|
|
* @param $insertMany si vrai, sauvegarde des instances reliées à $instance par un ManyToMany |
|
270
|
|
|
*/ |
|
271
|
|
|
public static function insert($instance,$insertMany=false){ |
|
272
|
|
|
$tableName=OrmUtils::getTableName(get_class($instance)); |
|
273
|
|
|
$keyAndValues=Reflexion::getPropertiesAndValues($instance); |
|
274
|
|
|
$keyAndValues=array_merge($keyAndValues, OrmUtils::getManyToOneMembersAndValues($instance)); |
|
275
|
|
|
$sql="INSERT INTO ".$tableName."(".SqlUtils::getInsertFields($keyAndValues).") VALUES(".SqlUtils::getInsertFieldsValues($keyAndValues).")"; |
|
276
|
|
|
Logger::log("insert", $sql); |
|
277
|
|
|
Logger::log("Key and values", json_encode($keyAndValues)); |
|
278
|
|
|
$statement=self::$db->prepareStatement($sql); |
|
279
|
|
|
foreach ($keyAndValues as $key=>$value){ |
|
280
|
|
|
self::$db->bindValueFromStatement($statement,$key,$value); |
|
281
|
|
|
} |
|
282
|
|
|
$result=$statement->execute(); |
|
283
|
|
|
if($result){ |
|
284
|
|
|
$accesseurId="set".ucfirst(OrmUtils::getFirstKey(get_class($instance))); |
|
285
|
|
|
$instance->$accesseurId(self::$db->lastInserId()); |
|
286
|
|
|
if($insertMany){ |
|
287
|
|
|
self::insertOrUpdateAllManyToMany($instance); |
|
288
|
|
|
} |
|
289
|
|
|
} |
|
290
|
|
|
return $result; |
|
291
|
|
|
} |
|
292
|
|
|
|
|
293
|
|
|
/** |
|
294
|
|
|
* Met à jour les membres de $instance annotés par un ManyToMany |
|
295
|
|
|
* @param object $instance |
|
296
|
|
|
*/ |
|
297
|
|
|
public static function insertOrUpdateAllManyToMany($instance){ |
|
298
|
|
|
$members=OrmUtils::getAnnotationInfo(get_class($instance), "#manyToMany"); |
|
299
|
|
|
if($members!==false){ |
|
300
|
|
|
$members=\array_keys($members); |
|
301
|
|
|
foreach ($members as $member){ |
|
302
|
|
|
self::insertOrUpdateManyToMany($instance, $member); |
|
303
|
|
|
} |
|
304
|
|
|
} |
|
305
|
|
|
} |
|
306
|
|
|
|
|
307
|
|
|
/** |
|
308
|
|
|
* Met à jour le membre $member de $instance annoté par un ManyToMany |
|
309
|
|
|
* @param Object $instance |
|
310
|
|
|
* @param String $member |
|
311
|
|
|
*/ |
|
312
|
|
|
public static function insertOrUpdateManyToMany($instance,$member){ |
|
313
|
|
|
$parser=new ManyToManyParser($instance, $member); |
|
314
|
|
|
if($parser->init()){ |
|
315
|
|
|
$myField=$parser->getMyFkField(); |
|
316
|
|
|
$field=$parser->getFkField(); |
|
317
|
|
|
$sql="INSERT INTO `".$parser->getJoinTable()."`(`".$myField."`,`".$field."`) VALUES (:".$myField.",:".$field.");"; |
|
318
|
|
|
$memberAccessor="get".ucfirst($member); |
|
319
|
|
|
$memberValues=$instance->$memberAccessor(); |
|
320
|
|
|
$myKey=$parser->getMyPk(); |
|
321
|
|
|
$myAccessorId="get".ucfirst($myKey); |
|
322
|
|
|
$accessorId="get".ucfirst($parser->getPk()); |
|
323
|
|
|
$id=$instance->$myAccessorId(); |
|
324
|
|
|
if(!is_null($memberValues)){ |
|
325
|
|
|
self::$db->execute("DELETE FROM `".$parser->getJoinTable()."` WHERE `".$myField."`='".$id."'"); |
|
326
|
|
|
$statement=self::$db->prepareStatement($sql); |
|
327
|
|
|
foreach ($memberValues as $targetInstance){ |
|
328
|
|
|
$foreignId=$targetInstance->$accessorId(); |
|
329
|
|
|
$foreignInstances=self::getAll($parser->getTargetEntity(), "`".$parser->getPk()."`"."='".$foreignId."'"); |
|
330
|
|
|
if(!OrmUtils::exists($targetInstance, $parser->getPk(), $foreignInstances)){ |
|
331
|
|
|
self::insert($targetInstance,false); |
|
332
|
|
|
$foreignId=$targetInstance->$accessorId(); |
|
333
|
|
|
Logger::log("InsertMany", "Insertion d'une instance de ".get_class($instance)); |
|
334
|
|
|
} |
|
335
|
|
|
self::$db->bindValueFromStatement($statement,$myField,$id); |
|
336
|
|
|
self::$db->bindValueFromStatement($statement,$field,$foreignId); |
|
337
|
|
|
$statement->execute(); |
|
338
|
|
|
Logger::log("InsertMany", "Insertion des valeurs dans la table association '".$parser->getJoinTable()."'"); |
|
339
|
|
|
} |
|
340
|
|
|
} |
|
341
|
|
|
} |
|
342
|
|
|
} |
|
343
|
|
|
/** |
|
344
|
|
|
* Met à jour $instance dans la base de données. |
|
345
|
|
|
* Attention de ne pas modifier la clé primaire |
|
346
|
|
|
* @param Classe $instance instance à modifier |
|
347
|
|
|
* @param $updateMany Ajoute ou met à jour les membres ManyToMany |
|
348
|
|
|
*/ |
|
349
|
|
|
public static function update($instance,$updateMany=false){ |
|
350
|
|
|
$tableName=OrmUtils::getTableName(get_class($instance)); |
|
351
|
|
|
$ColumnskeyAndValues=Reflexion::getPropertiesAndValues($instance); |
|
352
|
|
|
$ColumnskeyAndValues=array_merge($ColumnskeyAndValues, OrmUtils::getManyToOneMembersAndValues($instance)); |
|
353
|
|
|
$keyFieldsAndValues=OrmUtils::getKeyFieldsAndValues($instance); |
|
354
|
|
|
$sql="UPDATE ".$tableName." SET ".SqlUtils::getUpdateFieldsKeyAndValues($ColumnskeyAndValues)." WHERE ".SqlUtils::getWhere($keyFieldsAndValues); |
|
355
|
|
|
Logger::log("update", $sql); |
|
356
|
|
|
Logger::log("Key and values", json_encode($ColumnskeyAndValues)); |
|
357
|
|
|
$statement=self::$db->prepareStatement($sql); |
|
358
|
|
|
foreach ($ColumnskeyAndValues as $key=>$value){ |
|
359
|
|
|
self::$db->bindValueFromStatement($statement,$key,$value); |
|
360
|
|
|
} |
|
361
|
|
|
$result= $statement->execute(); |
|
362
|
|
|
if($result && $updateMany) |
|
363
|
|
|
self::insertOrUpdateAllManyToMany($instance); |
|
364
|
|
|
return $result; |
|
365
|
|
|
} |
|
366
|
|
|
|
|
367
|
|
|
/** |
|
368
|
|
|
* Réalise la connexion à la base de données en utilisant les paramètres passés |
|
369
|
|
|
* @param string $dbName |
|
370
|
|
|
* @param string $serverName |
|
371
|
|
|
* @param string $port |
|
372
|
|
|
* @param string $user |
|
373
|
|
|
* @param string $password |
|
374
|
|
|
*/ |
|
375
|
|
|
public static function connect($dbName,$serverName="127.0.0.1",$port="3306",$user="root",$password=""){ |
|
376
|
|
|
self::$db=new Database($dbName,$serverName,$port,$user,$password); |
|
377
|
|
|
self::$db->connect(); |
|
378
|
|
|
} |
|
379
|
|
|
} |
|
380
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return,dieorexitstatements that have been added for debug purposes.In the above example, the last
return falsewill never be executed, because a return statement has already been met in every possible execution path.