1. DBQuery object
Now, our DBQuery object simply emulates a stored procedure - once executed, it returns a result resource that must be saved; and if you want to use functions on that result set (such as num_rows() or fetch_row()), You have to pass the MySqlDB object. So, what is the effect if the DBQuery object implements the functions implemented by the MySqlDB object (which is designed to operate on the results of an executed query)? Let's continue using the code from the previous example; and let's assume that our result resources are now managed by a DBQuery object. The source code of the DBQuery class is shown in Listing 1.
Listing 1. Using the DBQuery class.
require mysql_db.php;
require mysql_db.php;
require_once query.php;
$db = new MySqlDb;
$db->connect(host, username, pass);
$db->query(use content_management_system);
$query = new DBQuery($db);
$query->prepare(SELECT fname,sname FROM users WHERE username=:1S AND pword=:2S AND expire_time<:3I);
try {
if($query->execute("visualad", "apron", time()))->num_rows() == 1) {
echo(Correct Credentials);
} else {
echo(Incorrect Credentials / Session Expired);
}
} catch (QueryException $e) {
echo(Error executing query: . $e);
} |
require_once query.php;
$db = new MySqlDb;
$db->connect(host, username, pass);
$db->query(use content_management_system);
$query = new DBQuery($db);
$query->prepare(SELECT fname,sname FROM users WHERE username=:1S AND pword=:2S AND expire_time<:3I); <🎜>
try { <🎜>
if($query->execute("visualad", "apron", time()))->num_rows() == 1) {
echo(Correct Credentials);
} else {
echo(Incorrect Credentials / Session Expired);
}
} catch (QueryException $e) {
echo(Error executing query: . $e);
} |
What we are most interested in in the modified code above are the catch statement and execute statement.
· The execute statement no longer returns a result resource, it now returns the DBQuery object itself.
· The DBQuery object now implements the num_rows() function—which we are already familiar with from the DB interface.
· If the query execution fails, it throws an exception of type QueryException. When converted to a string, it returns details of the error that occurred.
To do this, you need to use a proxy. In fact, you already use proxies in our DBQuery object, but now you'll use it in more depth to tie it tightly to the MySqlDB object. The DBQuery object has been initialized with an object that implements the DB interface, and it already contains a member function execute—which calls the query() method of the DB object to execute the query. The DBQuery object itself does not actually query the database, it leaves this task to the DB object. This is a proxy, which is a process by which an object can implement a specific behavior by sending messages to another object that implements the same or similar behavior.
To do this, you need to modify the DBQuery object to include all functions that operate on a result resource from the DB object. You need to use the stored results when executing a query to call the corresponding function of the DB object and return its results. The following functions will be added:
Listing 2: Extending the DBQuery class using proxies.
class DBQuery
class DBQuery
{
.....
public function fetch_array()
{
if (! is_resource($this->result)) {
throw new Exception(Query not executed.);
}
return $this->db->fetch_array($this->result);
}
public function fetch_row()
{
if (! is_resource($this->result)) {
throw new Exception(Query not executed.);
}
return $this->db->fetch_row($this->result);
}
public function fetch_assoc()
{
if (! is_resource($this->result)) {
throw new Exception(Query not executed.);
}
return $this->db->fetch_assoc($this->result);
}
public function fetch_object()
{
if (! is_resource($this->result)) {
throw new Exception(Query not executed.);
}
return $this->db->fetch_object($this->result);
}
public function num_rows()
{
if (! is_resource($this->result)) {
throw new Exception(Query not executed.);
}
return $this->db->num_rows($this->result);
}
} |
{
.....
public function fetch_array()
{
if (! is_resource($this->result)) {
Throw new Exception(Query not executed.);
}
return $this->db->fetch_array($this->result);
public function __construct(DB $db)
{
$this->db = $db;
} |
}
public function fetch_row()
{
if (! is_resource($this->result)) {
throw new Exception(Query not executed.);
}
return $this->db->fetch_row($this->result);
}
public function fetch_assoc()
{
if (! is_resource($this->result)) {
Throw new Exception(Query not executed.);
}
return $this->db->fetch_assoc($this->result);
}
public function fetch_object()
{
if (! is_resource($this->result)) {
Throw new Exception(Query not executed.);
}
return $this->db->fetch_object($this->result);
}
public function num_rows()
{
if (! is_resource($this->result)) {
Throw new Exception(Query not executed.);
}
return $this->db->num_rows($this->result);
}
} |
The implementation of each function is quite simple. It first checks to make sure the query has been executed, then delegates the task to the DB object, returning its results as if it were the query object itself (called a basic database function).
2. Type Hinting
In order for the proxy to work, we need to ensure that the $db variable of the DBQuery object is an instance of an object that implements the DB interface. Type hints are a new feature in PHP 5 that enable you to coerce function parameters into objects of a specific type. Prior to PHP 5, the only way to ensure that a function parameter was a specific object type was to use the type checking function provided in PHP (that is, is_a()). Now, you can simply cast an object type—by prefixing the function parameter with the type name. You've already seen type hints from our DBQuery object, which ensures that an object implementing the DB interface is passed into the object constructor.
public function __construct(DB $db)
{
$this->db = $db;
} |
When using type hints, you can specify not only object types, but also abstract classes and interfaces.
3. Throw exception
You may have noticed from the above code that you are catching an exception called QueryException (we will implement this object later). An exception is similar to an error, but more general. The best way to describe an exception is to use emergency. Although an emergency may not be "fatal," it must still be dealt with. When an exception is thrown in PHP, the current scope of execution is quickly terminated, whether it is a function, try..catch block or the script itself. The exception then traverses the call stack—terminating each execution scope—until it is either caught in a try..catch block or it reaches the top of the call stack—at which point it generates a fatal error.
Exception handling is another new feature in PHP 5. When used in conjunction with OOP, it can achieve good control over error handling and reporting. A try..catch block is an important mechanism for handling exceptions. Once caught, script execution will continue from the next line of code where the exception was caught and handled.
If the query fails, you need to change your execute function to throw an exception. You will throw a custom exception object called QueryException - the DBQuery object that caused the error is passed to it.
Listing 3. Throw an exception.
/**
*Execute current query
*
* Execute the current query—replacing any dot markers with the provided arguments
* .
*
* @parameters: mixed $queryParams,... query parameters
* @return: Resource A—reference describing the resource on which the query is executed. */
public function execute($queryParams = )
{
//For example: SELECT * FROM table WHERE name=:1S AND type=:2I AND level=:3N
$args = func_get_args();
if ($this->stored_procedure) {
/*Call the compile function to get the query*/
$query = call_user_func_array(array($this, compile), $args);
} else {
/*A stored procedure has not been initialized, therefore, it is executed as a standard query*/
$query = $queryParams;
}
$result = $this->db->query($query);
if (! $result) {
throw new QueryException($this);
http://www.bkjia.com/PHPjc/508484.htmlwww.bkjia.comtruehttp: //www.bkjia.com/PHPjc/508484.htmlTechArticle1. DBQuery object Now, our DBQuery object simply imitates a stored procedure. Once executed, it returns a required Save the result resource; and if you want to use the result...
|