cakePHP bind hasmany通过关系

时间:2012-07-25 12:36:24

标签: php cakephp cakephp-2.0

好的,这很难解释,但我会尽我所能。

我有3张桌子

companies     products     product_availabilities
---------     --------     ----------------------
id            id           id
name          name         company_id
                           product_id
                           buys (tinyint)
                           sells (tinyint)

他们的模特

class Company extends AppModel
{
        public $name = 'Company';

        public $hasMany = array(
            'ProductAvailability'
        );


class Product extends AppModel
{       
    public $name = 'Product';

    public $hasMany = array(
        'ProductAvailability'
    );


class ProductAvailability extends AppModel
{
    public $name = 'ProductAvailability';

    public $belongsTo = array(
        'Company',
        'Product'
    );
}

我想做的是当我创建公司时,我希望能够选择公司购买或销售的产品。我在书中看到了一个关于hasMany关系的例子(http://book.cakephp.org/1.3/view/1650/hasMany-through-The-Join-Model),但他们正在创建“连接表“控制器。是否可以将productAvailability模型绑定到我的公司模型,以便能够在创建公司时选择产品?

编辑:我就是这样做的。我知道这不是最优的,因为涉及到很多循环但是它有效。

公司控制人:

    $products = $this->Company->ProductAvailability->Product->find('list', array('fields' => array('Product.id', 'Product.label')));
    $this->set('products', $products);

    if($this->request->is('post')){             
        if($this->Company->save($this->request->data)){
            foreach($products as $product)
            {
                $tmpArray = array(
                    'company_id' => $this->Company->id,
                    'product_id' => $product['Product']['id']
                );

                foreach($this->request->data('BuyProducts.product_id') as $buyProduct)
                {
                    if($buyProduct == $product['Product']['id'])
                        $tmpArray['buys'] = 1;
                }
                foreach($this->request->data('SellProducts.product_id') as $sellProduct)
                {
                    if($sellProduct == $product['Product']['id'])
                        $tmpArray['sells'] = 1;
                }

                if(count($tmpArray) > 2)
                {
                    $this->Company->ProductAvailability->create();
                    $this->Company->ProductAvailability->set($tmpArray);
                    $this->Company->ProductAvailability->save();
                }  
            }

            $this->Session->setFlash('Yay', 'success');
            $this->redirect(array('action' => 'index'));
        } else {
            $this->Session->setFlash('Nay', 'error');
        }
    }

公司添加表格:

<?php echo $this->Form->create('Company'); ?>

<?php echo $this->Form->input('name', array( 'div' => 'full-form')); ?>

<?php echo $this->Form->input('BuyProducts.product_id', array('multiple' => 'checkbox', 'options' => $products, 'div' => 'full-form', 'label' => false)); ?>

<?php echo $this->Form->input('SellProducts.product_id', array('multiple' => 'checkbox', 'options' => $products, 'div' => 'full-form', 'label' => false)); ?>

<?php echo $this->Form->end(array('label' => __('Save'), 'div' => 'center', 'class' => 'bouton-vert')); ?>

2 个答案:

答案 0 :(得分:6)

您有两种选择。让cakePHP与 hasAndBelongsToMany 关系做一些魔术,或者手动完成,如果你向连接表添加属性,这是必要的

1。 CakePHP HABTM

使用CakePHP的功能并制定直接的解决方案,我会做出这些改变:

模型

如果一家公司有多个产品,并且这些产品属于许多公司。公司&lt; - &gt;产品

之间的 hasAndBelongsToMany 关系
// company.php
...
var $hasAndBelongsToMany = array(
    'Product' => array(
        'className' => 'Product',
        'joinTable' => 'companies_products',
        'foreignKey' => 'company_id',
        'associationForeignKey' => 'product_id',
        'unique' => true,
    )
);
...
// similar in product.php 

在数据库中添加必需的表'companies_products'。

<强>控制器

然后在公司控制器的添加功能中应该有:

$products = $this->Company->Product->find('list');
$this->set(compact('products'));

查看

最后在 add.ctp 中插入产品,select应允许多项选择,让cakePHP做一些魔法,如下所示:

echo $this->Form->input('products', array( 
                         'label' => 'Products to buy (Ctr+multiple choice)' 
                          'type' => 'select', 
                      'multiple' => true,
                       ));

2。手动

当HABTM变得更具“异国情调”并且包含一些属性时,例如“买入”或“卖出”,您需要采用手动方式。这是在产品控制器设置字段之前手动将它们插入数据库之前。类似的东西:

foreach($availableProducts as $availableProduct ){
  $this->Product->ProductAvailabilities->create();
  $this->Product->ProductAvailabilities->set( array(
    'company_id' => $this->Product->id,
    'product_id' => $availableProduct['Product']['id'],
    'buys' => $availableProduct['Product']['buy'], 
    'sells' => $availableProduct['Product']['sell'] 
             // or however you send it to the controller
  ));
$this->Product->ProductAvailabilities->save();
}

让我们希望这可以帮助你...

答案 1 :(得分:0)

你正在计划一个habtm-relationship(m:n),可能在连接表中有额外的字段。虽然这可以通过常规habtm来完成,但我更喜欢你选择的方式并将m:n设置为1:n:1,这是相同的,并在保存数据时为您提供更多选项。

这是similar question and answer

至于您的问题:您可以收集产品表中的数据,如下所示:

$this->Company->ProductAvailability->Product->find('all', $params);

另外,您可能需要查看对此用例非常有用的containable-behaviour

$params['conditions'] = array(
    'Company.id' => $id
);
$params['contain'] => array(
    'ProductAvailability' => array(
        'conditions' =>array(
            'buys' => 1
        ),
        'Product' => array(
            'order' => array(
                'name' => 'ASC'
            )
        )
    )
);
$this->Company->find('all', $params);