Yii Saves Record From Form 3 Times

I have the following action in my controller:


    public function actionEntersales()

    {

        $model = new Sales();

        if (!isset($_POST['Sales'])) {

            $model->receipt_date = date("Y-m-d", time());

        }

        if (isset($_POST['Sales'])) {

            $model->attributes = $_POST['Sales'];

            if ($model->validate()):

                $model->save();

                $this->redirect(array('company/comissionmanagement'));

            endif;

        }


        $this->render('entersales', array(

            'model' => $model,

        ));

    }



It should validate and then save the form data, where the "sales_items" have to be saved one by one in another table.

I tried to reach this goal by using a foreach on "features".

This is the related model:


    <?php

    

    /**

     * This is the model class for table "sales".

     *

     * The followings are the available columns in table 'sales':

     * @property integer $id

     * @property integer $company_id

     * @property integer $user_id

     * @property integer $store_id

     * @property integer $receipt_no

     * @property string $receipt_date

     * @property integer $carrier_id

     * @property integer $activationtype_id

     * @property string $mdn

     * @property string $accountpin

     * @property integer $rateplans_id

     * @property integer $status3_id

     * @property string $created

     * @property string $modified

     *

     * The followings are the available model relations:

     * @property Activationtypes $activationtype

     * @property Companies $company

     * @property Rateplans $rateplans

     * @property Stores $store

     * @property Users $user

     * @property Carriers $carrier

     * @property SalesItems[] $salesItems

     */

    class Sales extends CActiveRecord

    {

        /**

         * @return string the associated database table name

         */

    

        public $features;

    

        public function tableName()

        {

            return 'sales';

        }

    

        /**

         * @return array validation rules for model attributes.

         */

        public function rules()

        {

            // NOTE: you should only define rules for those attributes that

            // will receive user inputs.

            return array(

                array('company_id, user_id, store_id, receipt_no, receipt_date, carrier_id, activationtype_id, serial, mdn, accountpin, rateplans_id, status3_id', 'required'),

                array('company_id, user_id, store_id, receipt_no, carrier_id, activationtype_id, rateplans_id, status3_id', 'numerical', 'integerOnly' => true),

                array('mdn, accountpin', 'length', 'max' => 10),

                array('serial', 'length', 'max' => 18),

                array('modified', 'safe'),

                array('features', 'safe'),

                // The following rule is used by search().

                // @todo Please remove those attributes that should not be searched.

                array('id, company_id, user_id, store_id, receipt_no, receipt_date, carrier_id, activationtype_id, serial, mdn, accountpin, rateplans_id, status3_id, created, modified', 'safe', 'on' => 'search'),

            );

        }

    

        /**

         * @return array relational rules.

         */

        public function relations()

        {

            // NOTE: you may need to adjust the relation name and the related

            // class name for the relations automatically generated below.

            return array(

                'activationtype' => array(self::BELONGS_TO, 'Activationtypes', 'activationtype_id'),

                'company' => array(self::BELONGS_TO, 'Companies', 'company_id'),

                'rateplans' => array(self::BELONGS_TO, 'Rateplans', 'rateplans_id'),

                'store' => array(self::BELONGS_TO, 'Stores', 'store_id'),

                'user' => array(self::BELONGS_TO, 'Users', 'user_id'),

                'carrier' => array(self::BELONGS_TO, 'Carriers', 'carrier_id'),

                'salesItems' => array(self::HAS_MANY, 'SalesItems', 'sales_id'),

            );

        }

    

        /**

         * @return array customized attribute labels (name=>label)

         */

        public function attributeLabels()

        {

            return array(

                'id' => 'ID',

                'company_id' => 'Company',

                'user_id' => 'User',

                'store_id' => 'Store',

                'receipt_no' => 'Receipt No',

                'receipt_date' => 'Receipt Date',

                'carrier_id' => 'Carrier',

                'activationtype_id' => 'Activationtype',

                'serial' => ' Serial Number',

                'mdn' => 'Mdn',

                'accountpin' => 'Accountpin',

                'rateplans_id' => 'Rateplans',

                'status3_id' => 'Status3',

                'created' => 'Created',

                'modified' => 'Modified',

            );

        }

    

        /**

         * Retrieves a list of models based on the current search/filter conditions.

         *

         * Typical usecase:

         * - Initialize the model fields with values from filter form.

         * - Execute this method to get CActiveDataProvider instance which will filter

         * models according to data in model fields.

         * - Pass data provider to CGridView, CListView or any similar widget.

         *

         * @return CActiveDataProvider the data provider that can return the models

         * based on the search/filter conditions.

         */

        public function search()

        {

            // @todo Please modify the following code to remove attributes that should not be searched.

    

            $criteria = new CDbCriteria;

    

            $criteria->compare('id', $this->id);

            $criteria->compare('company_id', Yii::app()->user->cid);

            $criteria->compare('user_id', $this->user_id);

            $criteria->compare('store_id', $this->store_id);

            $criteria->compare('receipt_no', $this->receipt_no);

            $criteria->compare('receipt_date', $this->receipt_date, true);

            $criteria->compare('carrier_id', $this->carrier_id);

            $criteria->compare('activationtype_id', $this->activationtype_id);

            $criteria->compare('serial', $this->serial, true);

            $criteria->compare('mdn', $this->mdn, true);

            $criteria->compare('accountpin', $this->accountpin, true);

            $criteria->compare('rateplans_id', $this->rateplans_id);

            $criteria->compare('status3_id', $this->status3_id);

            $criteria->compare('created', $this->created, true);

            $criteria->compare('modified', $this->modified, true);

    

            return new CActiveDataProvider($this, array(

                'criteria' => $criteria,

            ));

        }

    

        /**

         * Returns the static model of the specified AR class.

         * Please note that you should have this exact method in all your CActiveRecord descendants!

         * @param string $className active record class name.

         * @return Sales the static model class

         */

        public static function model($className = __CLASS__)

        {

            return parent::model($className);

        }

    

        public function beforeValidate()

        {

            $this->company_id = Yii::app()->user->cid;

            $this->status3_id = 0;

            return parent::beforeValidate();

        }

    

        public function afterSave()

        {

            if (count($this->features) > 0):

                $sid = $this->id;

                foreach ($this->features as $key => $fid):

                    $si = new SalesItems();

                    $si->sales_id = $sid;

                    $si->feature_id = $fid;

                    $si->status2_id = 0;

                    $si->save(false);

                endforeach;

            endif;

            return parent::afterSave();

        }

    }



When i submit the form it save the record 3 times including all the sales_items record 3 times.

I can’t see in my code why it’s acting like that.

Can you post entersales view?




<?php

/* @var $this UsersController */

/* @var $model Users */

/* @var $form CActiveForm */

?>


<div class="form">


    <h1>Enter new SALE:</h1>


    <?php $form = $this->beginWidget('CActiveForm', array(

        'id' => 'entersales',

    ));

    $cid = Yii::app()->user->cid;

    ?>


    <p class="note">Fields with <span class="required">*</span> are required.</p>


    <?php echo $form->errorSummary($model); ?>


    <table>

        <tr>

            <td style="width:120px;">

                <?php echo $form->labelEx($model, 'user_id'); ?>

            </td>

            <td>

                <?php

                $list = CHtml::listData(Users::model()->findAll(array('order' => 'last_name', "condition" => "status1_id = 1 AND company_id = $cid")), 'id', 'concatened');

                echo $form->dropDownList($model, 'user_id', $list);

                ?>

            </td>

            <td>

                <?php echo $form->error($model, 'user_id'); ?>

            </td>

        </tr>

        <tr>

            <td style="width:120px;">

                <?php echo $form->labelEx($model, 'store_id'); ?>

            </td>

            <td>

                <?php

                $list = CHtml::listData(Stores::model()->findAll(array('order' => 'name', "condition" => "status1_id = 1 AND company_id = $cid")), 'id', 'name');

                echo $form->dropDownList($model, 'store_id', $list);

                ?>

            </td>

            <td>

                <?php echo $form->error($model, 'store_id'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'receipt_no'); ?>

            </td>

            <td>

                <?php echo $form->textField($model, 'receipt_no'); ?>

            </td>

            <td>

                <?php echo $form->error($model, 'receipt_no'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'receipt_date'); ?>

            </td>

            <td>

                <?php echo $form->dateField($model, 'receipt_date'); ?>

            </td>

            <td>

                <?php echo $form->error($model, 'receipt_date'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'carrier_id'); ?>

            </td>

            <td>

                <?php

                $list = CHtml::listData(Carriers::model()->findAll(array('order' => 'name', "condition" => "status1_id = 1 AND company_id = $cid")), 'id', 'name');

                echo $form->dropDownList($model, 'carrier_id', $list);

                ?>

            </td>

            <td>

                <?php echo $form->error($model, 'carrier_id'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'activationtype_id'); ?>

            </td>

            <td>

                <?php

                $list = CHtml::listData(Activationtypes::model()->findAll(array('order' => 'name', "condition" => "status1_id = 1 AND company_id = $cid")), 'id', 'name');

                echo $form->dropDownList($model, 'activationtype_id', $list);

                ?>

            </td>

            <td>

                <?php echo $form->error($model, 'activationtype_id'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'serial'); ?>

            </td>

            <td>

                <?php echo $form->textField($model, 'serial'); ?>

            </td>

            <td>

                <?php echo $form->error($model, 'serial'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'mdn'); ?>

            </td>

            <td>

                <?php echo $form->textField($model, 'mdn'); ?>

            </td>

            <td>

                <?php echo $form->error($model, 'mdn'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'accountpin'); ?>

            </td>

            <td>

                <?php echo $form->textField($model, 'accountpin'); ?>

            </td>

            <td>

                <?php echo $form->error($model, 'accountpin'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'rateplans_id'); ?>

            </td>

            <td>

                <?php

                $list = CHtml::listData(Rateplans::model()->findAll(array('order' => 'name', "condition" => "status1_id = 1 AND company_id = $cid")), 'id', 'name');

                echo $form->dropDownList($model, 'rateplans_id', $list);

                ?>

            </td>

            <td>

                <?php echo $form->error($model, 'rateplans_id'); ?>

            </td>

        </tr>

        <tr>

            <td>

                <?php echo $form->labelEx($model, 'features'); ?>

            </td>

            <td>

                <table>

                    <?php

                    echo $form->checkBoxList(

                        $model,

                        'features',

                        CHtml::listData(Features::model()->findAll(), 'id', 'name'), array('template' => '<tr><td style="width: 150px;" >{label}</td><td>{input}</td></tr>')

                    );

                    ?>

                </table>

            </td>

            <td>

                <?php echo $form->error($model, 'features'); ?>

            </td>

        </tr>


        <tr>

            <td colspan="3">

                <?php echo CHtml::submitButton('Submit'); ?>

            </td>

        </tr>

    </table>




    <?php $this->endWidget(); ?>


</div><!-- form --

I could be wrong! I don’t see anything that could be causing duplicates, dump the $_POST global var and inspect it just incase


// on another note you can merge the following rules into one

array('modified', 'safe'),

array('features', 'safe'),


// like so

array('features, modified', 'safe'),

Yup, I cannot see anything suspicious.

Does it always save the data 3 times? On every browser (just in case)?

OMG… omg… OMG… i’m so stupid…

Sorry guys…

I had the ajax validation in the original form view active, but not in the controller…

That cause the saves when i switched the input field…

NOOOOB ERROR!!!!

Wokring now…