Jump to content

My second attempt with classes - Any Advice?


TeddyKiller

Recommended Posts

Recently a mate of mine bought a script off the net. In which I could of created something similar, although.. this script was amazing, and the class functionality .. it's pretty amazing. I looked at it.. it uses 3 classes. User class, DB class, and a Session class which extends User.

 

I thought.. writing out something like this on my own.. would help me with OOP. I've posted threads before about OOP. I gained a little understanding. The knowledge in which members were posting in were way advanced for my small brain.

 

I've also just got to the Objects chapter in my book, so somewhere around the next week my knowledge might start building up with OOP quite rapidly.

 

So far I've only done the DB class. (All classes will get posted in here when they get done etc)

 

I'm wondering maybe you can give advice, little tweaks and changes to make it better? The original class in the login script my mate bought, had an escape_ function, which is used instead of mysql_real_escape_string, although I have a Clean function which does all that, and more. The clean function isn't included yet.. I'll get to that a bit later.

 

To intialise the DB Class.. you'd use..

<?php
define('DB_SERVER', "localhost");
define('DB_USER', "username");
define('DB_PASS', "password");
define('DB_NAME', "dbname");
  
define("COOKIE_EXPIRE", 60 * 60 * 24 * 60); //60 days by default
define("COOKIE_PATH", "/");
  
require_once("db.php");
  
$db = new Database(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
$db->connect();
?>

 

db.php, is what includes the class.

<?php
class Database {
    var $server = ""
    var $user = ""
    var $pass = "";
    var $database = "";
    var $affected_rows = 0;
    var $link_id = 0;
    var $query_id = 0;

    /* Database::__construct() */
    function __construct($server, $user, $pass, $database) {
        $this->server = $server;
        $this->user = $user;
        $this->pass = $pass;
        $this->database = $database;
    }
      
    /* Database::connect() - Connect and select database using vars above */
    function connect() {
        $this->link_id = $this->connect_db($this->server, $this->user, $this->pass);
          
        if (!$this->link_id) :
            print '<div style="text-align:center">' .
                '<span style="padding: 5px; border: 1px solid #999; background-color:#EFEFEF; ' . 
                    'font-family: Verdana; font-size: 11px; margin-left:auto; margin-right:auto">' . 
                '<b>Database Error:</b>Connection to Database ' . $this->database . ' Failed</span></div>';
        endif;
        
        if (!$this->select_db($this->database, $this->link_id)) :
            print '<div style="text-align:center">' . 
                '<span style="padding: 5px; border: 1px solid #999; background-color: #EFEFEF; ' . 
                    'font-family: Verdana; font-size: 11px; margin-left:auto; margin-right:auto">' . 
                '<b>Database Error:</b>mySQL database (' . $this->database . ')cannot be used</span></div>';
        endif;
        
        $this->query("SET NAMES 'utf8'", $this->link_id);
        $this->query("SET CHARACTER SET 'utf8'", $this->link_id);
          
        unset($this->password);
    }

    /* Database::connect_db() */
    function connect_db($server, $user, $pass)
    {
        return mysql_connect($server, $user, $pass);
    }
      
    /* Database::select_db() */
    function select_db($database, $link_id) {
        return mysql_select_db($database, $link_id);
    }
      
    /* Database::query() - Executes SQL query to an open connection */
    function query($sql) {
        if (trim($sql != "")) :
            $this->query_id = mysql_query($sql, $this->link_id);
        endif;
          
        if (!$this->query_id) :
            print "mySQL Error on Query : " . $sql;
        endif;
          
        return $this->query_id;          
    }
      
      
    /* Database::fetch() - Fetches and returns results one line at a time */
    function fetch($query_id = -1) {
        if ($query_id != -1) :
            $this->query_id = $query_id;
        endif;
          
        if (isset($this->query_id)) :
            $record = mysql_fetch_array($this->query_id, MYSQL_ASSOC);
        else :
            print "Invalid query_id: <b>".$this->query_id."</b>. Records could not be fetched.";
        endif;
        
        return $record;
    }
      
    /* Database::affected() - Returns the number of affected rows */
    function affected() {
        return mysql_affected_rows($this->link_id);
    }

    /* Database::fetchrow() - Fetches one row of data */
    function fetchrow($query_id = -1) {
        if ($query_id != -1) :
            $this->query_id = $query_id;
        endif;
        
        $this->fetch_row = mysql_fetch_row($this->query_id);
        return $this->fetch_row;
    }
      
    /* Database::close() - close the connection */
    function close() {
        if (!mysql_close($this->link_id)) :
            $this->error("Connection close failed.");
        endif;
    }
  }
?>

 

When connected, to do a query, you'd do something like this..

$query = $db->query("select * from users");

 

What do you think of this code? They may be some errors.. but feel free to point them out and fix them :)

All is appreciated!

Link to comment
Share on other sites

define("COOKIE_EXPIRE", 60 * 60 * 24 * 60);

 

No matter how many times you calculate 60 * 60 * 24 * 60 the result will always be 5184000, so write it! Instead of needlessly calculating it on each new request.

 

Drop the use of var instead use the proper access modifiers like private.

 

Don't interweave PHP with HTML, don't return HTML from functions/methods, don't allow functions to output to screen.

 

Typo if (trim($sql != "")) will result in if (trim(true)) you quite possibly want if (trim($sql) != '')

 

The class looks good overall probably due to the earlier example you had a look at.

Link to comment
Share on other sites

Thanks for the response.

 

No matter how many times you calculate 60 * 60 * 24 * 60 the result will always be 5184000, so write it!

Done, but changed it to 31536000 for 365 days.

 

Drop the use of var instead use the proper access modifiers like private.

Okay, what is the difference by the way?

 

Don't interweave PHP with HTML

Is there a reason for this? If I wanted HTML output to be printed.. what would the method be?

Link to comment
Share on other sites

Your class is under the assumption it is being used inside a web browser.  Such will not always be the case.  Therefore your class should resort to more generic methods of reporting errors, such as trigger_error(), logging, or a pub/sub system.  Then whichever container (or application) uses your class can determine the appropriate method of handling or reporting errors.

Link to comment
Share on other sites

Thank you roopurt18 although I'm not quite sure what you mean?

 

Here is the class now, with the changing of vars to privates. Not sure if I've got it correct though.

<?php
class Database {
    private $server = "";
    private $user = "";
    private $pass = "";
    private $database = "";
    private $affected_rows = 0;
    private $link_id = 0;
    private $query_id = 0;

    /* Database::__construct() */
    function __construct($server, $user, $pass, $database, $affected_rows, $link_id) {
        $this->server = $server;
        $this->user = $user;
        $this->pass = $pass;
        $this->database = $database;
        $this->affected_rows = $affected_rows;
        $this->link_id = $link_id;
    }
      
    /* Database::connect() - Connect and select database using vars above */
    function connect() {
        $this->link_id = $this->connect_db($this->server, $this->user, $this->pass);
          
        if (!$this->link_id) :
            print '<strong>Database Error:</strong>Connection to Database (' . $this->database . ') Failed';
        endif;
        
        if (!$this->select_db($this->database, $this->link_id)) :
            print '<strong>Database Error:</strong>mySQL database (' . $this->database . ') cannot be used';
        endif;
        
        $this->query("SET NAMES 'utf8'", $this->link_id);
        $this->query("SET CHARACTER SET 'utf8'", $this->link_id);
          
        unset($this->password);
    }

    /* Database::connect_db() */
    function connect_db() {
        return mysql_connect($this->server, $this->user, $this->pass);
    }
      
    /* Database::select_db() */
    function select_db() {
        return mysql_select_db($this->database, $this->link_id);
    }
      
    /* Database::query() - Executes SQL query to an open connection */
    function query($sql) {
        if (trim($sql) != "") :
            $this->query_id = mysql_query($sql, $this->link_id);
        endif;
          
        if (!$this->query_id) :
            print "mySQL Error on Query : " . $sql;
        endif;
          
        return $this->query_id;          
    }
      
      
    /* Database::fetch() - Fetches and returns results one line at a time */
    function fetch($query_id = -1) {
        if ($query_id != -1) :
            $this->query_id = $query_id;
        endif;
          
        if (isset($this->query_id)) :
            $record = mysql_fetch_array($this->query_id, MYSQL_ASSOC);
        else :
            print "Invalid query_id: <b>".$this->query_id."</b>. Records could not be fetched.";
        endif;
        
        return $record;
    }
      
    /* Database::affected() - Returns the number of affected rows */
    function affected() {
        return mysql_affected_rows($this->link_id);
    }

    /* Database::fetchrow() - Fetches one row of data */
    function fetchrow($query_id = -1) {
        if ($query_id != -1) :
            $this->query_id = $query_id;
        endif;
        
        $this->fetch_row = mysql_fetch_row($this->query_id);
        return $this->fetch_row;
    }
      
    /* Database::close() - close the connection */
    function close() {
        if (!mysql_close($this->link_id)) :
            $this->error("Connection close failed.");
        endif;
    }
}
?>

Link to comment
Share on other sites

I mean that when your class fails it is printing error messages that include markup; therefore your class is under the assumption that PHP has been invoked under a web server.  But what if you decide to use your class for a console application?  It's going to print a bunch of error messages that are difficult to read.

 

Also, if your class is being used in a web server application, then you don't want it to print things to the browser.  Your class needs to notify to the application, "Hey, something didn't work!" and then the application will decide what to do with it, either logging it, printing error messages, sending e-mails, or whatever else.

 

The job of your DB class is to connect to the database, run queries, etc. but not to print things to the screen.

Link to comment
Share on other sites

Your Database class is an improvement over the last you posted, but still can be made better. Add the access modifier public to any methods you wish to use in the main program and mark all others private. In the future it's possible you want to extend your Database class, but extending your Database class and overwriting it's behavior makes all that private stuff obsolete and makes for overhead as you can't access it from the child class. To avoid this we create an interface with the behavior we expect (the function's you call in your main program).

 

If we take another great look at your Database class we notice it actually performs 3 tasks:

 

1) connect to a database

2) handle results

3) handle queries

 

The Single-Responsibility Principle states that every class should have only one reason to change. Therefor we divide your big Database class into:

 

MySQL Interface

-------------------------

MysqlQuery -- handles select/insert/update/delete queries or MysqlQueryBuilder objects, returns MysqlResult

MysqlResult -- returned by a MysqlQuery object, performs operations on a result (handles num_rows & affected_rows in a universal way)

MysqlConnect -- connects to the database

[MysqlQueryBuilder -- creates select/insert/update/delete queries, implements __toString()]

 

This is specific to MySQL you can extend it or modify it to make it more universal.

 

Usage:

 

$con = new MysqlConnect('mysql://ignace:password@localhost:3601/database');
//creates mysql_connect($host, $username, $password, true/*$new_link*/)
$q = new MysqlQuery('SELECT * FROM table', $con);
$r = $q->execute(/*$query = null*/);
print $r->getRowCount();
while ($row = $r->fetchRow(/*$mode = MYSQL_ASSOC*/)) {
  print_r($row);
}

$con2 = new MysqlConnect('mysql://ignace:password2@localhost:3602/database2');
$sql = new MysqlQueryBuilder();
$r = $q->execute($sql->insert($data)->into('table'));
print $r->getRowCount();//num_rows & affected_rows universal accessor

Link to comment
Share on other sites

Hmm.. So.. what you're saying is, create an interface, Like below (For basics)

<?php
interface Mysql_Interface {
    class MysqlConnect {
        private $username;
        private $pass;
        private $server;
        private $database;

        public function __construct($username, $pass, $server, $database) {
            // Construct $this->name as $name
        }

        public function db_connect() {
           // Connect to database
        }

        public function db_select() {
           // Select database
        }
    }

    class MysqlQuery {
         
         public function execute($query) {
               return mysql_query($query);
         }

         // More functions
    }

    // More classes
}
?>

 

No quite sure I fully understand... I haven't managed to understand interfaces in noob language yet.

 

Thanks

Link to comment
Share on other sites

I'll provide an example to explain interface's, take your class Database for example it utilizes mysql_* functions imagine now that your client uses mssql so you could re-write it or you could extend it, like:

 

class DatabaseMsSQL extends Database {}

 

Which would be dumb because if you now forget to implement one method using mssql your application would fall back to mysql leading to serious errors, so you re-wrote it.

 

You now have 2 classes both named Database but a varying implementation and you can't call them both, the below for example will fail:

 

require('mysql/database.php');
require('mssql/database.php');

 

Now a new client comes along which has - you guessed it - 2 database servers one in mysql and one in mssql both used for their specific features (to keep it optimized). This is just a fictive example of course but it is possible. Anyway so you rename both classes you name one MySQL and the other MsSQL and you can include both.

 

The client is pleased with your work and now want some new functionality added one that will require you to pass the $db object (either MsSQL or MySQL) to a method that will act upon it's result and return some stuff.

 

This doesn't work:

 

public function someFunction(MySQL $m) {}
public function someFunction(MsSQL $m) {}

 

You could do of course (as PHP does not require a type to be specified):

 

public function someFunction($m) {}

 

But how will you know it will be a MsSQL or MySQL object?

 

if ($m instanceof MySQL || $m instanceof MsSQL)

 

But what if the user also adds a Oracle database?

 

if ($m instanceof MySQL || $m instanceof MsSQL || $m instanceof Oracle)

 

And what if multiple methods require a database object? You can't possibly write all that code and modify it every time a new database is introduced???

 

So, we create an interface like:

 

interface Database {
  public function query($sql);
  ..
}

 

Our method will hold:

 

public function someFunction(Database $d) {}

 

And our classes MySQL, MsSQL, and Oracle will implement this interface:

 

class MySQL implements Database

 

Now we can pass any class that implements Database to someFunction() without having to worry it wouldn't have a query() method.

 

I hope this explained it well, I have tried to keep it as simple as possible using various (im)possible scenario's

Link to comment
Share on other sites

define("COOKIE_EXPIRE", 60 * 60 * 24 * 60);

 

No matter how many times you calculate 60 * 60 * 24 * 60 the result will always be 5184000, so write it! Instead of needlessly calculating it on each new request.

 

Getting rid of three multiplication operations will not save you a whole bunch of time (especially with APC or similar service), and in this form it is more readable. You can see it's 60 days at first sight, while 5184000 is somewhat enigmatic.

Link to comment
Share on other sites

I'm of opinion every second of my life should be used optimally.

Comments or no comments, if I want to change this time from 60 to 90 days, I'd prefer not to use a calculator for that.

 

This is not to say, it cannot be done better

define('SECONDS_IN_DAY',86400);
$timeout = 60 * SECONDS_IN_DAY;

for example

Link to comment
Share on other sites

Ignace.. thank you. I understood alright till about half way through.

if ($m instanceof MySQL || $m instanceof MsSQL)

That would mean.. if $m is an instance of MySQL(Class) or an instance of MsSQL(Class), Correct?

 

So, if that statement returns true, how would it know which class to use?

 

Would interface database, hold the connection? If so... how would it know whether to connect to mysql, or mssql, etc?

 

For the query function, how would that be done? becaues for mysql, it's mysql_query, but adding in mssql, would be mssql_query. How would it know which to use?

 

I think I'm only confused because there wasn't a possible example, it was snippets in which I couldn't quite work out how it'd go.

All that I've got in my head.. is like below.

db.php

interface Database {
    public function execute($sql) {
          //What would go here to see which to use, mysql_query, or mssql_query etc
    }
    
    //Other functions
}

 

other file.php

class mysql implements Database {
      // some functions? What functions?
}

class mssql implements Database {
     // some functions? what functions?
}

 

Am I getting closer to what you mean, or am I just.. floating away?

 

Thanks

Link to comment
Share on other sites

So, if that statement returns true, how would it know which class to use?

 

It wouldn't make a decision it just used that line to verify that it's either of those classes and not SomeObject. MsSQL and MySQL share both the same functions (with a varying implementation mysql_* vs mssql_*).

 

Would interface database, hold the connection?

 

Not the interface but the implementing class.

 

interface Database {
  public function execute($query);
}

class MySQL implements Database {
  private $connection;
  
  public function execute($query) {
    return mysql_query($query, $this->connection);
  }
}

 

Your interface is actually your "validator" (if ($m instanceof MySQL || ..)

 

public function someFunction(Database $d) {
  return $d->execute('SELECT * FROM table');
}

 

I could use this function like this:

 

$o->someFunction(new MySQL());
$o->someFunction(new MsSQL());
$o->someFunction(new Oracle());

 

And it would all work as I know each of these (MySQL, MsSQL, Oracle) implement a execute() method as the interface Database said they should, and if they didn't an exception is thrown.

 

I couldn't for example do:

 

$o->someFunction(new SomeObject());

 

As SomeObject does not implement the Database interface and may therefor not have an execute() method (or has a different order of it's parameters) which I need in the someFunction() method.

Link to comment
Share on other sites

interface Database {
  public function execute($query);
}

class MySQL implements Database {
  private $connection;
  
  public function execute($query) {
    return mysql_query($query, $this->connection);
  }
}

Thanks.. it's closer to what my understanding it. I built upon it. Upon calling it, you'd pass the username password server and database through. It'll connect it, and it'll enable you to do queries. (I assuming using $db->execute)

 

I'm not sure if I'm correct with it though. You'll have to correct it .. and explain why it was wrong.

Then would you give an example on how to use it? So.. the interface etc will be in a file called..myfile.php, and that'd be require_once in a file called config. So it'll be like this..

 

config.php

<?php 
$server = 'localhost';
$username = 'username';
$password = 'password';
$database = 'database';

require_once("myfile.php");
?>

 

myfile.php (Built upon version of what you gave, could be wrong)

<?php
interface Database {
   public function __construct($server, $username, $password, $database);
   function connect();
   function connect_db();
   function select_db();
   public function execute($query);
}

class MySQL implements Database {
   private $server;
   private $username;
   private $password;
   private $database;
   
   private $connection;
   
   public function __construct($server, $username, $password, $database) {
      $this->server = $server;
      $this->username = $username;
      $this->password = $password;
      $this->database = $database;
   }
   
    function connect() {
        $this->connection = $this->connect_db($this->server, $this->usernname, $this->password);
          
        if (!$this->connection) print '<strong>Error:</strong> Connection to Database Failed';
      
        if (!$this->select_db($this->database, $this->connection)) print '<strong>Error:</strong> Cannot select Database';
      
        $this->query("SET NAMES 'utf8'", $this->connection);
        $this->query("SET CHARACTER SET 'utf8'", $this->connection);
          
        unset($this->password);
    }

    function connect_db() {
        return mysql_connect($this->server, $this->username, $this->password);
    }
     
    function select_db() {
        return mysql_select_db($this->database, $this->connection);
    }
   
   //Query functions
   public function execute($query) {
      return mysql_query($query, $this->connection);
   }
}
?>

 

So from this.. in config.php how would I connect to the database?

Then in a seperate file.. myfile2.php, if I wanted to do a query.. what would it be?

 

So basically. setting it up so it'd pretty much work with a connection, and query. Once I understand how to use, and get them working.. I can start putting in other bits like my database class in the original post contains.

 

Thanks. I'm getting closer :D

Link to comment
Share on other sites

What you gave as an example is indeed correct although I would add the access modifier for all methods, like

 

interface Database {
   public function __construct($server, $username, $password, $database);
   public function connect();
   public function connect_db();
   public function select_db();
   public function execute($query);
}

 

From this point you can move towards a more SRP (Single-Responsibility Principle) friendly design?

 

DatabaseQuery

DatabaseResult

DatabaseConnect

DatabaseQueryBuilder

 

Learn more about this in the Doctrine 2.0 API and take a peek in Zend framework 1.10 API for more information about design patterns and (H)MVC architecture.

Link to comment
Share on other sites

What you gave as an example is indeed correct

Wow.. I'm suprised. I made those changes with the access modifiers. Although as my previous post said, how would I use it? Like.. how would I connect to the database in config.php, then how would I do a query?

 

From this point you can move towards a more SRP (Single-Responsibility Principle) friendly design?

DatabaseQuery

DatabaseResult

DatabaseConnect

DatabaseQueryBuilder

I just had a quick read of the PHP Freaks tutorial: 00 PHP Part 2. Scrolled down to the SRP... and it talks about responsibilities, it highly confuses me. You might have to give a little example changing my example.. to a more SRP desgn.

 

Learn more about this in the Doctrine 2.0 API and take a peek in Zend framework 1.10 API for more information about design patterns and (H)MVC architecture.

I had a look at the Zend Framework not long ago. Got it installed and it.. well, it didn't make sense to me at all. I thought i'll enhance my knowledge a bit more before going onto Zend. I'll read up more about Zend and Doctrine, find out more about what it is before allowing my knowledge to expand - This will give me an idea of what I'm getting myself into.

 

Ontop of that, possibly taking my example, if I created another class for MsSQL, how would I choose what was used for the database access.

 

Though it would be greatly appreciate if you can get my example up and running.. with like I stated initializing new connection to the database, and doing a query.

 

Thanks for taking time to help me!

Link to comment
Share on other sites

Like.. how would I connect to the database in config.php, then how would I do a query?

 

Just like this:

 

require_once('config.php');
$db = new MySQL($config['host'], ..);
$r = $db->execute('SELECT * FROM table');

 

Of course you really shouldn't do this if you want your application to be able to use multiple DBMS systems (like MySQL and MSSQL) It would therefor be better to use a Factory pattern or Builder pattern, like:

 

require_once('config.php');
$db = DatabaseConnect::factory($config['db1']['scheme']);//mysql://ignace:password@localhost:3610/database
$query = new DatabaseQueryBuilder();
$insert = $query->insert($data)->into('table');

 

You don't have to worry just yet about the above code.

 

Scrolled down to the SRP... and it talks about responsibilities

 

Yup, to make sure every class does just one thing and one thing only. This makes that the class has a high-cohesion (other name for little number of methods) and adheres to the separation of concerns (the class minds his own business and is only told on a need-to-know basis)

 

if I created another class for MsSQL, how would I choose what was used for the database access.

 

How do you mean? mssql_* of course? Or do you mean the methods it would possess? All those defined in the Database interface of course.

Link to comment
Share on other sites

Just like this:

 

require_once('config.php');
$db = new MySQL($config['host'], ..);
$r = $db->execute('SELECT * FROM table');

Ah. Yeah that isn't hard. I thought of that.. but then I thought.. well there is an interface, it would be different.

 

Yup, to make sure every class does just one thing and one thing only.

Ah! That makes my brain understand.

 

if I created another class for MsSQL, how would I choose what was used for the database access.

How do you mean? mssql_* of course? Or do you mean the methods it would possess? All those defined in the Database interface of course.

I mean.. my application to be able to use multiple DBMS systems. How would that work exactly? I can only connect to one DBMS at a time (Correct me if wrong) so that means.. if I had multiple DBMS systems, only one can be used. How can that be chosen so that .. the chosen one is used.

Link to comment
Share on other sites

I mean.. my application to be able to use multiple DBMS systems.

 

You would use a Abstract Factory- (or Factory Method) and Adapter pattern, like:

 

class DatabaseAdapterFactory {
  public static function factory($adapterName) {
    //@returns any child of DatabaseAdapter
  }
}

abstract class DatabaseAdapter {}

class MySQLAdapter extends DatabaseAdapter {}

 

In your program you would use it like:

 

$adapter = DatabaseAdapterFactory::factory('mysql://ignace:password@localhost:3610/database');

 

The 'mysql://..' comes from your config.php (you parse it with parse_url)

Link to comment
Share on other sites

Hm.. so working with what I have at the moment, the interface, and the class MySQL. Then calling it through the config.php, and using the queries... what would I change to put it into a factory method?

class DatabaseAdapterFactory {
  public static function factory($adapterName) {
    //@returns any child of DatabaseAdapter
  }
}

Would factory() choose the right class to use? (MySQL Adapter, etc)

 

abstract class DatabaseAdapter {}

What would go here...?

 

class MySQLAdapter extends DatabaseAdapter {}

Is this the equivalent to what I have class MySQL implements Database {

So I wouldn't be using an interface no more?

 

Link to comment
Share on other sites

Would factory() choose the right class to use? (MySQL Adapter, etc)

 

That's the idea :)

 

What would go here...?

 

It's possible that your adapters will share certain common functionality, these should go in the abstract class. If you don't have any common functionality skip the abstract class and use the interface instead.

 

interface DatabaseAdapterInterface {
  const MODE_NUM = 1;
  const MODE_ASSOC = 2;
  const MODE_BOTH = 3;
  
  public function connect();
  public function disconnect();
  public function query($sql);
  public function fetchAll($mode = self::MODE_ASSOC);
  public function fetchRow($mode = self::MODE_ASSOC);
}

abstract class DatabaseAdapterAbstract implements DatabaseAdapterInterface {
  public function fetchAll($mode = self::MODE_ASSOC) {
    $rows = array();
    while ($row = $this->fetchRow($mode)) {
      $rows[] = $row;
    }
  }
}

class MySQLAdapter extends DatabaseAdapterAbstract {
  //@see DatabaseAdapterInterface
}

class MsSQLAdapter extends DatabaseAdapterAbstract {
  //@see DatabaseAdapterInterface
}

 

The fetchAll does not use any specifics (mysql_* or mssql_*) and can therefor be used as an abstraction as the implementation most likely won't change in child classes

Link to comment
Share on other sites

... That looks hot. I think I understand. $this->fetchRow($mode) Is this defined in the abstract class or would it be in the Adapters? I'm yet again.. confused.

 

Where did the factory go aswell? I'm really confused.. You might have to nip it all in for me.. or atleast do some of it so I can learn from the rest. I appreciate what you've given me.. although all your posts seem to be.. slightly different? A factory comes in, and then it disappears. It's confusing me alot.

 

Here is what I have.. the near enough complete version of my DB class/interface. - I haven't tested it yet. - Though I don't see a reason for it not to work.. unless its just a typo some where.

<?php
interface Database {
   public function __construct($server, $username, $password, $database);
   public function connect();
   public function connect_db();
   public function select_db();
   public function execute($sql);
   public function fetcharray($query = -1);
   public function fetchassoc($query = -1);
   public function fetchrow($query = -1);
   public function numrows($query = -1);
   public function close();
   
}

class MySQL implements Database {
   private $server = "";
   private $username = "";
   private $password = "";
   private $database = "";
   
   private $connection = "";
    
   /* Construct variables .. thing */
   public function __construct($server, $username, $password, $database) {
      $this->server = $server;
      $this->username = $username;
      $this->password = $password;
      $this->database = $database;
   }
      
   /* Connect to database and select database */
    public function connect() {
        $this->connection = $this->connect_db($this->server, $this->usernname, $this->password);
          
        if (!$this->connection) print '<strong>Error:</strong> Connection to Database Failed';
      
        if (!$this->select_db($this->database, $this->connection)) print '<strong>Error:</strong> Cannot select Database';
      
        $this->query("SET NAMES 'utf8'", $this->connection);
        $this->query("SET CHARACTER SET 'utf8'", $this->connection);
          
        unset($this->password);
    }
   
   /* Connect to the database */
    public function connect_db() {
        return mysql_connect($this->server, $this->username, $this->password);
    }
     
   /* Select the database */
    public function select_db() {
        return mysql_select_db($this->database, $this->connection);
    }
   
    /* Perform mysql_query */
   public function execute($sql) {
      if (trim($sql) != "") : $this->query_id = mysql_query($sql, $this->connection); endif;
      
      if (!$this->query_id) : print "MySQL Error on Query : " . $sql; endif;
      
         return $this->query_id;
   }
   
   /* Perform mysql_fetch_array */
   public function fetcharray($query_id = -1) {
        if ($query_id != -1) : $this->query_id = $query_id; endif;
          
        if (isset($this->query_id)) :
            $record = mysql_fetch_array($this->query_id, $this->connection);
        else :
            print "Invalid query_id: <b>".$this->query_id."</b>. Records could not be fetched. (fetch_assoc)";
        endif;
      
        return $record;
    }
   
   /* Perform mysql_fetch_assoc */
   public function fetchassoc($query_id = -1) {
        if ($query_id != -1) : $this->query_id = $query_id; endif;
          
        if (isset($this->query_id)) :
            $record = mysql_fetch_assoc($this->query_id, $this->connection);
        else :
            print "Invalid query_id: <b>".$this->query_id."</b>. Records could not be fetched. (fetch_assoc)";
        endif;
      
        return $record;
    }
   
   /* Perform mysql_fetch_row */
   public function fetchrow($query_id = -1) {
        if ($query_id != -1) : $this->query_id = $query_id; endif;
      
      if (isset($this->query_id)) :
           $record = mysql_fetch_row($this->query_id, $this->connection);
      else :
         print "Invalid query_id: <b>".$this->query_id."</b>. Records could not be fetched. (fetch_row)";
      endif;
      
        return $record;
    }
   
   /* Perform mysql_num_rows */
   public function numrows($query_id = -1) {
        if ($query_id != -1) : $this->query_id = $query_id; endif;
      
      if (isset($this->query_id)) :
           $record = mysql_num_rows($this->query_id, $this->connection);
      else :
         print "Invalid query_id: <b>".$this->query_id."</b>. Could not count rows (num_rows)";
      endif;
      
        return $record;
   }
   
   /* Close the connection */
   public function close() {
      if (!mysql_close($this->connection)) : print "Connection close failed."; endif;
    }
   
}
?>

Could you please assist me more in what I'm actually suppose to do? You are helping though.. but at the same time, I just don't understand :P

Link to comment
Share on other sites

I think I understand. $this->fetchRow($mode) Is this defined in the abstract class or would it be in the Adapters?

 

Because fetchRow contains no adapter specific code (in ignace's examples) it can go within the abstract definition.

 

Where did the factory go aswell? I'm really confused..

 

The factory would be a standalone class responsible for returning an adapter implementation based on whatever config options you passed it.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.