6dc0e9a07bcff97ac9b111f36e12f1f6

For the most part, this class does everything I need. I've been updating it to PHP5, and have noticed a really rather big issue with my Transaction support: it simple doesnt work.

I've explained the issue in comments in the code.

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
211
212
213
214
215
216
217
218
219
220
221
<?php

class DB {
	
	//connection variables
	protected $dbhost = 'localhost';
	protected $dbuser = 'root';
	protected $dbpass = '';
	protected $dbname = 'dbname';
	
	//normal global resources
	protected $db = null;
	protected static $instance = null;
	
	/**
	 * Singleton pattern for instantiating the DB class
	 */
	public static function GetInstance()
	{
		if(!self::$instance)
		{
			self::$instance = new DB;
		}
		return self::$instance;
	}
	
	protected function __construct()
	{
		if(($db = @mysql_connect($this->dbhost, $this->dbuser, $this->dbpass)) === false)
		{
			trigger_error('There was an error connecting to the server.');
			exit;
		}
		
		if((@mysql_select_db($this->dbname, $db)) === false)
		{
			trigger_error('There was an error selecting the database.');
			exit;
		}
		$this->db = $db;
	}
	
	/**
	 * simple method for sanitizing SQL query strings.
	 */
	public function Clean($string)
	{
		if(get_magic_quotes_gpc())
		{
			$string = stripslashes($string);
		}
		return mysql_real_escape_string($string);
	}
	
	/**
	 * DB class method call to the Query child class.
	 * SELECT queries only
	 * Returns an object.
	 */
	public function Query($statement)
	{
		return new Query($statement, $this->db);
	}
	
	/**
	 * DB class method call to the Execute child class.
	 * INSERT/UPDATE/DELETE queries only
	 * Returns number of rows affected.
	 */
	public function Execute($statement)
	{
		return new Execute($statement, $this->db);
	}
	
	/**
	 * Used to get the last inserted record
	 */
	public function InsertID()
	{
		return mysql_insert_id($this->link);
	}
	
	/**
	 * The transactional functions are giving me more of a headache than
	 * I sould care to have. The general idea behind what I want to do
	 * with them is be able to pass an array of SQL queries into one
	 * main method call, which in turn calls its child methods.
	 *
	 * The issue I have with this is that there are instances where I
	 * dont want to base a Commit / Rollback on whether or not the
	 * queries succeed or fail, but perhaps the time of day, or the
	 * privelage level of the user running the queries, etc.
	 */
	public function Transaction($queryArray)
	{
		/**
		 * this method call will return a new instance of the
		 * Transaction CLass. Operations are documented within
		 * the Transaction Class.
		 */
		 return new Transaction($queryArray, $this->db);
	}
	
	public function __destruct()
	{
		@mysql_close($this->db);
	}
	
}

/**
 * These are separate classes for the reason that I would like
 * to be able to edit them with as little distruption to the 
 * flow of the parent class as possible. 
 */

/**
 * Query child class. Used for running SELECT queries.
 * Called exclusively by the DB parent class in the Query method
 */
class Query
{
	protected $result;
	
	public function __construct($statement, $link)
	{
		if(($this->result = mysql_query($statement, $link)) === false)
		{
			trigger_error('There was an error in processing the Query method: '. mysql_error());
			exit;
		}
	}
	
	public function Fetch($class = null)
	{
		return @mysql_fetch_object($this->result);
	}
	
	public function __destruct()
	{
		@mysql_free_result($this->result);
	}
}

/**
 * Execute child class. Used for running INSERT/UPDATE/DELETE queries.
 * Called exclusively by the DB parent class in the Execute method
 */
class Execute
{
	public function __construct($statement, $link)
	{
		if((@mysql_query($statement, $link)) == false)
		{
			trigger_error('There was an error processing the Execute method: '. mysql_error());
			exit;
		}
		return @mysql_affected_rows($link);
	}
}

/**
 * Transaction child class. Used for transactional queries.
 * Called exclusively by the DB parent class in the Transaction method
 */
class Transaction
{
	public function __construct($queryArray, $link)
	{
		/**
		 * This is not working at all the way I want it to.
		 * 
		 * Essentially what it is doing, is running the first
		 * query, then basing the Commit / Rollback on the
		 * outcome of that single query. That's no good.
		 *
		 * I can see _why_ its not working, but that doesn't
		 * really help me to fix it. 
		 *
		 * $hold is set to 1 as its starting value, and as
		 * the loop progresses it either changes that or 
		 * doesnt, depending on the outcome. What it seems
		 * to be doing is running it once, and deciding
		 * "Hey! the query worked!, lets commit changes!".
		 */
		$hold = 1;
		$this->Begin();
		foreach($queryArray as $query) {
			@mysql_query($query, $link);
			if(@mysql_affected_rows($link) == 0)
			{
				$hold = 0;
			}
		}
		if($hold == 0)
		{
			$this->Rollback();
			return false;
		} else {
			$this->Commit();
			return true;
		}
	}
	
	private function Begin()
	{
		@mysql_query('BEGIN', $link);
	}
	
	private function Commit()
	{
		@mysql_query('COMMIT', $link);
	}
	
	private function Rollback()
	{
		@mysql_query('ROLLBACK', $link);
	}
}

?>

Refactorings

No refactoring yet !

1e8f141e7857d397d8020ed3b759e88a

Maciej Piechotka

July 21, 2008, July 21, 2008 19:24, permalink

2 ratings. Login to rate!

1. Why not PEAR DB?
2. Why not MySQLi with precompiled queries (it has everything you need but faster and in standard)?

6dc0e9a07bcff97ac9b111f36e12f1f6

Ishkur

July 22, 2008, July 22, 2008 03:36, permalink

No rating. Login to rate!

Well if I wanted to go that route I could just as well use PDO and be done with the whole class, but thats not really what I want. And to be completely honest I dont really like Pear, it just feels like there's so much overhead. I just sorta wanted the transactional functions to work.... the child methods themselves work, thats not an issue, but the constructor method is whats killing me.

1e8f141e7857d397d8020ed3b759e88a

Maciej Piechotka

August 6, 2008, August 06, 2008 21:23, permalink

1 rating. Login to rate!

Sorry for late response - so what do you want which is not covered by MySQLi?

Your refactoring





Format Copy from initial code

or Cancel