0

情報

多くの MANY_MANY リレーションシップを持つモデルを保存する際に問題が発生しています。製品属性と製品属性レベルを追加できるページがあります。私が今やりたいことは、製品の更新ページにこれのサポートを追加することです。したがって、更新ページに入ると、すべての製品属性が表示され、各製品属性について、その特定の製品属性に関連する製品属性レベルのドロップダウン リストが表示されます。

データベース

製品

  • ID

製品属性

  • ID

製品属性レベル

  • ID
  • product_attribute_id ## FK

ProductProductAttributeLevel -- これはピボット テーブルです。

  • product_id ## FK PK
  • product_attribute_level_id ## FK PK

アクティブレコード

製品:

class Product extends S360ActiveRecord {

    public function behaviors() {
        return array('CAdvancedArBehavior' => array(
            'class' => 'application.extensions.CAdvancedArBehavior')
        );
    }

    public function rules() {
        return array(
            array('attributeLevels', 'safe'),
        );
    }

    public function relations() {
        return array(
            'attributeLevels' => array(self::MANY_MANY,
                'ProductAttributeLevel',
                'product_product_attribute_level(product_id,product_attribute_level_id)'
            ),
        );
    }

}

製品属性:

class ProductAttribute extends S360ActiveRecord {

    public function relations() {
        return array(
            'levels' => array(self::HAS_MANY, 'ProductAttributeLevel', 'product_attribute_id'),
        );
    }

}

製品属性レベル:

class ProductAttributeLevel extends S360ActiveRecord {

    public function relations() {
        return array(
            'productAttribute' => array(self::BELONGS_TO, 'ProductAttribute', 'product_attribute_id'),
            'products' => array(self::MANY_MANY, 'Product', 'product_product_attribute_level(product_attribute_level_id,product_id)'),
        );
    }
}

ProductProductAttributeLevel:

class ProductProductAttributeLevel extends S360ActiveRecord {

    public function relations()
    {
        return array(
            'productAttributeLevel' => array(self::BELONGS_TO, 'ProductAttributeLevel', 'product_attribute_level_id'),
            'product' => array(self::BELONGS_TO, 'Product', 'product_id'),
        );
    }

}

製品を更新する私の ProductController メソッドは次のようになります。

public function actionUpdate($id) {

    $model = $this->loadModel($id);
    $this->performAjaxValidation($model);

    if (isset($_POST['Product'])) {
        $model->attributes = $_POST['Product'];

        if ($model->save()) {
            $this->redirect(array('index'));
        }
    }

  $this->render('update', array('model' => $model));

}

私のフォームビューの関連部分:

<?php 
    $form=$this->beginWidget('S360ActiveForm', array(
        'id' => 'product-form',
        'enableAjaxValidation' => true,
    )); 
?>

<?php $attributes = ProductAttribute::model()->findAllByAttributes(array('survey_id' => $model->parent_id)); if ($attributes): ?>
<div class="span6">
    <?php foreach ($attributes as $attribute) {
        echo $form->dropDownListRow($model, 'attributeLevels',
            CMap::mergeArray(
                array('0' => Yii::t('backend','No attribute level')),
                CHtml::listData($attribute->levels, 'id', 'label')
            ),
            array('class' => 'span5')
        );
    }?>
</div>
<?php endif; ?>

問題

私はこのCDBExceptionを取得します:

CDbCommand は SQL ステートメントの実行に失敗しました: SQLSTATE[23000]: 整合性制約違反: 1452 子行を追加または更新できません: 外部キー制約が失敗しました ( product_product_attribute_level, CONSTRAINT product_product_attribute_level_ibfk_2FOREIGN KEY ( product_attribute_level_id) REFERENCES product_attribute_level( id) ON DELE)。実行された SQL ステートメント: insert into product_product_attribute_level (product_id, product_attribute_level_id) 値 ('5', '0')

問題は、ID が「0」の product_attribute_level が存在せず、ID が「1」から始まることです。正しいID番号を挿入するように変更するにはどうすればよいですか?

私が欲しいものの例

2 つの製品属性があるとします。属性 1 と属性 2。Attribute1 には、製品属性レベル Attribute1_Level1 および Attribute1_Level2 があります。Attribute2 には、製品属性レベル Attribute2_Level1、Attribute2_Level2、および Attribute2_Level3 があります。

製品の編集/更新ページに移動すると、これが表示されます: 属性 http://img201.imageshack.us/img201/9252/screenshot20130207at103.png /9252/screenshot20130207at103.pngAttribute1 ドロップダウン

製品はアンケートに属しています。製品属性も調査に属しているため、製品が持つことができるすべての製品属性を取得するのは簡単です:

$attributes = ProductAttribute::model()->findAllByAttributes(array('survey_id' => $product->survey_id));

この後、各属性に属するすべての製品属性レベルを取得する必要がありますが、これも非常に簡単です。

foreach ($attributes as $attribute) {

    echo $form->dropDownList($attribute, 'label',
        CHtml::listData($attribute->levels, 'id', 'label'),
        $htmlOptions
    );

}

問題は、それを製品に接続し、さまざまなドロップダウンから選択した内容に基づいて「$product->attributeLevels」関係を更新する方法です。$product->attributeLevels は、ProductAttributeLevel のリストである必要があり、テーブル「product_product_attribute_level」を介して保存する必要があります。

4

1 に答える 1

1

そしてもちろん、ドロップダウンから選択していますか? そうでない場合は、実際に「0」を送信しているためです

<?php foreach ($attributes as $attribute) {
        echo $form->dropDownListRow($model, 'attributeLevels',
            CMap::mergeArray(
                // **HERE**
                array('0' => Yii::t('backend','No attribute level')),
                CHtml::listData($attribute->levels, 'id', 'label')
            ),
            array('class' => 'span5')
        );
    }?>

レコードを表さない最初のオプションとして何かが必要な場合は、2 つのオプションがあります。ドキュメントから、promptまたはdropDownListemptyの属性を使用します。

  • prompt: 文字列。最初のリスト オプションとして表示されるプロンプト テキストを指定します。その値は空です。プロンプト テキストは HTML エンコードされないことに注意してください。

  • empty: 文字列。空の選択に対応するテキストを指定します。その値は空です。'empty' オプションは、値とラベルのペアの配列にすることもできます。各ペアは、最初にリスト オプションをレンダリングするために使用されます。テキスト ラベルは HTML エンコードされないことに注意してください。

ここで、attributeLevels のドロップダウン リストが必要ですが、それらを製品に保存する必要があります。属性を反復処理し、そのレベルを取得しますが、次のように製品に保存します。

<?php foreach ($attributes as $i => $attribute) {
        echo $form->dropDownListRow($product, "[$i]attributeLevels",
            CHtml::listData($attribute->levels, 'id', 'label'),
            array('class' => 'span5', 'prompt' => 'No attribute level')
        );
    }?>

それらを製品に保存するには、コントローラーで次のようにします。

public function actionUpdate($id) {

  $model = $this->loadModel($id);
  $this->performAjaxValidation($model);

  if (isset($_POST['Product'])) {
    $attrLevels = $_POST['Product']['attributeLevels'];
    unset($_POST['Product']['attributeLevels']);
    $model->attributes = $_POST['Product'];

    if( $model->save() ) {
      $valid=true;
      foreach($attrLevels as $i=>$attrLevel)
      {
        $pivot = new ProductProductAttributeLevel;
        $pivot->product_id = $model->id;
        $pivot->product_attribute_level_id = $attrLevel;
        $valid=$item->save() && $valid;
      }
      if($valid){
        $this->redirect(array('index'));
      }
    }
  }

  $this->render('update', array('model' => $model));

}

免責事項:コピー/貼り付けは機能しない場合がありますが、アイデアは得られます

于 2013-02-05T14:49:41.623 に答える