Zend Framework Models

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
noondaysun
Forum Newbie
Posts: 4
Joined: Tue Oct 28, 2008 9:04 am

Zend Framework Models

Post by noondaysun »

It seems to me that I'm writing a hell of a lot of repetitive code in the models directory. Each model provides an interface to a specific database table and any associated tables right. But the actual classes are mere copies of one another bar protected $_name references a different table and if I have defined any convenience methods to make database queries simpler for me. Here is one of my model classes:

Code: Select all

 
<?php
/** Class::Industry
    * @author Feighen Oosterbroek
    * @author feighen@noondaysun.org
    * @copyright 2008 onwards Feighen Daniel Oosterbroek ta Noon Day Sun Programming
    * @license Creative Commons BSD license
    * @license http://creativecommons.org/licenses/BSD/ -> Summary License
    * @license http://opensource.org/licenses/bsd-license.php
*/
class Industry extends Zend_Db {
    //: Variables
    protected $_name = "industry";
    
    //: Public Functions
    /** Industry::create($data)
        * insert Data into the database
        * @param array $data data to insert
        * @return array results on success false otherwise
    */
    public function create(array $data) {
        $registry = Zend_Registry::getInstance();
        $config = $registry->get("config");
        $db = parent::factory($config->database);
        
        $data["create_at"] = date("U");
        $data["update_at"] = date("U");
        $data["authorid"] = $config->user->id;
        if (($db->insert($this->_name, $data)) === false) {
            return false;
        }
        return self::read(array("id"=>$db->lastInsertId()));
    }
    
    /** Industry::delete($data)
        * delete Data from the database
    */
    public function delete($where) {
        $registry = Zend_Registry::getInstance();
        $config = $registry->get("config");
        $db = parent::factory($config->database);
        
        if (($db->delete($this->_name, $where)) === false) {
            return false;
        }
        return true;
    }
    
    /** Industry::fetch($data)
        * fetch Data from the database
        * @param $qry[fields] string sql field list
        * @param $qry[from] string sql table list
        * @param $qry[where] string sql where statement
        * @param $qry[group] string sql group by statement 
        * @param $qry[having] string sql having statement
        * @param $qry[order] string sql order by statement
        * @param $qry[limit] int sql limit
        * @param $qry[start_row] int sql offset
        * @return array results on success, false on failure
    */
    public function read(array $data) {
        $registry = Zend_Registry::getInstance();
        $config = $registry->get("config");
        $db = parent::factory($config->database);
        
        # first check to see if $qry[fields] isset
        # second check to see if $qry[from] isset
        if (!isset($data["fields"]) || !$data["fields"]) {$data["fields"] = "*";}
        if (!isset($data["from"]) || !$data["from"]) {$data["from"] = $this->_name;}
        
        # we need to generate the qry_string
        $qry_str = (string)"select ".$data["fields"];
        $qry_str .= " from ".$data["from"];
        $qry_str .= " where 1=1";
        if (isset($data["where"]) && $data["where"]) {
            $qry_str .= " and ".$data["where"];
        }
        if (isset($data["id"]) && $data["id"]) {
            $qry_str .= " and id=".$data["id"];
        }
        if (isset($data["group"]) && $data["group"]) {
            $qry_str .= " group by ".$data["group"];
        }
        if (isset($data["having"]) && $data["having"]) {
            $qry_str .= " having ".$data["having"];
        }
        if (isset($data["order"]) && $data["order"]) {
            $qry_str .= " order by ".$data["order"];
        }
        if (isset($data["limit"]) && $data["limit"]) {
            $qry_str .= " limit ".$data["limit"];
            if (isset($data["start_row"]) && $data["start_row"]) {
                $qry_str .= " offset ".$data["start_row"];
            }
        }
        if (($stmt = $db->query($qry_str)) === false) {
            return false;
        }
        
        $func = isset($data["id"]) && $data["id"] ? "fetchRow" : "fetchAll";
        return $stmt->$func();
    }
    
    /** Industry::update($data, $where)
        * fetch Data from the database
    */
    public function update(array $data, $where) {
        $registry = Zend_Registry::getInstance();
        $config = $registry->get("config");
        $db = parent::factory($config->database);
        
        $data["update_at"] = date("U");
        if (($db->update($this->_name, $data, $where)) === false) {
            return false;
        }
        
        return self::read(array("where"=>$where));
    }
}
 
My question is this. Why not just create a single model that does all the database queries in a generic format. So, for instance, I would create a setter function for $_name. Would that break all MVC patterns? Is it a better method of coding on the framework to create multiple models doing, essentially, the same thing. Seems to me that this way violates DRY methods, for obvious reason.
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: Zend Framework Models

Post by Eran »

You should probably take a look at Zend_Db_Table.

I also wrote a post some time ago about integrating it with more common model code (data validation / filtering) which might be useful to you - http://www.techfounder.net/2008/05/21/m ... rk-part-2/
noondaysun
Forum Newbie
Posts: 4
Joined: Tue Oct 28, 2008 9:04 am

Re: Zend Framework Models

Post by noondaysun »

Whichever way you do it it seems to be a lot of fairly repetitive coding for the models themselves. Was thinking of using a genericTable which extends either Zend_Db_Table_Abstract or Zend_Db, and then genericModel which extends genericTable.
My thoughts on this would be that it would retrieve the table info via a describe table call which would then be looped through for all the required class variables $_primary etc. Just not too sure about how to set up the referenced tables arrays yet. Know that the foreign keys can be retrieved. In terms of the framework would this be a good thing to try and implement or not? Thinking of extending Zend_Tool to create this type of generic model, structure. It would certainly make creating a new project from scratch easier for some
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: Zend Framework Models

Post by Eran »

Not sure what you mean by that. In your code you used Zend_Db directly, and repeated a lot of code that already exists in Zend_Db_Table. Some things you have to set up - the table name, and declaring the relationships if you want, but I wouldn't call those repetitive since they change from model to model. As you can see in the examples I gave, I extended Zend_Db_Table with a model class which encapsulated some additional repeating code, such as validation and filtering for model data.

If you are talking about retrieving metadata and setting up some things auto-magically, Zend_Db_Table already has methods to handle that, check out info() and _metadata().
noondaysun
Forum Newbie
Posts: 4
Joined: Tue Oct 28, 2008 9:04 am

Re: Zend Framework Models

Post by noondaysun »

Sure the individual models will vary from class to class even if only slightly. The idea behind that is what is repetitive. What I was thinking was that you could pass in a table name to this generic model and it would auto receive all table parameters etc so that it would be something like this:
/application/models/DbTable/GenericTable.php
/application/models/GenericModel.php

And that is all that would be in the models directory. GenericModel.php would be a lot more complex than the current models because it needs to parse your database structure from table information. Think this way also enforces better *.sql files as you need to set up foreign keys etc.

I suppose what I'm saying, a little more succinctly, is that I would prefer not to have to type in all the models by hand in favour of a more generic model class
Post Reply