开发者

Zend: Creating models for a products table

I'm trying to create two models, products and product_manufacturers so that I can pull in manufacturers as well as products, edit them in the admin if necessary, and the usual CRUD stuff. Here's the schema for the tables ( it's not finalized so if you have any suggestions go ahead ).

CREATE TABLE `product_manufacturers` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `manufacturer_name` varchar(100) default NULL,
  `active` tinyint(1) default '1',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

CREATE TABLE `products` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `product_name` varchar(100) default NULL,
  `manufacturer_id` int(11) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

Example data:

( products ) -

id product_name manufacturer_id
1  iPod Nano 4g 1

( product_manufacturers ) -

id manufacturer_name active
1  Apple             1

I've created two models, but I'm having trouble pulling in the products based on the active product manufacturers ( and yes, I'm using a model autoloader ).

protected function _initAutoload ()
{
    // Add autoloader empty namespace
    $autoLoader = Zend_Loader_Autoloader::getInstance();
$resourceLoader = new Zend_Loader_Autoloader_Resource(
    array(
    'basePath' => APPLICATION_PATH ,
    'namespace' => '' ,
    'resourceTypes' => array(
        'form' => array('path' => 'forms/' ,
        'namespace' => 'Form_') ,
        'model' => array('path' => 'models/' ,
        'namespace' => 'Model_')
    )
    ));
    // Return it so that it can be stored by the bootstrap
    return $autoLoader;
}

application/models/Product.php:

<?php
require_once 'Zend/Db/Table/Abstract.php';

class Model_Product extends Zend_Db_Table_Abstract
{
    /**
     * The default table name 
     */
    protected $_name = 'products';
    protected $_dependentTables = array('Model_Manufacturer');
}

application/models/Manufacturer.php:

class Model_Manufacturer extends Zend_Db_Table_Abstract
{
    /**
     * The default table name 
     */
    protected $_name = 'product_manufacturers';
    protected $_referenceMap = array(
 'Model_Product' => array(
     'manufacturer_id' => array('id'),
     'id' => array('manufacturer_id'),
 ),
    );
}

I have a feeling I'm completely doing things wrong, as I'm creating an object from the Products Model and trying to print out all products which have a corresponding manufacturer, and that manufacturer is active.

 $model = new Model_Product();
 $results = $model->fetchAll();
 foreach ($results as $result) {
     //print_r($result);
     echo $result->product_name;
 }

I'm new to model creation, could anyone provide advice on how I could properly change my current code so that the products model properly relies on the manufacturers model?

I have a feeling that I'm improperly setting the dependentTables/referenceMap, and instead of using the generic fetchAll method I should be creating a custom method in either of the models to do the fetching and maybe a manual join with the manufacturers table, or would a proper referenceMap and dependentTables property sol开发者_Python百科ve that issue?


There are a few things to fix up here, but here are a few tips.

i. Table models work a little better if their names are pluralized. They sound better in the magic methods (e.g. $product_set = findProducts() instead of findModel_Product())

ii. The reference map is the important one and allows for those nifty magic selection methods (e.g. findParentX()) to work. It belongs in the dependent table, which is the product table here because it references the product_manufacturer.

  // in Model_Product
  protected $_referenceMap = array(

    // rule name
    'Manufacturer' => array(

      'columns'       => 'manufacturer_id',     // this column
      'refTableClass' => 'Model_Manufacturer',  // references that table object
      'refColumns'    => 'id'                   // and references that column
    )
  );



iii. Move dependent tables entry to your product_manufacturers table model, if you'd like: it's used only to replicate ON DELETE/UPDATE CASCADE database commands, though. (Leave it for now)

// in manufacturer table model
protected $_dependentTables = array('Model_Product');



Fetching

To get a product's manufacturer, do this:

$manufacturer = $product_row->findParentManufacturer();


To get a manufacturer's products, do this:

$product_set = $manufacturer_row->findProducts(); // Well, findModel_Product(), which is why you should rename your table ;)


For other magic methods originating from each single row, dig into the source code for Zend_Db_Table_Row_Abstract (especially public function __call).


i have implemented reference maps and i'm retrieving the parent's details of a record using the $childObject->findParentObject() method- which works well for single instances of a child object.

however i have an issue with using this to retrieve the details of parent objects for multiple child rows [for display purposes] though, which currently involves doing a select to retrieve the initial record set then traversing this, using the findParentObject() method to get what i want for that record. thus i've decided to ignore the reference map and do a join for this, bypassing the reference map completely. this works fine, is one select only and is quicker.

my question then is is there a nice way of using the reference map to achieve the same results, using one query? the way i'm currently using the reference map feels a bit contrived, although it feels like for the sake of purity i should be using it to do what i need...

rob ganly

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜