Model -> Save Function Undefined?

I seem to be having an issue with my model->save() function being undefined.

For logistics purposes this is what I am creating.

I have an order form which displays a list of custom options & subsequent prices. There is a list at the top which is a base product which has to be chosen and options that either add a fixed price of $0-whatever or a percent calculated using the base price.

I wrote the scripts to do everything from format the output on the order form to do all the price calculations. Currently everything works except for when I go to save my model I get the error "Property "Order.save" is not defined."

I don’t quite understand what the issue is or where to even begin with fixing it, I am new to yii so, still learning a lot of the functionality.

I am still new to the passing data around part of Yii, I’ve only been working with it for a week or two. I can provide a sample of the generated html from all the forms if needed.

Any help is appreciated, I honestly don’t even know where to start looking.

OrderController.php


<?php


class OrderController extends GxController {


public function filters() {

	return array(

			'accessControl', 

			);

}


public function accessRules() {

	return array(

			array('allow', 

				'actions'=>array('index', 'view', 'Populateaddress'),

				'users'=>array('@'),

				),

			array('allow', 

				'actions'=>array('minicreate', 'create', 'update', 'admin', 'delete'),

				'users'=>array('admin'),

				),

			array('deny', 

				'users'=>array('*'),

				),

			);

}


	public function actionView($id) {

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

			'model' => $this->loadModel($id, 'Order'),

		));

	}


	public function actionCreate() {

		$model = new Order;




		$this->performAjaxValidation($model, 'order-form');


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

			$model->setAttributes($_POST['Order']);

            if (!isset($POST['basePrice'])) {

                //ERROR ERROR ERROR

            }

            else {

                $model->setBasePriceID($_POST['basePrice']);

            }


            if (!isset($POST['childOptions'])) {

                //ERROR ERROR ERROR

            }

            else {

                $model->setChosenOptions($_POST['childOptions']);

            }


            if(!$model->save){

                $msg = print_r($model->getErrors(),1);

                throw CHttpException(400,'data not saving: '.$msg );

            }

			if ($model->save(false)) {

				if (Yii::app()->getRequest()->getIsAjaxRequest())

					Yii::app()->end();

			    else

					$this->redirect(array('view', 'id' => $model->id));

			}

		}


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

	}


	public function actionUpdate($id) {

		$model = $this->loadModel($id, 'Order');


		$this->performAjaxValidation($model, 'order-form');


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

			$model->setAttributes($_POST['Order']);


			if ($model->save()) {

				$this->redirect(array('view', 'id' => $model->id));

			}

		}


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

				'model' => $model,

				));

	}


	public function actionDelete($id) {

		if (Yii::app()->getRequest()->getIsPostRequest()) {

			$this->loadModel($id, 'Order')->delete();


			if (!Yii::app()->getRequest()->getIsAjaxRequest())

				$this->redirect(array('admin'));

		} else

			throw new CHttpException(400, Yii::t('app', 'Your request is invalid.'));

	}


	public function actionIndex() {

		$dataProvider = new CActiveDataProvider('Order');

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

			'dataProvider' => $dataProvider,

		));

	}


	public function actionAdmin() {

		$model = new Order('search');

		$model->unsetAttributes();


		if (isset($_GET['Order']))

			$model->setAttributes($_GET['Order']);


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

			'model' => $model,

		));

	}


    public function actionPopulateaddress()

    {

        $cID = (int) $_POST['customer_id'];


        $bData = Address::model()->findAll('customer_id=:customer_id AND type <= 1', array(':customer_id'=>$cID));

        $bData = CHtml::listData($bData,'id','linkInfo');

        $bDropdown = "<option value=''>Select Billing Address</option>";

        foreach($bData as $value=>$name)

            $bDropdown .= CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);




        $dData = Address::model()->findAll('customer_id=:customer_id AND type = 2', array(':customer_id'=>$cID));

        $dData = CHtml::listData($dData,'id','linkInfo');

        $dDropdown = "<option value=''>Select Delivery Address</option>";

        foreach($dData as $value=>$name)

            $dDropdown .= CHtml::tag('option', array('value'=>$value),CHtml::encode($name),true);


        // return data (JSON formatted)

        echo CJSON::encode(array(

            'billingA'=>$bDropdown,

            'deliveryA'=>$dDropdown

        ));

    }


}

Order.php (model)


<?php


Yii::import('application.models._base.BaseOrder');


class Order extends BaseOrder

{


    private $_basePrice;

    public $cOptions = array();

    public $baseid;


	public static function model($className=__CLASS__) {

		return parent::model($className);

	}


    public function setBasePriceID($basePriceID)

    {

        $this->_basePrice = Order::model()->findbyPk($basePriceID);

        $this->baseid = $basePriceID;

    }


    public function setChosenOptions($chosenOptions = array())

    {

        $this->cOptions = $chosenOptions;

    }


    public function candaOptionPrice($optionID)

    {

        $optionRow = Options::model()->findbyPK($optionID);

        if ($optionRow->price == 0.00) { }

        else

        {

            if ($optionRow->price_type == 2) { $this->price += $optionRow->price; }

            else {

                $this->price += ($optionRow->price / 100) * $this->_basePrice;

            }

        }

    }


    public function beforeSave()

    { // Should have a base price & chosen options by now.

        parent::beforeSave();

        $this->price = $this->_basePrice;

        if (is_array($this->cOptions)) {

            foreach ($this->cOptions as $options)

            {

                $this->candaOptionPrice($options->id);

                if ($options == end($this->chosenoptions))

                {

                    $this->chosenoptions .= $options->id;

                }

                else {

                    $this->chosenoptions .= $options->id . ":";

                }

            }

        }

        else { $this->candaOptionPrice($this->cOptions); }




        $this->balance = $this->price;


        if ($this->isNewRecord) { $this->creation_date = date(""); }


    }




}

BaseOrder.php


<?php


/**

 * This is the model base class for the table "order".

 * DO NOT MODIFY THIS FILE! It is automatically generated by giix.

 * If any changes are necessary, you must set or override the required

 * property or method in class "Order".

 *

 * Columns in table "order" available as properties of the model,

 * followed by relations of table "order" available as properties of the model.

 *

 * @property integer $id

 * @property integer $customer_id

 * @property integer $billing_address_id

 * @property string $delivery

 * @property string $delivery_date

 * @property integer $delivery_address_id

 * @property string $creation_date

 * @property string $price

 * @property string $balance

 * @property string $chosenoptions

 * @property integer $baseid

 *

 * @property Address $billingAddress

 * @property Address $deliveryAddress

 * @property Customer $customer

 * @property Payment[] $payments

 */

abstract class BaseOrder extends GxActiveRecord {


	public static function model($className=__CLASS__) {

		return parent::model($className);

	}


	public function tableName() {

		return 'order';

	}


	public static function label($n = 1) {

		return Yii::t('app', 'Order|Orders', $n);

	}


	public static function representingColumn() {

		return 'delivery';

	}


	public function rules() {

		return array(

			array('customer_id, delivery', 'required'),

			array('customer_id, billing_address_id, delivery_address_id, baseid', 'numerical', 'integerOnly'=>true),

			array('delivery', 'length', 'max'=>1),

			array('price, balance', 'length', 'max'=>10),

			array('delivery_date, creation_date, chosenoptions', 'safe'),

			array('billing_address_id, delivery_date, delivery_address_id, creation_date, price, balance, chosenoptions, baseid', 'default', 'setOnEmpty' => true, 'value' => null),

			array('id, customer_id, billing_address_id, delivery, delivery_date, delivery_address_id, creation_date, price, balance, chosenoptions, baseid', 'safe', 'on'=>'search'),

		);

	}


	public function relations() {

		return array(

			'billingAddress' => array(self::BELONGS_TO, 'Address', 'billing_address_id'),

			'deliveryAddress' => array(self::BELONGS_TO, 'Address', 'delivery_address_id'),

			'customer' => array(self::BELONGS_TO, 'Customer', 'customer_id'),

			'payments' => array(self::HAS_MANY, 'Payment', 'order_id'),

		);

	}


	public function pivotModels() {

		return array(

		);

	}


	public function attributeLabels() {

		return array(

			'id' => Yii::t('app', 'ID'),

			'customer_id' => null,

			'billing_address_id' => null,

			'delivery' => Yii::t('app', 'Delivery'),

			'delivery_date' => Yii::t('app', 'Delivery Date'),

			'delivery_address_id' => null,

			'creation_date' => Yii::t('app', 'Creation Date'),

			'price' => Yii::t('app', 'Price'),

			'balance' => Yii::t('app', 'Balance'),

			'chosenoptions' => Yii::t('app', 'Chosenoptions'),

			'baseid' => Yii::t('app', 'Baseid'),

			'billingAddress' => null,

			'deliveryAddress' => null,

			'customer' => null,

			'payments' => null,

		);

	}


	public function search() {

		$criteria = new CDbCriteria;


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

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

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

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

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

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

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

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

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

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

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


		return new CActiveDataProvider($this, array(

			'criteria' => $criteria,

		));

	}

}

Order _form view


<?php

/**

 * Created by JetBrains PhpStorm.

 * User: Jeffrey Mele

 * Date: 5/7/13

 * Time: 8:37 PM

 * To change this template use File | Settings | File Templates.

 */


class orderForm {


    private $_selectedOptions = array();

    private $_model;

    private $_output;


    public function orderForm ($selectedOptions = array())

    {

        $this->_selectedOptions = $selectedOptions;

        $this->start();

    }


    public function instantiateModel()

    {

        $this->_model = Catagory::model()->findAll();

    }


    private function start()

    {

        $this->instantiateModel();

        $this->generateCategories($this->_model);

    }


    private function generateCategories($model)

    {

        foreach ($model as $catagoryRow)

        {

            $this->_output .= "<div class=\"row-fluid\"> <div class=\"span12\">

                                <h2>". $catagoryRow->name ."</h2>";


            $this->generateOptions($catagoryRow->options);


            $this->_output .= "</div></div>";      // Close Span 12 from up there

        }

    }


    private function generateOptions($aOptions) // Generate options and subsequent labels

    {

        $spancount = 0; # have to create a new row every 4 items (span3 for each item)


        $this->_output .= "<div class=\"row-fluid\"><div class=\"span12\"><div class=\"row-fluid\">";

        foreach ($aOptions as $option)

        {

            $trimmedName = $option->name;

            if ($option == end($aOptions)) { $spanvalue = 12 - $spancount; /* Last item of array */ } else { $spanvalue = 4; } /* not last item of array $str = str_replace(' ','',$str); */

            if ($spancount == 12) { $this->_output .= "</div></div></div><div class=\"row-fluid\"><div class=\"span12\"><div class=\"row-fluid\">"; }

                if ($option->price_type == 0) // If option is "Base price"

                {

                    $this->_output .= "<div class=\"span{$spanvalue}\">

                                        <label class=\"radio\" for=\"{$trimmedName}\">

                                            <input type=\"radio\" name=\"baseChoice\" value=\"{$option->id}\" id=\"{$trimmedName}\"> $option->name < $option->price >

                                        </label>

                                       </div>";

                }

                else

                {

                    $this->_output .= "<div class=\"span{$spanvalue}\">

                                        <label class=\"checkbox\" for=\"{$trimmedName}\">

                                            <input type=\"checkbox\" name=\"childOptions[]\" value=\"{$option->id}\" id=\"{$trimmedName}\"> $option->name < $option->price >

                                        </label>

                                       </div>";

                }


            if ($spancount == 12 ) { $spancount = 0; }

            if($option == end($aOptions)) {$this->_output .= "</div></div></div>"; }

            else { $spancount += 4; }


        }





    }


    public function getOutput()

    {

        return $this->_output;

    }





}

orderForm.php (called in view)


<?php

/**

 * Created by JetBrains PhpStorm.

 * User: Jeffrey Mele

 * Date: 5/7/13

 * Time: 8:37 PM

 * To change this template use File | Settings | File Templates.

 */


class orderForm {


    private $_selectedOptions = array();

    private $_model;

    private $_output;


    public function orderForm ($selectedOptions = array())

    {

        $this->_selectedOptions = $selectedOptions;

        $this->start();

    }


    public function instantiateModel()

    {

        $this->_model = Catagory::model()->findAll();

    }


    private function start()

    {

        $this->instantiateModel();

        $this->generateCategories($this->_model);

    }


    private function generateCategories($model)

    {

        foreach ($model as $catagoryRow)

        {

            $this->_output .= "<div class=\"row-fluid\"> <div class=\"span12\">

                                <h2>". $catagoryRow->name ."</h2>";


            $this->generateOptions($catagoryRow->options);


            $this->_output .= "</div></div>";      // Close Span 12 from up there

        }

    }


    private function generateOptions($aOptions) // Generate options and subsequent labels

    {

        $spancount = 0; # have to create a new row every 4 items (span3 for each item)


        $this->_output .= "<div class=\"row-fluid\"><div class=\"span12\"><div class=\"row-fluid\">";

        foreach ($aOptions as $option)

        {

            $trimmedName = $option->name;

            if ($option == end($aOptions)) { $spanvalue = 12 - $spancount; /* Last item of array */ } else { $spanvalue = 4; } /* not last item of array $str = str_replace(' ','',$str); */

            if ($spancount == 12) { $this->_output .= "</div></div></div><div class=\"row-fluid\"><div class=\"span12\"><div class=\"row-fluid\">"; }

                if ($option->price_type == 0) // If option is "Base price"

                {

                    $this->_output .= "<div class=\"span{$spanvalue}\">

                                        <label class=\"radio\" for=\"{$trimmedName}\">

                                            <input type=\"radio\" name=\"baseChoice\" value=\"{$option->id}\" id=\"{$trimmedName}\"> $option->name < $option->price >

                                        </label>

                                       </div>";

                }

                else

                {

                    $this->_output .= "<div class=\"span{$spanvalue}\">

                                        <label class=\"checkbox\" for=\"{$trimmedName}\">

                                            <input type=\"checkbox\" name=\"childOptions[]\" value=\"{$option->id}\" id=\"{$trimmedName}\"> $option->name < $option->price >

                                        </label>

                                       </div>";

                }


            if ($spancount == 12 ) { $spancount = 0; }

            if($option == end($aOptions)) {$this->_output .= "</div></div></div>"; }

            else { $spancount += 4; }


        }





    }


    public function getOutput()

    {

        return $this->_output;

    }





}

Error


CException


Property "Order.save" is not defined.


C:\xampp\Yii_Core\framework\db\ar\CActiveRecord.php(143)


131      */

132     public function __get($name)

133     {

134         if(isset($this->_attributes[$name]))

135             return $this->_attributes[$name];

136         elseif(isset($this->getMetaData()->columns[$name]))

137             return null;

138         elseif(isset($this->_related[$name]))

139             return $this->_related[$name];

140         elseif(isset($this->getMetaData()->relations[$name]))

141             return $this->getRelated($name);

142         else

143             return parent::__get($name);

144     }

145 

146     /**

147      * PHP setter magic method.

148      * This method is overridden so that AR attributes can be accessed like properties.

149      * @param string $name property name

150      * @param mixed $value property value

151      */

152     public function __set($name,$value)

153     {

154         if($this->setAttribute($name,$value)===false)

155         {

Stack Trace

#0	

+  C:\xampp\Yii_Core\framework\db\ar\CActiveRecord.php(143): CComponent->__get("save")

#1	

–  C:\xampp\htdocs\test\protected\controllers\OrderController.php(55): CActiveRecord->__get("save")

50             }

51             else {

52                 $model->setChosenOptions($_POST['childOptions']);

53             }

54 

55             if(!$model->save){

56                 $msg = print_r($model->getErrors(),1);

57                 throw CHttpException(400,'data not saving: '.$msg );

58             }

59             if ($model->save(false)) {

60                 if (Yii::app()->getRequest()->getIsAjaxRequest())

#2	

+  C:\xampp\Yii_Core\framework\web\actions\CInlineAction.php(49): OrderController->actionCreate()

#3	

+  C:\xampp\Yii_Core\framework\web\CController.php(308): CInlineAction->runWithParams(array("r" => "order/create"))

#4	

+  C:\xampp\Yii_Core\framework\web\filters\CFilterChain.php(133): CController->runAction(CInlineAction)

#5	

+  C:\xampp\Yii_Core\framework\web\filters\CFilter.php(40): CFilterChain->run()

#6	

+  C:\xampp\Yii_Core\framework\web\CController.php(1145): CFilter->filter(CFilterChain)

#7	

+  C:\xampp\Yii_Core\framework\web\filters\CInlineFilter.php(58): CController->filterAccessControl(CFilterChain)

#8	

+  C:\xampp\Yii_Core\framework\web\filters\CFilterChain.php(130): CInlineFilter->filter(CFilterChain)

#9	

+  C:\xampp\Yii_Core\framework\web\CController.php(291): CFilterChain->run()

#10	

+  C:\xampp\Yii_Core\framework\web\CController.php(265): CController->runActionWithFilters(CInlineAction, array("accessControl"))

#11	

+  C:\xampp\Yii_Core\framework\web\CWebApplication.php(282): CController->run("create")

#12	

+  C:\xampp\Yii_Core\framework\web\CWebApplication.php(141): CWebApplication->runController("order/create")

#13	

+  C:\xampp\Yii_Core\framework\base\CApplication.php(169): CWebApplication->processRequest()

#14	

–  C:\xampp\htdocs\test\index.php(13): CApplication->run()

08 defined('YII_DEBUG') or define('YII_DEBUG',true);

09 // specify how many levels of call stack should be shown in each log message

10 defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

11 

12 require_once($yii);

13 Yii::createWebApplication($config)->run();

2013-05-08 07:08:54 Apache/2.2.17 (Win32) mod_ssl/2.2.17 OpenSSL/0.9.8o PHP/5.3.4 mod_perl/2.0.4 Perl/v5.10.1 Yii Framework/1.1.13

I fixed the issue where save is not defined,

line of code i pulled off the net in ordercontroller says model->save instead of model->save().

however, i still have the issue where my order doesn’t make it into the database, even with model->save(false)

before the $model->save function can you var_dumb just to see if anything is there. Also can you try

$model->attributes=$_POST[‘order’];

instead of setAttributes

Cheers

I did some modifying, I got it so the data in the model is perfect, but still doesn’t show up in the database.

putting a var_dump in the controller right before it loads the view yields


Array ( [customer_id] => 1 [billing_address_id] => 1 [delivery] => y [delivery_date] => 2013-05-22 [delivery_address_id] => 9 [baseid] => 2 [creation_date] => 2013-05-08 09:22:15 [price] => 22 [balance] => 22 [chosenoptions] => 7 [id] => )

yet it still doesn’t save, or throw an error.




if (!$model->save()) {

  echo CHtml::errorSummary($model);

  exit;

}



You will see your issue.

check validation of data (rules in Model) and its message in view, and also check data in firebug console

When I do this, the script exits, but nothing gets echo’d out.

Same thing as above, form is not outputting any errors, model is not outputting any errors and if I echo out the attributes of the model everything is in correct form yet it doesn’t save.

Well, problem solved. Issue was I didn’t “return true;” at the end of beforeSave.