OOP database class
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
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
<?php
class Database {
// @param String
private $db;
// @param String
private $query;
/**
* Constructor, connect to the database
* @param String $host, The host to connect
* @param String $database, The database to connect
* @param String $user, The database user
* @param String $password, The database password
*/
public function __construct($host = 'localhost', $database, $user, $password) {
if($host && $database && $user && $password) {
if (mysql_connect($host, $user, $password)) {
if (!$this->db = mysql_select_db($database)) {
throw new SQLException('Connection with the database failed.');
}
}else{
throw new SQLException('Connection with the server failed.');
}
}else{
throw new SQLException('1 or more database parameters are missing.');
}
}
/**
* Check if there is a database connection
* @return Boolean
*/
private function isConnected() {
if ($this->db == '') {
throw new SQLException('There is no database connection.');
return false;
}
}
/**
* Set a query
* @param String $query, The preforming query
* @return Resource, The preformed query
*/
public function setQuery($query) {
$this->isConnected();
if ($query) {
if ($this->query = mysql_query($query)) {
return $this->query;
}else{
throw new SQLException('Query failed, reason: '.mysql_error());
}
}else{
throw new SQLException('1 or more query parameters are missing.');
}
}
/**
* Get the num rows from last preformed query
* @param String $query, The preformed query
* @return Integer
*/
public function getNumRows($query = '') {
$this->isConnected();
if (is_resource($query) || is_resource($this->query)) {
$query = (!is_resource($query)) ? $this->query : $query;
if ($numRows = mysql_num_rows($query)) {
return $numRows;
}else{
throw new SQLException('Query failed, reason: '.mysql_error());
}
}else{
throw new SQLException('No query preformed.');
}
}
/**
* Get the fetch from last preformed query
* @param String $query, The preformed query
* @return Array
*/
public function getFetch($query = '') {
$this->isConnected();
if (is_resource($query) || is_resource($this->query)) {
$query = (!is_resource($query)) ? $this->query : $query;
if ($fetch = mysql_fetch_array($query)) {
return $fetch;
}else{
throw new SQLException('Query failed, reason: '.mysql_error());
}
}else{
throw new SQLException('No query preformed.');
}
}
/**
* Get the last inserted id
* @return Integer
*/
public function getLastId() {
$this->isConnected();
return mysql_insert_id();
}
}
try {
$db = new Database(HOST, DATABASE, USER, PASSWORD);
$result = $db->setQuery('SELECT id FROM table_test');
$result = $db->getFetch($result);
echo $db->getNumRows();
} catch (CoreException $error) {
echo $error->getMessage();
} catch (SQLException $error) {
echo $error->getMessage();
}
?>
class Database {
// @param String
private $db;
// @param String
private $query;
/**
* Constructor, connect to the database
* @param String $host, The host to connect
* @param String $database, The database to connect
* @param String $user, The database user
* @param String $password, The database password
*/
public function __construct($host = 'localhost', $database, $user, $password) {
if($host && $database && $user && $password) {
if (mysql_connect($host, $user, $password)) {
if (!$this->db = mysql_select_db($database)) {
throw new SQLException('Connection with the database failed.');
}
}else{
throw new SQLException('Connection with the server failed.');
}
}else{
throw new SQLException('1 or more database parameters are missing.');
}
}
/**
* Check if there is a database connection
* @return Boolean
*/
private function isConnected() {
if ($this->db == '') {
throw new SQLException('There is no database connection.');
return false;
}
}
/**
* Set a query
* @param String $query, The preforming query
* @return Resource, The preformed query
*/
public function setQuery($query) {
$this->isConnected();
if ($query) {
if ($this->query = mysql_query($query)) {
return $this->query;
}else{
throw new SQLException('Query failed, reason: '.mysql_error());
}
}else{
throw new SQLException('1 or more query parameters are missing.');
}
}
/**
* Get the num rows from last preformed query
* @param String $query, The preformed query
* @return Integer
*/
public function getNumRows($query = '') {
$this->isConnected();
if (is_resource($query) || is_resource($this->query)) {
$query = (!is_resource($query)) ? $this->query : $query;
if ($numRows = mysql_num_rows($query)) {
return $numRows;
}else{
throw new SQLException('Query failed, reason: '.mysql_error());
}
}else{
throw new SQLException('No query preformed.');
}
}
/**
* Get the fetch from last preformed query
* @param String $query, The preformed query
* @return Array
*/
public function getFetch($query = '') {
$this->isConnected();
if (is_resource($query) || is_resource($this->query)) {
$query = (!is_resource($query)) ? $this->query : $query;
if ($fetch = mysql_fetch_array($query)) {
return $fetch;
}else{
throw new SQLException('Query failed, reason: '.mysql_error());
}
}else{
throw new SQLException('No query preformed.');
}
}
/**
* Get the last inserted id
* @return Integer
*/
public function getLastId() {
$this->isConnected();
return mysql_insert_id();
}
}
try {
$db = new Database(HOST, DATABASE, USER, PASSWORD);
$result = $db->setQuery('SELECT id FROM table_test');
$result = $db->getFetch($result);
echo $db->getNumRows();
} catch (CoreException $error) {
echo $error->getMessage();
} catch (SQLException $error) {
echo $error->getMessage();
}
?>
Gewijzigd op 25/08/2011 09:38:44 door Joakim Broden
Fabian M op 24/08/2011 20:32:39:
Dat is natuurlijk geheel persoonlijk! Zoals Hertog Jan het doet kan het ook.
Ozzie PHP op 24/08/2011 20:41:50:
Dat is natuurlijk geheel persoonlijk! Zoals Hertog Jan het doet kan het ook.
Fabian M op 24/08/2011 20:32:39:
Dat is natuurlijk geheel persoonlijk! Zoals Hertog Jan het doet kan het ook.
Ik zou het alleen adviseren voor het uitleggen van een lijn, niet meerderen.
Waarom gooi je een coreException als een query niet werkt?
Jacco Brandt op 24/08/2011 21:13:14:
Waarom gooi je een coreException als een query niet werkt?
Dit omdat ik op internet heb gelezen dat je met throw/try/catch een mooie fout afhandeling kunt maken, als een query niet werkt is dat toch een fout? Of kan dit beter?
Ik zou een nette afhandeling geven. Met een aangepast bericht die past bij je layout. Anders schrikt het zo af...
Ik zou helemaal gek worden van deze manier van programmeren. Ik vindt het er niet overzichtelijk uitzien. Maar iedere zijn eigen style.
Het is anders wel rete handig hoor... als je in het catch-blok verwijst naar een mooie 'foutmelding'-view dan kun je je foutmeldingen op een hele gelikte manier tonen, terwijl je op de plekken in de code waar zich een fout kan voordoen alleen maar 1 zinnetje tekst hoeft neer te zetten. Verder hoef je nergens aan te denken.
Maar het is geen CoreException, maar een SQL, of Database-Exeption.
Mijn reactie was meer bedoeld als reactie op PHP Scripter die die manier van programmeren onoverzichtelijk vind.
Wat ik zelf wel eens heb gedaan is alles in 1 try - catch blok zetten....
In de try start ik m'n framework op en als ie ergens (waar dan ook) een exception tegenkomt dan laat ik 'm een view aanroepen waarin de foutmelding wordt getoond.
Dit stukje, zoals de topicstarter doet:
try {
$db = new Database(HOST, DATABASE, USER, PASSWORD);
$result = $db->setQuery('SELECT id FROM table_test');
$result = $db->getFetch($result);
print_r($results);
} catch (CoreException $error) {
echo $error->getMessage();
}
... hoef ik niet te doen. Dat zou bij mij dan gewoon dit zijn:
$db = new Database(HOST, DATABASE, USER, PASSWORD);
$result = $db->setQuery('SELECT id FROM table_test');
$result = $db->getFetch($result);
print_r($results);
Dat gaat prima, omdat alles uiteindelijk in het try - catch blok staat.
Op die manier werkt mijn CMS overigens ook. ;-)
Misschien een leuke toevoeging voor de class:
getTotalExecutedQueries(), uitleg lijkt me niet nodig ;-)
Misschien kan je ook een classe bouwen (lang leven OOP) die een meting doet hoelang een query draait. Leuk voor benchmarking en debugging.
Gewijzigd op 24/08/2011 23:19:30 door - Ariën -
- Aar - op 24/08/2011 23:17:05:
Ja, maar het gaat om het voorbeeld, welke onder de class staat.
Op die manier werkt mijn CMS overigens ook. ;-)
Misschien een leuke toevoeging voor de class:
getTotalExecutedQueries(), uitleg lijkt me niet nodig ;-)
Op die manier werkt mijn CMS overigens ook. ;-)
Misschien een leuke toevoeging voor de class:
getTotalExecutedQueries(), uitleg lijkt me niet nodig ;-)
De manier van de topicstarter, of zoals ik 'm beschreef?
tussen een algemeen try - catch blok.... ;-)
ah oke, nice :-)
@Ozzie en Aar, jullie raden dus aan om alles met throw new shizzle te doen en dan alle throws opvangen in 1 try/catch blok. Dus dan zou je dit krijgen:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
try {
// Hier komt dan de complete CMS/Website/Applicatie, met dus alle classes/html/javasscript ed
} catch (CoreException $error) {
// Hier de code tonen van de foutmelding
}
?>
try {
// Hier komt dan de complete CMS/Website/Applicatie, met dus alle classes/html/javasscript ed
} catch (CoreException $error) {
// Hier de code tonen van de foutmelding
}
?>
Diverse vragen die mij nog oproepen:
1) Maar als je dan bijvoorbeeld een CoreException, SQLException hebt en dergelijke hoe vang je die dan op omdat je maar 1 catch hebt? Of moet je dan met meerdere catch werken zoals:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
try {
// Hier komt dan de complete CMS/Website/Applicatie, met dus alle classes/html/javasscript ed
} catch (CoreException $error) {
// Hier de code tonen van de foutmelding 'Core'
} catch (SQLException $error) {
// Hier de code tonen van de foutmelding 'SQL'
}
?>
try {
// Hier komt dan de complete CMS/Website/Applicatie, met dus alle classes/html/javasscript ed
} catch (CoreException $error) {
// Hier de code tonen van de foutmelding 'Core'
} catch (SQLException $error) {
// Hier de code tonen van de foutmelding 'SQL'
}
?>
2) Als je voor elk soort fout een aparte Exception maakt zoals CoreException, SQLException, krijg je op het laatst toch heel veel Exception classes? Zorgt dit niet voor te veel code en dergelijke?
In de begin post heb ik nu de nieuwe code geplaatst, maar zit ik een beetje op de goede weg of raden jullie mij anderdere dingen qua OOP/Throw. Graag tips en tricks :)
Gewijzigd op 25/08/2011 09:37:58 door Joakim Broden
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
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
<?php
$db = new Database(...);
function list_topics()
{
global $db;
$db->setQuery("SELECT id, title, last_post_datetime FROM topics");
while ($topic = $db->getFetch())
echo $topic['title'] . " (" . user_format_timestamp($topic['last_post_datetime']) . ")\n";
}
function user_format_timestamp($timestamp)
{
$format = user_get_preference('timestamp_format', 'd-m-Y');
return date($format, $timestamp);
}
function user_get_preference($key, $default_value = null)
{
static $preferences;
if (!$preferences)
$preferences = user_fetch_preferences($_SESSION['user_id']);
return isset($preferences[$key])
? $preferences[$key]
: $default_value;
}
function user_fetch_preferences($user_id)
{
global $db;
$db->setQuery("SELECT key, value FROM preferences WHERE user_id = $user_id");
$preferences = array();
while ($row = $db->getFetch())
$preferences[$row['key']] = $row['value'];
return $preferences;
}
list_topics();
?>
$db = new Database(...);
function list_topics()
{
global $db;
$db->setQuery("SELECT id, title, last_post_datetime FROM topics");
while ($topic = $db->getFetch())
echo $topic['title'] . " (" . user_format_timestamp($topic['last_post_datetime']) . ")\n";
}
function user_format_timestamp($timestamp)
{
$format = user_get_preference('timestamp_format', 'd-m-Y');
return date($format, $timestamp);
}
function user_get_preference($key, $default_value = null)
{
static $preferences;
if (!$preferences)
$preferences = user_fetch_preferences($_SESSION['user_id']);
return isset($preferences[$key])
? $preferences[$key]
: $default_value;
}
function user_fetch_preferences($user_id)
{
global $db;
$db->setQuery("SELECT key, value FROM preferences WHERE user_id = $user_id");
$preferences = array();
while ($row = $db->getFetch())
$preferences[$row['key']] = $row['value'];
return $preferences;
}
list_topics();
?>
Ik zou toch meer PDO's idee aanhouden, waarbij PDO::query een PDOStatement object teruggeeft, en je PDOStatement::fetch gebruikt om van die ene query de resultaten op te halen. Zo lopen je resultaten nooit door elkaar.
Gewijzigd op 25/08/2011 09:47:41 door Jelmer -
Gewijzigd op 25/08/2011 09:58:53 door - Ariën -
Hertog Jan op 25/08/2011 09:18:39:
@Ozzie en Aar, jullie raden dus aan om alles met throw new shizzle te doen en dan alle throws opvangen in 1 try/catch blok. Dus dan zou je dit krijgen:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
try {
// Hier komt dan de complete CMS/Website/Applicatie, met dus alle classes/html/javasscript ed
} catch (CoreException $error) {
// Hier de code tonen van de foutmelding
}
?>
try {
// Hier komt dan de complete CMS/Website/Applicatie, met dus alle classes/html/javasscript ed
} catch (CoreException $error) {
// Hier de code tonen van de foutmelding
}
?>
Dat was wel hoe ik het destijds gedaan had, maar dan deed ik het ongeveer op deze manier:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<?php
try {
// Hier komt dan de complete CMS/Website/Applicatie, met dus alle classes/html/javasscript ed
} catch (Exception $error) {
// Eigengemaakte class aanroepen.
MyException::show();
}
?>
try {
// Hier komt dan de complete CMS/Website/Applicatie, met dus alle classes/html/javasscript ed
} catch (Exception $error) {
// Eigengemaakte class aanroepen.
MyException::show();
}
?>
Op het moment dat je ergens een exception throwde dan kon ik er een extra 'type' parameter aan mee geven:
throw new MyException('Geen database verbinding' , 'database');
In MyException vang je dan het type op (de default zet je dan bijvoorbeeld op 'standard'). Op het moment dat het type 'database' is (zoals hierboven) kun je daar de layout van je view op aanpassen door bijvoorbeeld een plaatje van een database te tonen, of door een aparte titel boven de foutmelding te zetten 'Database fout:'.
In plaats van dat je dus allerlei verschillende soorten exceptions heb, gebruik je er slechts 1 (MyException) en daar stuur je alles naartoe. Aan de hand van de parameter wordt in de MyException class bepaald om wat voor soort Exception het gaat.
Geen idee of dit een goede manier is, maar ik vind het wel handig.
Gewijzigd op 25/08/2011 10:15:26 door Ozzie PHP
The Force op 24/08/2011 21:17:50:
Het voordeel van die block comment is dat je er documentatie mee kan laten genereren. PHP Documentor accepteert geen //. Zie http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.quickstart.pkg.html .
Heb ik nog mooit gezien. Lijkt me best handig...