补充其他答案;要仅获取单个字段的值,请使用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 "contains",您应该使用'%' . $station . '%'
. 对于“开始于”使用$station . '%'
- 正如@mark 所建议的那样;
beforeSave()
是模型的回调,应该位于那里。还; beforeSave()
在验证发生后触发,因此可能为时已晚。beforeValidate()
是最好的回调
- 如果
Experience
模型已经附加到Station
模型上,则不需要使用组件,因为您可以直接访问Station
模型。最好将 search-method 放在Station
模型中;
将其全部移动到右侧(*)位置
*) 其他选项总是可能的,这只是一种可能的方法
将“搜索”方法添加到 Station-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');
}
..并在体验模型中使用它
应用程序/模型/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);
}
[更新] 使用约定,防止不必要的行为
写完前面的例子后,我注意到你当前的设置有一些缺陷;
- 如果vertrekstation和aankomststation应该持有站点的“外键”(站点ID),则它们不是根据CakePHP 模型和数据库约定命名的
- 因为
1)
通过把这段代码放在里面,更新现有记录beforeValidate()
时也会触发。因为您使用aankomststation和vertrekstation字段来保存电台的名称(在表单内)和id (在数据库内),所以模型将在更新时尝试通过id查找 station-id 。请注意,在表单中,您仍将使用vertrekstation和aankomstation作为字段名称。这些字段名称不是存在于您的数据库中,因此将无法直接更新数据库中的数据,这就是beforeValidate()
回调的用途
- 因为
Experience
模型需要与模型的两个关系Station
(一次为departure station
( 'vertrekstation' ),一次为arrival station
( 'aankomststation' )),所以您需要 Station-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);
}
}