beforeSave
函数中,我想操作一些$this->request->data
条目。
这是我的组成部分:
<?php
App::uses('Component', 'Controller');
class GetStationComponent extends Component {
public function getStationId ($station) {
$stationInstance = ClassRegistry::init('Station');
$conditions = array('OR' => array(
array('Station.code LIKE' => $station),
array('Station.naam LIKE' => $station),
array('Station.naam_overig LIKE' => $station)
));
$result = $stationInstance->find('list', array('conditions'=>$conditions));
$value = array_values($result);
$value = $value[0];
return $value;
}
}
?>
这是我在Controller中的beforeSave函数:
public function beforeSave($options = array()) {
if (!empty($this->request->data['Experience']['vertrekstation']) && !empty($this->request->data['Experience']['aankomststation'])) {
$this->request->data['Experience']['vertrekstation'] = $this->GetStation->getStationId($this->request->data['Experience']['vertrekstation']);
$this->request->data['Experience']['aankomststation'] = $this->GetStation->getStationId($this->request->data['Experience']['aankomststation']);
}
return true;
}
它应该返回站名的ID。但是在数据库中,名称本身被存储(由用户填写)而不是ID。我需要在我的组件中更改(我猜...)以返回正确的值?
(PS组件中的查询本身返回一个ID,因为起初我将'beforeSave'直接放入我保存数据的函数中,但是我的验证错误表明它不是正确的值。哪个是正确的......)
答案 0 :(得分:1)
补充其他答案;要获得单个字段的值,请使用Model::field()
return $stationInstance->field('id', $conditions);
最好在此语句中添加排序顺序,以确保始终以相同的顺序返回结果:
return $stationInstance->field('id', $conditions, 'code ASC');
由于您只对模型执行单个查询,之后不执行任何操作,因此您甚至不需要中间$stationInstance
变量。您的代码可以进一步简化为:
return ClassRegistry::init('Station')->field('id', $conditions, 'code ASC');
Den Haag
时阻止选择Den Haag HS
)%
查询,您未使用LIKE
包围搜索字词。如果您打算搜索“name ”包含“,则应使用'%' . $station . '%'
。对于“以”开头“使用$station . '%'
beforeSave()
是模型的回调,应位于此处。
也;验证发生后会触发beforeSave()
,因此可能为时已晚。 beforeValidate()
是此Experience
模型已附加到Station
模型,则无需使用组件,因为您可以直接访问Station
模型。最好将搜索方法放在Station
模型中; *)其他选项总是可行的,这只是可能的方法
将“搜索”方法添加到工作站模型;
应用程序/型号/ Station.php
public function getStationIdByName($name)
{
$name = trim($name);
if (empty($name)) {
return null;
}
$name = '%' . $name . '%';
$conditions = array(
'OR' => array(
array($this->alias . '.code LIKE' => $name),
array($this->alias . '.naam LIKE' => $name),
array($this->alias . '.naam_overig LIKE' => $name),
)
);
return $this->field('id', $conditions, 'code ASC');
}
..并在体验模型中使用它
应用程序/型号/ Experience.php
public function beforeValidate(array $options = array())
{
if (
!empty($this->data[$this->alias]['vertrekstation'])
&& !empty($this->data[$this->alias]['aankomststation'])
) {
// Directly access the Station-model from within the Experience Model
$this->data[$this->alias]['vertrekstation']
= $this->Station->getStationIdByName($this->data[$this->alias]['vertrekstation']);
$this->data[$this->alias]['aankomststation']
= $this->Station->getStationIdByName($this->data[$this->alias]['aankomststation']);
}
// Call parent-callback after setting the values
return parent::beforeValidate($options);
}
在写完前一个例子之后,我注意到你当前的设置存在一些缺陷;
1)
将此代码放在beforeValidate()
内,当 更新 现有记录时,也会触发此代码。因为您使用 aankomststation 和 vertrekstation 字段来保存工作站的名称(在表单内)和 id (在数据库内),模型将在更新时尝试通过 id 查找station-id。请注意在表单 中,您仍然会使用 vertrekstation 和 aankomstation 作为字段名称。这些字段名称 not 存在于您的数据库中,因此无法直接更新数据库中的数据,这是beforeValidate()
回调用于Experience
模型需要与Station
模型的两个关系(一次为departure station
('vertrekstation'),一次用于arrival station
('aankomststation')),您需要一个用于Station模型的别名。请参阅:Multiple relations to the same model 应用程序/型号/ Experience.php
class Experience extends AppModel {
/**
* Station will be associated to the 'Experience' Model TWICE
* For clarity, using an 'alias' for both associations
*
* The associated Models will be accessible via;
* $this->DepartureStation
* $this->ArrivalStation
*
* To stick to the CakePHP conventions, name the foreign keys
* accordingly
*/
public $belongsTo = array(
'DepartureStation' => array(
'className' => 'Station',
'foreignKey' => 'departure_station_id',
),
'ArrivalStation' => array(
'className' => 'Station',
'foreignKey' => 'arrival_station_id',
)
);
public function beforeValidate(array $options = array())
{
// vertrekstation and aankomststation hold the 'names' of the
// stations and will only be present if the form has been submitted
if (
!empty($this->data[$this->alias]['vertrekstation'])
&& !empty($this->data[$this->alias]['aankomststation'])
) {
// Directly access the Station-model from within the Experience Model
// using the *aliases*
$this->data[$this->alias]['departure_station_id']
= $this->DepartureStation->getStationIdByName($this->data[$this->alias]['vertrekstation']);
$this->data[$this->alias]['arrival_station_id']
= $this->ArrivalStation->getStationIdByName($this->data[$this->alias]['aankomststation']);
// Invalidate the vertrekstation and aankomststation fields if lookup failed
if (empty($this->data[$this->alias]['departure_station_id'])) {
// Unable to find a station. Mark the Form-field invalid
$this->invalidate('vertrekstation', __('A station with this name was not found'));
}
if (empty($this->data[$this->alias]['arrival_station_id'])) {
// Unable to find a station. Mark the Form-field invalid
$this->invalidate('aankomststation', __('A station with this name was not found'));
}
}
// Call parent-callback after setting the values
return parent::beforeValidate($options);
}
}
答案 1 :(得分:0)
Cake的find('list')选项返回一个类似
的数组array( 1 => 'name1',
3 => 'name2',
//etc...
)
其中index是id,值是您在模型上设置的显示字段。
因此,当您执行$value = array_values($result);
时,您将提取数组的值(即显示字段)。我假设你没有使用id作为displayField,所以这就是为什么它返回名字而不是id。
我不确定你为什么使用find('list')而不是find('first')或其他替代方法,但如果你不想因为某种原因修改它,应该返回的修复搜索获得的第一个ID是
reset($result); //possibly not needed, but just in case
$value = key($result );
答案 2 :(得分:0)
首先,您必须了解Cake的工作原理
您的模型中没有$this->request
。它是控制器的一部分。
在您的模型中,您传递的数据将直接在$this->data
。
public function beforeSave($options = array()) {
parent::beforeSave($options); // you also forgot the parent call
if (!empty($this->data[$this->alias]['vertrekstation']) && ...)) {
$this->data[$this->alias]['vertrekstation'] = ...;
}
return true;
}
您的查找电话也看起来很糟糕。我不知道你想做什么。 但我强烈建议您使用debug()等来找出返回的内容并相应地更正您的代码。 如果你只对一个值感兴趣,你可能需要找到(第一个)。