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);
        }
    
    }
    
    [更新]使用约定,防止不必要的行为 在写了前面的示例之后,我注意到您当前的设置中存在一些缺陷

  • 如果vertrekstation和aankomststation应持有站点的“外键”(站点-id),则不会根据
  • 由于
    1)
    将此代码放在
    beforeValidate()
    中,因此在更新现有记录时也会触发此代码。由于您正在使用aankomststation和vertrekstation字段来保存站点名称(在表单中)和id(在数据库中),因此模型将在更新时尝试通过id查找站点id。请注意,在表单中仍将使用vertrekstation和aankomstation作为字段名。数据库中不存在这些字段名,因此无法直接更新数据库中的数据,这就是使用
    beforeValidate()
    回调的原因
  • 由于
    体验
    模型需要与
    车站
    模型有两种关系(一种是
    始发站
    ('vertrekstation'),另一种是
    到达站
    ('aankomststation')),因此您需要车站模型的别名。见:
  • 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);
        }
    
    }
    

    您不应该使用
    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