致命错误:调用成员函数isAttributeRequired()

时间:2014-07-03 00:08:47

标签: yii

运行我的网站时出现以下错误。有什么想法发生了什么?我是Yii的新手和框架我不知道这个错误意味着什么或它在哪里。我发布了我的控制器以及错误。我一直在研究更新行动..

致命错误:在第1414行的C:\ xampp \ framework \ web \ helpers \ CHtml.php中的非对象上调用成员函数isAttributeRequired()

查看

<?php Yii::app()->clientScript->registerCoreScript('jquery'); ?>
<?php
/* @var $this BookingController */
/* @var $model Booking */
/* @var $bookingRoom BookingRoom */

$this->breadcrumbs=array(
'Bookings'=>array('index'),
$model->Id=>array('view','id'=>$model->Id),
'Update'
);

$this->menu=array(
array('label'=>'List Booking', 'url'=>array('index')),
array('label'=>'Create Booking', 'url'=>array('create')),
array('label'=>'View Booking', 'url'=>array('view', 'id'=>$model->Id)),
array('label'=>'Manage Booking', 'url'=>array('admin'))
);
?>

<h1>Update Booking <?php echo $model->Id; ?></h1>
<a href="create.php"></a>
<?php //$this->renderPartial('_form', array('model'=>$model)); ?>

<div class="form">
<button id="btnAdd" type='btnAdd'>Add</button>
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'booking-form',
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation'=>false,
)); ?>

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

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

<div class="row">
    <?php echo $form->labelEx($model,'Id'); ?>
    <?php echo $form->textField($model,'Id'); ?>
    <?php echo $form->error($model,'Id'); ?>
</div>

<div class="row"> 
    <?php echo $form->labelEx($model,'customerId'); ?>
    <?php echo $form->textField($model,'customerId'); ?>
    <?php echo $form->error($model,'customerId'); ?>
</div>

<div class="row">
    <?php echo $form->labelEx($model,'date'); ?>
    <?php echo $form->textField($model,'date'); ?>
    <?php echo $form->error($model,'date'); ?>
</div>

    <table id="tblData">
        <tbody>
    <?php foreach($items as $i=>$item): ?>

        <tr>
            <td>
                         <div>
    <?php echo $form->labelEx($item,'bookingId'); ?>
    <?php echo $form->textField($item,'['.$i.']bookingId'); ?>
    <?php echo $form->error($item,'bookingId'); ?>
                </div>
            </td>

            <td>
    <div>
    <?php echo $form->labelEx($item,'Room No'); ?>
    <?php echo $form->dropDownList($item, '['.$i.']roomId', CHtml::listData(
    Room::model()->findAll(), 'id', 'id'), array('single'=>'single', 'size'=>5)
    ); ?>
    <?php echo $form->error($item,'roomId'); ?>
    </div>
            </td><td>
    <div>
    <?php echo $form->labelEx($item,'startDate'); ?>
    <?php echo $form->textField($item,'['.$i.']startDate'); ?>
    <?php echo $form->error($item,'startDate'); ?>
</div>
                </td><td>
    <div>
    <?php echo $form->labelEx($item,'endDate'); ?>
    <?php echo $form->textField($item,'['.$i.']endDate'); ?>
    <?php echo $form->error($item,'endDate'); ?>
</div>
    </td><td>
    <div>
    <?php echo $form->labelEx($item,'adults'); ?>
    <?php echo $form->dropDownList($item, '['.$i.']adults', array('1'=>'1', 
                                                                 '2'=>'2', 
                                                                 '3'=>'3', 
                                                                 '4'=>'4',
                                                                 '5'=>'5'), array('single'=>'single', 'size'=>5)
    ); ?>
    <?php echo $form->error($item,'adults'); ?>
    </div>
</td><td>
            <div>
    <?php echo $form->labelEx($item,'children'); ?>
    <?php echo $form->dropDownList($item, '['.$i.']children', array('1'=>'1', 
                                                                 '2'=>'2', 
                                                                 '3'=>'3', 
                                                                 '4'=>'4',
                                                                 '5'=>'5'), array('single'=>'single', 'size'=>5)
    ); ?>
    <?php echo $form->error($item,'children'); ?>
    </div>
    </td>
    <td>
        <button type='button'>Delete</button>
    </td>
    </tr>
    <?php endforeach; ?>   
        </tbody>
    </table>


    <div class="row buttons">
      <?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>

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

</div><!-- form -->

预订模式

<?php

/**
 * This is the model class for table "booking".
 *
 * The followings are the available columns in table 'booking':
 * @property integer $Id
 * @property integer $customerId
 * @property string $date
 *
 * The followings are the available model relations:
 * @property Bookingroom[] $bookingrooms
 */
class Booking extends CActiveRecord
{
/**
 * @return string the associated database table name
 */
public function tableName()
{
    return 'booking';
}

/**
 * @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('Id, customerId, date', 'required'),
        array('Id, customerId', 'numerical', 'integerOnly'=>true),
        // The following rule is used by search().
        // @todo Please remove those attributes that should not be searched.
        array('Id, customerId, date', '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(       
                 'rooms' => array(self::HAS_MANY, 'Room', 'id')
    );
}

/**
 * @return array customized attribute labels (name=>label)
 */
public function attributeLabels()
{
    return array(
        'Id' => 'ID',
        'customerId' => 'Customer',
        'date' => 'Date',
    );
}

/**
 * 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('customerId',$this->customerId);
    $criteria->compare('date',$this->date,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 Booking the static model class
 */
public static function model($className=__CLASS__)
{
    return parent::model($className);
}
}

BookingRoom模型

<?php

/**
 * This is the model class for table "bookingRoom".
 *
 * The followings are the available columns in table 'bookingRoom':
 * @property integer $roomId
 * @property integer $bookingId
 * @property string $startDate
 * @property string $endDate
 * @property integer $adults
 * @property integer $children
 */
class BookingRoom extends CActiveRecord
{
/**
 * @return string the associated database table name
 */
public function tableName()
{
    return 'bookingRoom';
}

/**
 * @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('roomId, bookingId, startDate, endDate, adults, children', 'required'),
        array('roomId, adults, children', 'numerical', 'integerOnly'=>true),
        // The following rule is used by search().
        // @todo Please remove those attributes that should not be searched.
        array('roomId, bookingId, startDate, endDate, adults, children', '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(   
                //'booking' => array(self::BELONGS_TO, 'Booking', 'bookingId'),
                //'room' => array(self::BELONGS_TO, 'Room', 'roomId'),
    );
}

/**
 * @return array customized attribute labels (name=>label)
 */
public function attributeLabels()
{
    return array(
        'roomId' => 'Room',
        'bookingId' => 'Booking',
        'startDate' => 'Start Date',
        'endDate' => 'End Date',
        'adults' => 'Adults',
        'children' => 'Children',
    );
}

/**
 * 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('roomId',$this->roomId);
    $criteria->compare('bookingId',$this->bookingId);
    $criteria->compare('startDate',$this->startDate,true);
    $criteria->compare('endDate',$this->endDate,true);
    $criteria->compare('adults',$this->adults);
    $criteria->compare('children',$this->children);

    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 BookingRoom the static model class
 */
public static function model($className=__CLASS__)
{
    return parent::model($className);
}

public function primaryKey()
{
    return array('roomId', 'bookingId');
}
}

房间模型

<?php

/**
 * This is the model class for table "room".
 *
 * The followings are the available columns in table 'room':
 * @property integer $id
 * @property integer $beds
 */
class Room extends CActiveRecord
{
/**
 * @return string the associated database table name
 */
public function tableName()
{
    return 'room';
}

/**
 * @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('id, beds', 'required'),
        array('id, beds', 'numerical', 'integerOnly'=>true),
        // The following rule is used by search().
        // @todo Please remove those attributes that should not be searched.
        array('id, beds', '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(
               //'bookingrooms' => array(self::HAS_MANY, 'BookingRoom', 'roomId'),
                'bookings' => array(self::MANY_MANY, 'Booking','bookingroom(bookingId, roomId)'),
    );
}

/**
 * @return array customized attribute labels (name=>label)
 */
public function attributeLabels()
{
    return array(
        'id' => 'ID',
        'beds' => 'Beds',
    );
}

/**
 * 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('beds',$this->beds);

    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 Room the static model class
 */
public static function model($className=__CLASS__)
{
    return parent::model($className);
}
}

预订控制器

class BookingController extends Controller
{
/**
 * @var string the default layout for the views. Defaults to '//layouts/column2', meaning
 * using two-column layout. See 'protected/views/layouts/column2.php'.
 */
public $layout='//layouts/column2';

/**
 * @return array action filters
 */
public function filters()
{
    return array(
        'accessControl', // perform access control for CRUD operations
        'postOnly + delete', // we only allow deletion via POST request
    );
}

/**
 * Specifies the access control rules.
 * This method is used by the 'accessControl' filter.
 * @return array access control rules
 */
public function accessRules()
{
    return array(
        array('allow',  // allow all users to perform 'index' and 'view' actions
            'actions'=>array('index','view', 'display'),
            'users'=>array('*'),
        ),
        array('allow', // allow authenticated user to perform 'create' and 'update' actions
            'actions'=>array('create','update'),
            'users'=>array('@'),
        ),
        array('allow', // allow admin user to perform 'admin' and 'delete' actions
            'actions'=>array('admin','delete'),
            'users'=>array('admin'),
        ),
        array('deny',  // deny all users
            'users'=>array('*'),
        ),
    );
}



/**
 * Displays a particular model.
 * @param integer $id the ID of the model to be displayed
 */
public function actionView($id)
{
    $this->render('view',array(
        'model'=>$this->loadModel($id),
    ));
}


    public function getItemsToUpdate($id){
        // create an empty list of records
        $items = array();

            // Iterate over each item from the submitted form                        
            if (isset($_POST['BookingRoom']) && is_array($_POST['BookingRoom'])) {  

                foreach ($_POST['BookingRoom'] as $item) {                        

                    //$item['bookingId'] = $id;
                     // If item id is available, read the record from database 
                    if (( array_key_exists('bookingId', $item) && array_key_exists('roomId', $item) ) && ( array_key_exists('startDate', $item) && array_key_exists('endDate', $item) )){

                        //$items[] = BookingRoom::model()->findByPk($item['bookingId']);
                    //$items[] = BookingRoom::model()->find('bookingId=:bookingId', array(':bookingId'=>$id));
                      $items[] = BookingRoom::model()->findByAttributes(array('roomId' => $item['roomId'], 'bookingId' => $item['bookingId'], 'startDate' => $item['startDate'], 'endDate' => $item['endDate']));
                      //var_dump($items);
                    // Otherwise create a new record
                    } else {

                        $items[] = new BookingRoom();
                    }
            }

                    } 
             else {

                $items = BookingRoom::model()->findAll('bookingId=:bookingId', array(':bookingId'=>$id));

            } 
            return $items;                     
    }



/**
 * Creates a new model.
 * If creation is successful, the browser will be redirected to the 'view' page.
 */
public function actionCreate()
{

    $model=new Booking;
            //$BookingRoom=new BookingRoom;
            $items=$this->getItemsToUpdate();

            if (isset($_POST['Booking'])){
            $model->attributes=$_POST['Booking'];
            }
            //var_dump($items);
    // Uncomment the following line if AJAX validation is needed
    // $this->performAjaxValidation($model);                                                                              


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

                $valid=true;
                foreach($items as $i=>$item)
                {
                    if(isset($_POST['BookingRoom'][$i]))
                    $item->attributes=$_POST['BookingRoom'][$i];
                    $valid=$item->validate() && $valid;
                }

                $valid=$model->validate() && $valid;


                if($valid){

                }                                                                          
              }


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

}

/**
 * Updates a particular model.
 * If update is successful, the browser will be redirected to the 'view' page.
 * @param integer $id the ID of the model to be updated
 */
public function actionUpdate($id)
{
    $baseUrl = Yii::app()->baseUrl; 
            $cs = Yii::app()->getClientScript();
            $cs->registerScriptFile($baseUrl.'/js/functions.js');

// first time round
        if (!isset($_POST['Booking'])) {
            $model=$this->loadModel($id);
        } else {

          $model = $this->loadModel($id);
          $model->attributes=$_POST['Booking'];              
          $model->update();
        }

            $items = array();

    // Uncomment the following line if AJAX validation is needed
    // $this->performAjaxValidation($model);                                                                              


             $items=$this->getItemsToUpdate($id);

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

                $valid=true;

                foreach($items as $item)
                {

                }                    

                //$valid=$model->validate() && $valid;

                if($valid){
                        // construct sql save the booking



                }                                                                         
              }

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

}

/**
 * Deletes a particular model.
 * If deletion is successful, the browser will be redirected to the 'admin' page.
 * @param integer $id the ID of the model to be deleted
 */
public function actionDelete($id)
{
    $this->loadModel($id)->delete();

    // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
    if(!isset($_GET['ajax']))
        $this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
}

    public function actionDisplay()
{
    $dataProvider=new CActiveDataProvider('Booking');
    $this->render('index',array(
        'dataProvider'=>$dataProvider,
    ));
}

/**
 * Lists all models.
 */
public function actionIndex()
{
    $dataProvider=new CActiveDataProvider('Booking');
    $this->render('index',array(
        'dataProvider'=>$dataProvider,
    ));
}

/**
 * Manages all models.
 */
public function actionAdmin()
{
    $model=new Booking('search');
    $model->unsetAttributes();  // clear any default values
    if(isset($_GET['Booking']))
        $model->attributes=$_GET['Booking'];

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

/**
 * Returns the data model based on the primary key given in the GET variable.
 * If the data model is not found, an HTTP exception will be raised.
 * @param integer $id the ID of the model to be loaded
 * @return Booking the loaded model
 * @throws CHttpException
 */
public function loadModel($id)
{                        
    $model=Booking::model()->findByPk($id);
            /*
            $criteria=new CDbCriteria;
            $criteria->condition='bookingId=:bookingId';
            $criteria->select = 'roomId';
            $criteria->params=array(':bookingId'=>$_GET['id']);
            $bookingRooms = BookingRoom::model()->findAll($criteria);

            $rooms = array();
            foreach ($bookingRooms as $room) {
                $rooms[] = $room->roomId;
            }

            $model->rooms = $rooms;
            */
    if($model===null) {
        throw new CHttpException(404,'The requested page does not exist.');
            }
    return $model;




}

/**
 * Performs the AJAX validation.
 * @param Booking $model the model to be validated
 */
protected function performAjaxValidation($model)
{
    if(isset($_POST['ajax']) && $_POST['ajax']==='booking-form')
    {
        echo CActiveForm::validate($model);
        Yii::app()->end();
    }
}


}

堆栈跟踪

Application Log
Timestamp   Level   Category    Message
15:23:06.388200     trace   system.CModule  

Loading "log" application component
in C:\xampp\htdocs\index.php (13)

15:23:06.400199     trace   system.CModule  

Loading "request" application component
in C:\xampp\htdocs\index.php (13)

15:23:06.409199     trace   system.CModule  

Loading "urlManager" application component
in C:\xampp\htdocs\index.php (13)

15:23:06.436199     trace   system.web.filters.CFilterChain     

Running filter BookingController.filteraccessControl()
in C:\xampp\htdocs\index.php (13)

15:23:06.439199     trace   system.CModule  

Loading "user" application component
in C:\xampp\htdocs\index.php (13)

15:23:06.447200     trace   system.CModule  

Loading "session" application component
in C:\xampp\htdocs\index.php (13)

15:23:06.453200     trace   system.CModule  

Loading "clientScript" application component
in C:\xampp\protected\controllers\BookingController.php (181)
in C:\xampp\htdocs\index.php (13)

15:23:06.483200     trace   system.db.ar.CActiveRecord  

Booking.findByPk()
in C:\xampp\protected\controllers\BookingController.php (285)
in C:\xampp\protected\controllers\BookingController.php (189)
in C:\xampp\htdocs\index.php (13)

15:23:06.483200     trace   system.CModule  

Loading "db" application component
in C:\xampp\protected\controllers\BookingController.php (285)
in C:\xampp\protected\controllers\BookingController.php (189)
in C:\xampp\htdocs\index.php (13)

15:23:06.488199     trace   system.db.CDbConnection     

Opening DB connection
in C:\xampp\protected\controllers\BookingController.php (285)
in C:\xampp\protected\controllers\BookingController.php (189)
in C:\xampp\htdocs\index.php (13)

15:23:07.536200     trace   system.db.CDbCommand    

Querying SQL: SHOW FULL COLUMNS FROM `booking`
in C:\xampp\protected\controllers\BookingController.php (285)
in C:\xampp\protected\controllers\BookingController.php (189)
in C:\xampp\htdocs\index.php (13)

15:23:07.556200     trace   system.db.CDbCommand    

Querying SQL: SHOW CREATE TABLE `booking`
in C:\xampp\protected\controllers\BookingController.php (285)
in C:\xampp\protected\controllers\BookingController.php (189)
in C:\xampp\htdocs\index.php (13)

15:23:07.562200     trace   system.db.CDbCommand    

Querying SQL: SELECT * FROM `booking` `t` WHERE `t`.`Id`=23 LIMIT 1
in C:\xampp\protected\controllers\BookingController.php (285)
in C:\xampp\protected\controllers\BookingController.php (189)
in C:\xampp\htdocs\index.php (13)

15:23:07.573199     trace   system.db.ar.CActiveRecord  

Booking.update()
in C:\xampp\protected\controllers\BookingController.php (191)
in C:\xampp\htdocs\index.php (13)

15:23:07.573199     trace   system.db.ar.CActiveRecord  

Booking.updateByPk()
in C:\xampp\protected\controllers\BookingController.php (191)
in C:\xampp\htdocs\index.php (13)

15:23:07.574199     trace   system.db.CDbCommand    

Executing SQL: UPDATE `booking` SET `Id`=:yp0, `customerId`=:yp1,
`date`=:yp2 WHERE `booking`.`Id`=23
in C:\xampp\protected\controllers\BookingController.php (191)
in C:\xampp\htdocs\index.php (13)

15:23:07.666199     trace   system.db.ar.CActiveRecord  

BookingRoom.findByAttributes()
in C:\xampp\protected\controllers\BookingController.php (77)
in C:\xampp\protected\controllers\BookingController.php (200)
in C:\xampp\htdocs\index.php (13)

15:23:07.666199     trace   system.db.CDbCommand    

Querying SQL: SHOW FULL COLUMNS FROM `bookingRoom`
in C:\xampp\protected\controllers\BookingController.php (77)
in C:\xampp\protected\controllers\BookingController.php (200)
in C:\xampp\htdocs\index.php (13)

15:23:07.685199     trace   system.db.CDbCommand    

Querying SQL: SHOW CREATE TABLE `bookingRoom`
in C:\xampp\protected\controllers\BookingController.php (77)
in C:\xampp\protected\controllers\BookingController.php (200)
in C:\xampp\htdocs\index.php (13)

15:23:07.688199     trace   system.db.CDbCommand    

Querying SQL: SELECT * FROM `bookingRoom` `t` WHERE `t`.`roomId`=:yp0 AND
`t`.`bookingId`=:yp1 AND `t`.`startDate`=:yp2 AND `t`.`endDate`=:yp3 LIMIT
1
in C:\xampp\protected\controllers\BookingController.php (77)
in C:\xampp\protected\controllers\BookingController.php (200)
in C:\xampp\htdocs\index.php (13)

15:23:07.695199     trace   system.CModule  

Loading "widgetFactory" application component
in C:\xampp\protected\views\booking\update.php (34)
in C:\xampp\protected\controllers\BookingController.php (224)
in C:\xampp\htdocs\index.php (13)

1 个答案:

答案 0 :(得分:0)

问题在于BookingController :: getItemsToUpdate:

$items[] = BookingRoom::model()->findByAttributes(array('roomId' => $item['roomId'], 'bookingId' => $item['bookingId'], 'startDate' => $item['startDate'], 'endDate' => $item['endDate']));

您可以更改此查询逻辑或重写代码:

$model = BookingRoom::model()->findByAttributes(array('roomId' => $item['roomId'], 'bookingId' => $item['bookingId'], 'startDate' => $item['startDate'], 'endDate' => $item['endDate']));
if ($model) {
    $items[] = $model;
}