[OOP|SQLite] global vanuit extended class
Misschien zegt de titel genoeg. Ik heb een heel achterhaald DB systeem gebouwd dat zowel SQLite als MySQLi aankan met zelfde syntax/queries. Het probleem is echter dat SQLite geen fatsoenlijke error handling heeft, dus die moet ik afvangen met een tijdelijke error_handler. Die errorhandler wordt dus niet aangeroepen vanuit trigger_error() omdat het alleen om sqlite errors gaat, die gespawnd worden 'tijdens' het uitvoeren van de query.
Het doel is geen errors te printen (dat kan, namelijk afvangen en discarden) en in de code zelf netjes een msg weer te geven. In die msg kan ik de query zetten (die wordt nl. ook in de code aangemaakt, dus die heb ik) en dat er een fout is opgetreden. Maar WAT de fout is, is niet te achterhalen... De error handler vangt de fout af en discard m dan, dus die gaat verloren. Ik heb geprobeerd -- op elke mogelijke manier -- om te fout op te slaan in de DB klasse om m zo netjes te kunnen printen, in de code, via een public var, maar ik kan via de error handler niet (meer) bij de geinstantieerde (snappie?) klasse, dus kan m nergens opslaan.
Toen dacht ik, net als php heeft/had, de error op te slaan in een global/public var -- bijvorbeeld $szLastSQLiteError -- en die in de code aan te roepen in geval van error. Het probleem: de var wordt niet gevuld. Heb een aantal manieren geprobeerd, maar kom er niet uit!
Ik zal mijn code printen, maar let op, het is achterhaald, slecht en slordig :)
Alle defininitions bestaan en zijn as expected.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
<?php
/** PERFORM QUERY **/
function sqlquery( $sqlQuery, $dbCon = NULL, $bLastTry = FALSE )
{
if ( TRUE === $bLastTry && !is_object($dbCon) )
{
trigger_error("<span style=\"color:#bb0000;font-weight:bold;\">DB CONNECTION NEEDED TO PERFORM QUERIES!</span>", E_USER_ERROR);
}
/** SQLITE **/
if ( "sqlite" == SQL_HANDLER )
{
if ( !$dbCon ){$dbCon = sqlconnect( DB_SQLITE_DBNAME ); sqlquery($sqlQuery,$dbCon,TRUE);}
$qR = $dbCon->query($sqlQuery);
// var_dump( $qR );
if ( !$qR )
{
return FALSE;
}
else if ( FALSE !== $qR && TRUE !== $qR )
{
return $qR->fetchAll( SQLITE_ASSOC );
}
else
{
return $qR;
}
return FALSE;
}
/* */
/** MYSQLI **/
if ( "mysql" == SQL_HANDLER )
{
if ( !$dbCon ){$dbCon = sqlconnect( DB_SQLITE_DBNAME ); sqlquery($sqlQuery,$dbCon,TRUE);}
$qR = $dbCon->query($sqlQuery);
// var_dump( $qR );
if ( !$qR )
{
return FALSE;
}
else if ( FALSE !== $qR && TRUE !== $qR )
{
$arrResults = Array( );
while ( $arr = $qR->fetch_assoc() )
{
$arrResults[] = $arr;
}
// print_r( $arrResults );
return $arrResults;
}
else
{
return $qR;
}
return FALSE;
}
/* */
} // END sqlquery( )
/** CONNECT TO DATABASE **/
function sqlconnect( $dbname = SQL_LOGIN_DATABASE_MEM, $host = SQL_LOGIN_HOST, $user = SQL_LOGIN_USER, $pass = SQL_LOGIN_PASS, $sock = SQL_LOGIN_SOCKET, $port = SQL_LOGIN_PORT )
{
global $LastSQLiteError;
$LastSQLiteError = "";
/** SQLITE **/
if ( "sqlite" == SQL_HANDLER )
{
try {
$dbCon = new CVM_SQLiteDatabase( $dbname );
} catch ( Exception $exc ) {
die("Exception caught: "".$exc->getMessage()."" :: ".print_r( $exc->getTrace(), TRUE )." <--\n");
}
if ( !$dbCon )
{
return FALSE;
}
return $dbCon;
}
/* */
/** MYSQLI **/
if ( "mysql" == SQL_HANDLER )
{
$dbCon = new CVM_mysqli( $host, $user, $pass, $dbname, $port, $sock );
if ( !$dbCon )
{
return FALSE;
}
return $dbCon;
}
/* */
} // END sqlconnect( )
/** MYSQLI CLASS | EXTENDED FOR sqlquery( ) **/
class CVM_mysqli extends mysqli
{
final public function query( $sql )
{
$result = parent::query( $sql );
if ( !$result )
{
die( "<div style=\"position:absolute;top:0;left:0;margin:0;padding:7px;border:solid 4px red;\">\n<b>SQL ERROR!!</b><br/>\n" .
"<div style=\"background-color:#ccc;\"><font style=\"font-family:'courier new';font-size:10pt;\">"".$sql.""</div>\n" .
"^^ " . $this->error . "</font></div>\n" );
}
return $result;
} // END query( )
public function sqlquery( $sql )
{
$q = sqlquery( $sql, $this );
// print_r( $q );
return $q;
} // END sqlquery( )
} // END Class CVM_mysqli
if ( "sqlite" == SQL_HANDLER )
{
/** SQLITE CLASS | EXTENDED FOR 'ERROR REPORTING' **/
class CVM_SQLiteDatabase extends SQLiteDatabase
{
const FieldDelimiter = "";
public $szLastError = "";
public function query( $sql )
{
// Filter errors only in this class!
set_error_handler("sqlite_errorhandler");
$result = parent::query( $sql );
if ( !$result )
{
return FALSE;
die( "<br/>\n<pre>>> $sql <<</pre>\n\n" );
}
restore_error_handler( );
return $result;
} // END query( )
public function sqlquery( $sql )
{
return sqlquery( $sql, $this );
}
static public function setError( $err )
{
// echo $err;
global $LastSQLiteError;
$LastSQLiteError = $err;
}
public function prepare_fields( $tmp_arrFields )
{
$arrFields = Array( );
foreach ( $tmp_arrFields AS $fldName )
{
if ( 0 < strlen(trim($fldName)) )
{
$arrFields[] = $fldName;
}
}
$retval = self::FieldDelimiter . implode(self::FieldDelimiter.", ".self::FieldDelimiter, $arrFields) . self::FieldDelimiter;
return trim($retval);
} // END prepare_fields( )
} // END CLASS VM_SQLiteDatabase
/** SQLITE ERROR REPORTING **/
function sqlite_errorhandler( $errno, $errstr, $errfile, $errline )
{
$errstr = trim(str_replace('::','',$errstr));
$errstr = trim(substr($errstr, strpos($errstr, ':')+1));
CVM_SQLiteDatabase::setError($errstr);
return;
echo '<font color="blue"><b>SQLITE ERROR</b>: '.$errstr.'</font>';
} // END sqlite_errorhandler( )
}
?>
/** PERFORM QUERY **/
function sqlquery( $sqlQuery, $dbCon = NULL, $bLastTry = FALSE )
{
if ( TRUE === $bLastTry && !is_object($dbCon) )
{
trigger_error("<span style=\"color:#bb0000;font-weight:bold;\">DB CONNECTION NEEDED TO PERFORM QUERIES!</span>", E_USER_ERROR);
}
/** SQLITE **/
if ( "sqlite" == SQL_HANDLER )
{
if ( !$dbCon ){$dbCon = sqlconnect( DB_SQLITE_DBNAME ); sqlquery($sqlQuery,$dbCon,TRUE);}
$qR = $dbCon->query($sqlQuery);
// var_dump( $qR );
if ( !$qR )
{
return FALSE;
}
else if ( FALSE !== $qR && TRUE !== $qR )
{
return $qR->fetchAll( SQLITE_ASSOC );
}
else
{
return $qR;
}
return FALSE;
}
/* */
/** MYSQLI **/
if ( "mysql" == SQL_HANDLER )
{
if ( !$dbCon ){$dbCon = sqlconnect( DB_SQLITE_DBNAME ); sqlquery($sqlQuery,$dbCon,TRUE);}
$qR = $dbCon->query($sqlQuery);
// var_dump( $qR );
if ( !$qR )
{
return FALSE;
}
else if ( FALSE !== $qR && TRUE !== $qR )
{
$arrResults = Array( );
while ( $arr = $qR->fetch_assoc() )
{
$arrResults[] = $arr;
}
// print_r( $arrResults );
return $arrResults;
}
else
{
return $qR;
}
return FALSE;
}
/* */
} // END sqlquery( )
/** CONNECT TO DATABASE **/
function sqlconnect( $dbname = SQL_LOGIN_DATABASE_MEM, $host = SQL_LOGIN_HOST, $user = SQL_LOGIN_USER, $pass = SQL_LOGIN_PASS, $sock = SQL_LOGIN_SOCKET, $port = SQL_LOGIN_PORT )
{
global $LastSQLiteError;
$LastSQLiteError = "";
/** SQLITE **/
if ( "sqlite" == SQL_HANDLER )
{
try {
$dbCon = new CVM_SQLiteDatabase( $dbname );
} catch ( Exception $exc ) {
die("Exception caught: "".$exc->getMessage()."" :: ".print_r( $exc->getTrace(), TRUE )." <--\n");
}
if ( !$dbCon )
{
return FALSE;
}
return $dbCon;
}
/* */
/** MYSQLI **/
if ( "mysql" == SQL_HANDLER )
{
$dbCon = new CVM_mysqli( $host, $user, $pass, $dbname, $port, $sock );
if ( !$dbCon )
{
return FALSE;
}
return $dbCon;
}
/* */
} // END sqlconnect( )
/** MYSQLI CLASS | EXTENDED FOR sqlquery( ) **/
class CVM_mysqli extends mysqli
{
final public function query( $sql )
{
$result = parent::query( $sql );
if ( !$result )
{
die( "<div style=\"position:absolute;top:0;left:0;margin:0;padding:7px;border:solid 4px red;\">\n<b>SQL ERROR!!</b><br/>\n" .
"<div style=\"background-color:#ccc;\"><font style=\"font-family:'courier new';font-size:10pt;\">"".$sql.""</div>\n" .
"^^ " . $this->error . "</font></div>\n" );
}
return $result;
} // END query( )
public function sqlquery( $sql )
{
$q = sqlquery( $sql, $this );
// print_r( $q );
return $q;
} // END sqlquery( )
} // END Class CVM_mysqli
if ( "sqlite" == SQL_HANDLER )
{
/** SQLITE CLASS | EXTENDED FOR 'ERROR REPORTING' **/
class CVM_SQLiteDatabase extends SQLiteDatabase
{
const FieldDelimiter = "";
public $szLastError = "";
public function query( $sql )
{
// Filter errors only in this class!
set_error_handler("sqlite_errorhandler");
$result = parent::query( $sql );
if ( !$result )
{
return FALSE;
die( "<br/>\n<pre>>> $sql <<</pre>\n\n" );
}
restore_error_handler( );
return $result;
} // END query( )
public function sqlquery( $sql )
{
return sqlquery( $sql, $this );
}
static public function setError( $err )
{
// echo $err;
global $LastSQLiteError;
$LastSQLiteError = $err;
}
public function prepare_fields( $tmp_arrFields )
{
$arrFields = Array( );
foreach ( $tmp_arrFields AS $fldName )
{
if ( 0 < strlen(trim($fldName)) )
{
$arrFields[] = $fldName;
}
}
$retval = self::FieldDelimiter . implode(self::FieldDelimiter.", ".self::FieldDelimiter, $arrFields) . self::FieldDelimiter;
return trim($retval);
} // END prepare_fields( )
} // END CLASS VM_SQLiteDatabase
/** SQLITE ERROR REPORTING **/
function sqlite_errorhandler( $errno, $errstr, $errfile, $errline )
{
$errstr = trim(str_replace('::','',$errstr));
$errstr = trim(substr($errstr, strpos($errstr, ':')+1));
CVM_SQLiteDatabase::setError($errstr);
return;
echo '<font color="blue"><b>SQLITE ERROR</b>: '.$errstr.'</font>';
} // END sqlite_errorhandler( )
}
?>
Het gehele MySQLi gedeelte is te verwaarlozen, ik gebruik alleen nog SQLite (in MySQLi is dit een eitje).
Een aanroep en usage kan zijn:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Iemand betere ideeen? Heel de code mag afgekraakt worden :) Graag met onderbouwing aub.
groetjes
Rudie
deze standaard voorschriften, maar binnen je klasse definieert. Vervolgens registreer je hem dan met
Als ik het goed heb wordt dan de method van de huidige instance aangeroepen, en hoef je niet met static-zooi te klooien.
Wat nu als je een errorhandler maakt volgens Als ik het goed heb wordt dan de method van de huidige instance aangeroepen, en hoef je niet met static-zooi te klooien.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class DB {
protected $errors = array();
public function query($sql)
{
set_error_handler(array($this, 'errorHandler'));
/* query etc. */
}
public function errorHandler($errno, $errstr, $errfile, $errline)
{
$this->errors[] = array($errno, $errstr);
}
}
$instance = new DB(...);
$instance->query('Foute query!');
var_dump($instance);
?>
class DB {
protected $errors = array();
public function query($sql)
{
set_error_handler(array($this, 'errorHandler'));
/* query etc. */
}
public function errorHandler($errno, $errstr, $errfile, $errline)
{
$this->errors[] = array($errno, $errstr);
}
}
$instance = new DB(...);
$instance->query('Foute query!');
var_dump($instance);
?>
Geweldig!
Ik ga het proberen
dank
groetjes
R