doujianmin6527 2013-12-16 02:38
浏览 39
已采纳

Yii crud更新 - 错误400 - 复合键导致问题

I am having a problem with the UPDATE of the 'bootstrap.widgets.TbGridView' in YII php framework.

The link generated by the UPDATE/pencil icon of my 'bootstrap.widgets.TbGridView' produce an Error 400. The link looks like this

http://mysite/index.php?r=marketingchannel/update&id%5Bid%5D=119&id%5BControllingChannel_id%5D=7

I have tried entering the link manually like this

http://mysite/index.php?r=marketingchannel/update&id=119&ControllingChannel_id=7

then I get the following CDbException

The value for the column "id" is not supplied when querying the table "marketingchannel".

The Stacktrace (of my entering link manually) looks like this:

0. /framework/db/schema/CDbCommandBuilder.php(519): CDbCommandBuilder->createInCondition(CMysqlTableSchema, array("id", "ControllingChannel_id"), array("119"), "t.")
1. /framework/db/ar/CActiveRecord.php(1431): CDbCommandBuilder->createPkCriteria(CMysqlTableSchema, "119", "", array(), ...)
2. /protected/controllers/MarketingchannelController.php(158): CActiveRecord->findByPk("119")
3. /protected/controllers/MarketingchannelController.php(89): MarketingchannelController->loadModel("119")
4. unknown(0): MarketingchannelController->actionUpdate("119")
5. /framework/web/actions/CAction.php(108): ReflectionMethod->invokeArgs(MarketingchannelController, array("119"))
6. /framework/web/actions/CInlineAction.php(47): CAction->runWithParamsInternal(MarketingchannelController, ReflectionMethod, array("r" => "marketingchannel/update", "id" => "119", "ControllingChannel_id" => "7"))
7. /framework/web/CController.php(308): CInlineAction->runWithParams(array("r" => "marketingchannel/update", "id" => "119", "ControllingChannel_id" => "7"))

This tells me it is finding the id in the url...however cannot process it.

Note: I realise the Gridview is producing a link with [ ] parenthese url encoded. However I dont understand why even when I manually enter a link, it still doesnt work.

Note2: I have many Gridviews like this in my application, it is only two that are not working. Coincidently their models are related by Foreign Keys. However other Gridviews related to these two, do function properly.

Update: Code of my Controller's Update Action

/**
* 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)
{
$model=$this->loadModel($id);

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

if(isset($_POST['Marketingchannel']))
{
$model->attributes=$_POST['Marketingchannel'];
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}

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

Update: Code of my Model

/**
 * This is the model class for table "marketingchannel".
 *
 * The followings are the available columns in table 'marketingchannel':
 * @property integer $id
 * @property string $MarketingChannel
 * @property integer $ControllingChannel_id
 *
 * The followings are the available model relations:
 * @property Audibeneid[] $audibenes
 * @property Audibeneid[] $audibenes1
 * @property Controllingchannel $controllingChannel
 * @property Verwendung[] $verwendungs
 */
class Marketingchannel extends CActiveRecord
{
     public $ControllingChannel_search;

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Marketingchannel the static model class
     */
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'marketingchannel';
    }

    /**
     * @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('ControllingChannel_id', 'required'),
            array('ControllingChannel_id', 'numerical', 'integerOnly'=>true),
            array('MarketingChannel', 'length', 'max'=>100),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            //Original   --  array('id, MarketingChannel, ControllingChannel_id', 'safe', 'on'=>'search'),
            array('id, MarketingChannel, ControllingChannel_id, ControllingChannel_search', '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(
            'audibenes' => array(self::HAS_MANY, 'Audibeneid', 'MarketingChannel_id'),
            'audibenes1' => array(self::HAS_MANY, 'Audibeneid', 'MarketingChannel_ControllingChannel_id'),
            'controllingChannel' => array(self::BELONGS_TO, 'Controllingchannel', 'ControllingChannel_id'),
            'verwendungs' => array(self::HAS_MANY, 'Verwendung', 'MarketingChannel_id'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'id' => 'ID',
            'MarketingChannel' => 'Marketing Channel',
            'ControllingChannel_id' => 'Controlling Channel id',
            'ControllingChannel_search' => 'Controlling Channel',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria=new CDbCriteria;
        $criteria->with = array( 'controllingChannel' );
        $criteria->compare('id',$this->id);
        $criteria->compare('MarketingChannel',$this->MarketingChannel,true);
        $criteria->compare('ControllingChannel_id',$this->ControllingChannel_id);
        $criteria->compare( 'controllingChannel.Controllingchannel', $this->ControllingChannel_search, true );
        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
        ));
    }
}

Update: Sql of my Table

CREATE TABLE IF NOT EXISTS `marketingchannel` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `MarketingChannel` varchar(100) DEFAULT NULL,
  `ControllingChannel_id` int(11) NOT NULL,
  PRIMARY KEY (`id`,`ControllingChannel_id`),
  UNIQUE KEY `MarketingChannel_UNIQUE` (`MarketingChannel`),
  KEY `fk_MarketingChannel_ControllingChannel1_idx` (`ControllingChannel_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=137 ;

grid view code.

<?php $this->widget('bootstrap.widgets.TbGridView',
array( 'id'=>'marketingchannel-grid', 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>
array( 'id', 'MarketingChannel', array( 'name'=>'ControllingChannel_search', 'value'=>'$data->controllingChannel->ControllingChannel' ), 'ControllingChannel_id', 
array( 'class'=>'bootstrap.widgets.TbButtonColumn', ), ), )); ?>

展开全部

  • 写回答

2条回答 默认 最新

  • doutou3725 2013-12-16 02:54
    关注

    Please change your action code to this and run again.

    public function actionUpdate($id)
    {
    $model=$this->loadModel($id);
    
    // Uncomment the following line if AJAX validation is needed
    // $this->performAjaxValidation($model);
    
    if(isset($_POST['Marketingchannel']))
    {
    $model->attributes=$_POST['Marketingchannel'];
    $model->id = $_GET['id'];
    if($model->save())
    $this->redirect(array('view','id'=>$model->id));
    }
    
    $this->render('update',array(
    'model'=>$model,
    ));
    }
    

    The reason could be due to the miss of id. $model->id might not be set.

    When you have a composite primary key, you should specify it in the array like done below.

    Updated Answer

    public function actionUpdate()
    {
    $id = $_GET['id'];
    $ControllingChannel_id = $_GET['ControllingChannel_id'];
    $model = Marketingchannel::model()->findByPk(array(
    'id' => $id,
    'ControllingChannel_id' => $ControllingChannel_id
    ));
    
    if(isset($_POST['Marketingchannel']))
    {
    $model->attributes=$_POST['Marketingchannel'];
    if($model->save())
    $this->redirect(array('view','id'=>$model->id));
    }
    
    $this->render('update',array(
    'model'=>$model,
    ));
    }
    

    To resolve the incorrect URL in gridview, you should modify your coding as following and include your url (where to go when pencil icon is clicked) . i.e updateButtonUrl = "the Url to update action"

    $this->widget('bootstrap.widgets.TbGridView', array('id'=>'marketingchannel-grid', 'dataProvider'=>$model->search(), 'filter'=>$model,
       'columns'=>
       array('id', 'MarketingChannel', array('name'=>'ControllingChannel_search', 'value'=>'$data->controllingChannel->ControllingChannel')
          , 'ControllingChannel_id',
          array(
             'htmlOptions'=>array('nowrap'=>'nowrap'),
             'class'=>'bootstrap.widgets.TbButtonColumn',
     'updateButtonUrl'=>'Yii::app()->createUrl("Marketingchannel/Update/",array("id"=>$data->id, "ControllingChannel_id"=>$data->ControllingChannel_id))',
          ),
          array('class'=>'bootstrap.widgets.TbButtonColumn'))));
    

    Ref : http://yiibooster.clevertech.biz/widgets/grids/view/gridview.html

    展开全部

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部