Cakephp 自定义组件赢得';t返回值
好的,情况就是这样。在我的Cakephp 自定义组件赢得';t返回值,cakephp,cakephp-2.0,custom-component,Cakephp,Cakephp 2.0,Custom Component,好的,情况就是这样。在我的beforeSave函数中,我想处理一些$this->request->data条目 这是我的组件: <?php App::uses('Component', 'Controller'); class GetStationComponent extends Component { public function getStationId ($station) { $stationInstance = ClassRegistry::init
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;
}
}
?>
它应该返回站点名称的ID。但是在数据库中存储的是名称本身(由用户填写),而不是ID。我需要在我的组件中更改什么(我猜…)才能返回正确的值
(另一方面,组件中的查询本身返回一个ID,因为起初我将“beforeSave”直接放入保存数据的函数中,但随后我的验证错误表明它不是正确的值。这是正确的…Cake的find('list')选项返回如下数组
array( 1 => 'name1',
3 => 'name2',
//etc...
)
其中,索引是id,值是在模型上设置的显示字段。
因此,当您执行$value=array\u values($result)代码>,您正在提取数组的值(即显示字段)。我假设您没有使用id作为显示字段,所以它返回的是名称而不是id
我不知道为什么要使用find('list')而不是find('first')或其他替代方法,但是如果您不想出于任何原因修改它,那么应该返回搜索获得的第一个id的修复程序是
reset($result); //possibly not needed, but just in case
$value = key($result );
首先你必须了解蛋糕是如何工作的
您的型号中没有$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()等来找出返回的内容并相应地更正代码。
如果你只对一个值感兴趣,你可能需要(首先)找到它。补充其他答案;要仅获取单个字段的值,请使用
最好在此语句中添加排序顺序,以确保结果始终以相同的顺序返回:
return $stationInstance->field('id', $conditions, 'code ASC');
由于您只对模型执行一个查询,之后不做任何事情,因此您甚至不需要中间的$stationInstance
变量。您的代码可以进一步简化为:
return ClassRegistry::init('Station')->field('id', $conditions, 'code ASC');
一些观察
- 由于站点名称上的“模糊”匹配,第一个结果可能并不总是用户想要的站点。最好在前端提供“自动完成”功能,并让用户选择正确的站点(例如,当用户想要选择
Den Haag HS
时,防止选择Den Haag
)
- 如果电台与某个电台不完全匹配,则应显示未找到该电台的警告
- 对于
类
查询,您没有用%
包围搜索词。如果要搜索“name”contains,应使用“%”$车站.“%”代码>。对于“以开头”,请使用$station.%'代码>
- 正如@mark所建议的
beforeSave()
是模型的回调,应该位于那里。
还有,<代码>beforeSave()
在验证完成后触发,因此可能太晚了beforeValidate()
是此操作的最佳回调
体验
模型已连接到站点
模型,则无需使用组件,因为您可以直接访问站点
模型。最好将搜索方法放在站点
模型中李>
将其全部移动到正确的(*)位置
*)其他选择总是可能的,这只是一种可能的方法
将“搜索”方法添加到站点模型中
app/Model/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');
}
…并在体验模型中使用它
app/Model/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);
}
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)
将此代码放在beforeValidate()
中,因此在更新现有记录时也会触发此代码。由于您正在使用aankomststation和vertrekstation字段来保存站点名称(在表单中)和id(在数据库中),因此模型将在更新时尝试通过id查找站点id。请注意,在表单中仍将使用vertrekstation和aankomstation作为字段名。数据库中不存在这些字段名,因此无法直接更新数据库中的数据,这就是使用beforeValidate()
回调的原因体验
模型需要与车站
模型有两种关系(一种是始发站
('vertrekstation'),另一种是到达站
('aankomststation')),因此您需要车站模型的别名。见: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);
}
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);
}
}
您不应该使用
array\u keys()
而不是array\u values()
?或者只需key($result)
即可获得结果中的第一个键。最后,您需要检查$result
是否实际包含一个结果,也许find('first')
在这里更合适,我不知道为什么,但是如果我使用find('first')
它会返回一个数组数组('Station'=>数组('id'=>'132'))
。然后我必须再次修改它。我实际上在寻找的只是从我的列表中提取id,一个常规的MySQL查询如下:'SELECT Experience.id from Experience WHERE Experience.code like{$value}或Experience.naam like{$value}或Experience.naam_overig like{$value}
,但出于某种原因,我无法通过Cake的方式获得此信息……好的,我的错误。。。在我的凝视中,我没有看到它实际上是一个Ca