views:

59

answers:

3

I want to be able to do something like this:

$table_object->getRows()->where($wer)->or($or)->orderBy('field', 'DESC');

If i were sure that all the methods will be called each time and in that order, then it would be simple and i can return an instance of the object itself on each method call so that the query gets build and finally executed at orderBy method. However I want the class to be able to also execute queries like so:

$table_object->getRows()->where($wer);

The following code would work for the first code example (ie when all methods are called) but not with the second one where only method where is called after getRows. It only returns an instance of itself.

class DatabaseTable extends Database
{ 
 protected $table_name;
 protected $query;

 public function getRows()
 {
  return ($this instanceof self)? $this : false;
 }

 public function where(array $where)
 {

  foreach ($where as $field => $value){
   $w[] = $field . ' = "' . $this->escapeString($value) . '"';
  }

  $this->query = "SELECT * FROM {$this->table_name} WHERE " . join($w, ' AND '));

  return $this;
 }

 public function or(array $Clause)
 {
  foreach ($clause as $field => $value){
   $o[] = $field . ' = "' . $this->escapeString($value) . '"';
  }

  $this->query .= join($w, ' AND ');

  return $this; 
 }

 public function orderBy($field, $type)
 {
  $this->query .= " ORDER BY $field $type ";
  $this->executeQuery($this->query); 
 }

}

Ignore all minor errors - (i didnt check if it worked for sure, but it should.) how can I achieve this?

+6  A: 

Don't go through that hassle of building your own when you can use Doctrine

$q = Doctrine_Query::create()
    ->from('User u')
    ->leftJoin('u.Phonenumbers p');

or Propel

$c = new Criteria();
$c->add(AuthorPeer::FIRST_NAME, "Karl");
$c->add(AuthorPeer::LAST_NAME, "Marx", Criteria::NOT_EQUAL);
$authors = AuthorPeer::doSelect($c);

or Zend_Db_Query.

  $select = $db->select()
               ->from(array('p' => 'products'),
                      array('product_id', 'product_name'))
               ->join(array('l' => 'line_items'),
                      'p.product_id = l.product_id');

If they don't suit you for whatever reason, you can use them as a starting point on how to roll your own.

Gordon
Nice examples :)
David Caunt
@David these are from the respective frameworks' documentation
Gordon
My purpose here was more to learn how its done rather then to recreate.. I ll have a look at those.
Shafee
If you immediately decided to start from scratch you learn how _you_ would do it and in all likelihood not how it's done "properly" (no offense, we're all in the same boat). Do some research, look at what others have done before ..then, maybe, roll you own implementation. Relax, and stand on the shoulders of giants for a while =]
VolkerK
I'm not sure why some developers are hesitant to write raw SQL queries. The examples above are a terrible mess.
Johannes Gorset
@FRKT They are not exactly pretty, but there are cases, when they are much less of a mess than a couple dozen lines of SQL code that needs criteria added and/or removed on the fly.
Gordon
+4  A: 

You might want to look at Zend Framework's Zend_Db_Select component, which provides an OO interface to SQL queries. Zend_Db also provides a number of other useful database functions.

David Caunt
:/ never occurred to me to have a look in there.
Shafee
A: 

As others have mentioned you shouldn't reinvent the wheel when a component already exists that can do what you want (Zend_Db_Select).

But if you still want to create your own, then one possibility is to include a Select($fields) method that is appended to the end of your query and that can take a list of fields to select or "*" for all. This select() method would be what actually executes the sql code for you. Yes, I know that it wouldn't look exactly like SQL in that the select would be at the end, but it is an easy solution to implement.

As an aside, what you are trying to do is build up a fluent interface or DSL, so it might be worth while to read up a little on them, to be see how some implementations are constructed.

Waleed Al-Balooshi