August 28, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

PHP 5 OOP: Protecting Data With Visibility

  • May 10, 2006
  • By Adam Delves
  • Send Email »
  • More Articles »

The Compile Function

The next task is to build the compile() and execute() functions.

The compile() function is shown in Listing 3. It will:

  • Take a variable number of arguments; which match the placeholders in the query.
  • Check that the placeholder is of the correct data type and substitute it for the value in the argument.
  • Return the query as a string but does not execute it.
  • Throw an exception if the query object has not been initialized as a stored procedure using the prepare() function.

Listing 3: The compile() function
/** 
     * Returns the compiled query without executing it. 
     * @param mixed $args,... Query Parameters 
     * @return string Compiled Query 
     */ 
    public function compile($params) 
    { 
        if (! $this->stored_procedure) { 
            throw new Exception("Stored procedure has not been initialized."); 
        } 

        /* substitute parameters */ 
        $params = func_get_args(); // get function arguments 
        $query = preg_replace("/(?compile_callback($params, 1, "2")', $this->query); 

        return $this->add_strings($query); // put the strings back into the query 
    } 
     
    /** 
     * Re-inserts strings removed by the prepare() function. 
     */ 
    private function add_strings($string) 
    { 
        $numbers = array_keys($this->query_strings); 
        $count = count($numbers); 

        $searches = array(); 

        for($x = 0; $x < $count; $x++) { 
            $searches[$x] = "$||${$numbers[$x]}"; 
        } 

        return str_replace($searches, $this->query_strings, $string); 
    } 

    /** 
     * Executed each time a place holder is substituted in the stored procedure. 
     */ 
    protected function compile_callback($params, $index, $type) 
    {         
        --$index; 

        /* throw an exception */ 
        if (! isset($params[$index])) { 
            throw new Exception("Required number of arguments not sent to stored procedure."); 
        } 
         
        /* you may want to add additional types such as dates and times here */ 
        switch ($type) { 
            case 'S': 
                return '"' . $this->db->escape_string($params[$index]) . '"'; 
                break; 
            case 'I': 
                return (int) $params[$index]; 
                break; 
            case 'N': 
                return (float) $params[$index]; 
            default: 
                throw new Exception("Unrecognized data type '$type' specified in stored procedure."); 
        } 
    } 

The compile() function uses two additional functions. The compile_callback() function is used as a callback in the preg_replace() function call. It is executed each time a place holder is found in the query replacing the place holder with the value in passed to the compile function.

The Execute Function

Finally, you need to build the execute() function. The execute() function compiles the query and then executes it using the DB object which was used to initialize the DBQuery object, notice in Listing 4 how the call_user_func_array() function is used to get the compiled query, this is used because the number of arguments passed to the execute function cannot be determined until runtime.

Listing 4: The execute() function


/** 
     * Executes the current Query 
     * 
     * Executes the current query replacing any place holders with the supplied 
     * parameters. 
     * 
     * @param mixed $queryParams,... Query parameter 
     * @return resource A reference to the resource representing the executed query. 
     */ 
    public function execute($queryParams = '') 
    { 
        //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 was not initialized, so execute this as a standard query */ 
            $query = $queryParams; 
        } 
             
        $this->result = $this->db->query($query); 

        return $this->result; 
    } 

The complete source for the query object may be found as an attachment at the end of this article. Remember that you are reinventing a very simplistic version of the wheel here, as stored procedures and database abstraction has already been addressed by the PearDB PHP extension.

Pulling it all Together - A short Example

To demonstrate how the query object may be used, I have constructed a small example that uses the DBQuery object as a stored procedure in checking for a correct user name and password. This is shown in listing 5.

Listing 5: A short example

require 'mysql_db.php5'; 
    require_once 'query2.php5'; 


    $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'); 

    if ($result = $query->execute("visualad", "apron", time())) { 
        if ($db->num_rows($result) == 1) { 
            echo('Correct Credentials'); 
        } else { 
            echo('InCorrect Credentials / Session Expired'); 
        } 
    } else { 
        echo('Error executing query: ' . $db->error()); 
    } 

Conclusion

In this article you have seen how to protect and restrict the visibility of object data using the accessibility modifiers private, protected and public when declaring class variables. These modifiers are used in the MysqlDB and DBQuery classes to protect data important to the internal workings of the objects.

In our next article I'll present another new feature in PHP 5, type hinting. You will also get to extend the DBQuery to allow for support of all the functions in the DB interface that operate on the result of an executed query. This will be accomplished using delegation.

If you have any comments regarding this tutorial please post them here.

Downloads

You can download the query.zip file here.

About the Author

Adam Delves is a university student and web programmer from the UK who is studying computing. He has been a PHP programmer for over 3 years and now runs two small websites and writes articles for PHP builder.com.



Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel