cakephp 模型 saveAssociated 错误 - 不能将字符串偏移量用作数组
Posted
技术标签:
【中文标题】cakephp 模型 saveAssociated 错误 - 不能将字符串偏移量用作数组【英文标题】:cakephp model saveAssociated error - Cannot use string offset as an array 【发布时间】:2013-11-19 11:22:21 【问题描述】:我这里有一个梨形的。它把我逼疯了,花了一天的时间在上面。我希望有人可以快速浏览一下并指出明显的内容。
我几乎完成了从 1.3.14 到 2.4.2 的 cakephp 升级。我遇到的其余问题之一是 saveAll 模型调用......它实际上是正确插入第一个数组的数据,但其余部分抛出异常。
我得到的错误是:
Error: Cannot use string offset as an array
File: /srv/www/test/public_html/app/Lib/cakephp/lib/Cake/Model/Model.php
Line: 2453
如果我查看 Model.php,问题就出现在这里:
case 'hasMany':
foreach ($values as $i => $value)
if (isset($values[$i][$association]))
$values[$i][$association][$key] = $this->id;
else
$values[$i] = array_merge(array($key => $this->id), $value, array($key => $this->id));
$values[$i][$association][$key] = $this->id;
我在这里转储了输出,本例 $values[$i][$association] = 3,它不是数组。
现在,查看发布的数据,我看不出有什么问题。和 cake1.3.14 一样。
发布数据的 var_dump:
array(3)
["Client"]=>
array(20)
["NAME"]=>
string(6) "ZZTEST"
["PHONE"]=>
string(0) ""
["X_PHONE2"]=>
string(0) ""
["FAX"]=>
string(0) ""
["EMAIL"]=>
string(0) ""
["X_REQUIRE_PO"]=>
string(1) "N"
["TAXREG"]=>
string(0) ""
["CREDLIMIT"]=>
string(5) "10000"
["X_QCHECKAPP"]=>
string(1) "Y"
["X_PUBLIC_LIABILITY_EXPIRY"]=>
string(10) "19-03-2014"
["ADDRESS1"]=>
string(0) ""
["ADDRESS2"]=>
string(0) ""
["POST_CODE"]=>
string(0) ""
["DELADDR1"]=>
string(0) ""
["DELADDR2"]=>
string(0) ""
["DELADDR6"]=>
string(0) ""
["NOTES"]=>
string(0) ""
["HEAD_ACCNO"]=>
int(-1)
["CURRENCYNO"]=>
int(0)
["AVE_DAYS_TO_PAY"]=>
int(-1)
["ClientRateGroup"]=>
array(1)
["rate_group_id"]=>
string(1) "3"
["ClientExtra"]=>
array(2)
["client_type_id"]=>
string(1) "1"
["client_salesperson_id"]=>
string(2) "25"
控制器的一个sn-p:
class ClientsController extends AppController
public $name = 'Clients';
public $uses = array('ExonetClient', 'Quote');
// The saveAll call is causing the problem
function add()
if (!empty($this->request->data))
$this->request->data['ExonetClient']['HEAD_ACCNO'] = -1;
$this->request->data['ExonetClient']['CURRENCYNO'] = 0;
$this->request->data['ExonetClient']['AVE_DAYS_TO_PAY'] = -1;
$this->Client->create();
unset($this->ExonetClient->ClientRateGroup->validate['client_id']);
unset($this->ExonetClient->ClientExtra->validate['client_id']);
// Allow an entry to clients_rate_groups table if the rate group is
//selected for a client
if (!empty($this->request->data['ClientRateGroup']['rate_group_id'])
|| !empty($this->request->data['ClientExtra']['client_type_id'])
)
if ($this->ExonetClient->saveAll($this->request->data, array('validate' => true)) === true)
//
// If an AJAX request, then echo the ID of the item.
if ($this->RequestHandler->isAjax())
echo $this->ExonetClient->getLastInsertId();
exit;
else
$this->Session->setFlash(
__('The client has been saved successfully'),
'default',
array('class' => 'success')
);
$this->redirect(array('action' => 'index'));
else
$error = __('The client could not be saved. Please, try again.');
if ($this->RequestHandler->isAjax())
$this->set('error_message', $error);
else
$this->Session->setFlash($error);
以下是相关模型:
客户:
App::uses('AppModel', 'Model');
class ExonetClient extends AppModel
public $name = 'ExonetClient';
public $actsAs = array(
'CakephpAssets.Logable' => array('change' => 'serialize', 'userModel' => 'User', 'userKey' => 'user_id'),
'LocationStorage' => array(),
);
public $useDbConfig = 'exonet';
public $useTable = 'DR_ACCS';
public $primaryKey = 'ACCNO';
public $displayField = 'NAME';
public $hasMany = array(
'ContactLink' => array(
'className' => 'ExonetClientContact',
'foreignKey' => 'ACCNO',
'dependent' => true,
),
'SubcontractorIncompatibility' => array(
'className' => 'ClientsSubcontractor',
'foreignKey' => 'client_id',
'dependent' => true,
),
'Docket' => array(
'className' => 'Docket',
'foreignKey' => 'client_id',
'dependent' => false,
),
'SpreadsheetQueue' => array(
'className' => 'SpreadsheetQueue',
'foreignKey' => 'client_id',
'dependent' => false,
),
'Spreadsheet' => array(
'className' => 'Spreadsheet',
'foreignKey' => 'client_id',
'dependent' => false,
),
'ClientRateGroup' => array(
'className' => 'ClientRateGroup',
//'joinTable' => 'clients_rate_groups',
'foreignKey' => 'client_id',
//'associationForeignKey' => 'client_id',
//'unique' => true,
'dependent' => true,
'conditions' => '',
//'fields' => '',
'order' => array('effective_date' => 'DESC', 'expiry_date' => 'DESC'),
'limit' => '',
'offset' => '',
'finderQuery' => ''
//'deleteQuery' => '',
//'insertQuery' => ''
),
);
ClientExtra:
App::uses('AppModel', 'Model');
class ClientExtra extends AppModel
public $name = 'ClientExtra';
public $validate = array(
'client_type_id' => array(
'numeric' => array(
'rule' => array('numeric'),
'allowEmpty' => true,
),
),
'client_id' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
public $belongsTo = array(
'ClientType' => array(
'className' => 'ClientType',
'foreignKey' => 'client_type_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Client' => array(
'className' => 'ExonetClient',
'foreignKey' => 'client_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Salesperson' => array(
'className' => 'Salesperson',
'foreignKey' => 'client_salesperson_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
ClientRateGroup:
App::uses('AppModel', 'Model');
class ClientRateGroup extends AppModel
public $useTable = 'clients_rate_groups';
public $name = 'ClientRateGroup';
public $validate = array(
'rate_group_id' => array(
'numeric' => array(
'rule' => array('numeric'),
'allowEmpty' => true,
),
),
'client_id' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
'effective_date' => array(
'date' => array(
'rule' => array('date'),
),
),
);
public $belongsTo = array(
'RateGroup' => array(
'className' => 'RateGroup',
'foreignKey' => 'rate_group_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Client' => array(
'className' => 'ExonetClient',
'foreignKey' => 'client_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
【问题讨论】:
请注意,您的错误消息中的行号与您在 2.4.2 中显示的型号代码不匹配 我在里面有一些调试语句,一定是把行号弄错了。绝对是 2.4.2 代码库 【参考方案1】:您的数据格式不正确,无法保存hasMany
关联数据。检查docs for Model::saveAssociated()
:
为了保存一条记录及其具有hasMany关联的相关记录,数据数组应该是这样的:
$data = array( 'Article' => array('title' => 'My first article'), 'Comment' => array( array('body' => 'Comment 1', 'user_id' => 1), array('body' => 'Comment 2', 'user_id' => 12), array('body' => 'Comment 3', 'user_id' => 40), ), );
所以你的ClientRateGroup
键应该包含一个数据数组的数组,类似于:
'ClientRateGroup' => array(
array('rate_group_id' => 3)
)
也许你的ClientExtra
数据也应该这样格式化,不确定Client
模型上没有适当的关联,很可能这实际上应该是Client hasOne ClientExtra
关联,很难说。
【讨论】:
自蛋糕 1.3.14 以来这是否发生了变化?我将尝试按照 saveAssociated 文档重新格式化请求。 @AdamP 我不确定,现在无法测试,但 1.3 的书提倡相同的风格:book.cakephp.org/1.3/en/The-Manual/Developing-with-CakePHP/…以上是关于cakephp 模型 saveAssociated 错误 - 不能将字符串偏移量用作数组的主要内容,如果未能解决你的问题,请参考以下文章
Cakephp:使用`saveAssociated()`时如何将`parent_id`保存到基于树的模型中?
Cakephp saveAssociated 和 SaveAll Nothing 正常工作