我已经研究了一下,我发现CakePHP的表单帮助器不能正确解释ENUM字段,所以它只是输出一个文本输入。我发现了一个帖子,建议使用一个助手来实现这个特定的目的。有人知道更好的方法吗?或者如果CakePHP开发人员打算在某一天纠正这个问题?
感谢阅读!
下面是一个助手扩展。
App::uses('FormHelper', 'View/Helper');
/**
* APP/View/Helper/MySqlEnumFormHelper.php
* It extends FormHelper to implement ENUM datatype of MySQL.
*
* http://blog.xao.jp/blog/cakephp/implementation-of-mysql-enum-datatype-in-formhelper/
*
* created Oct. 15, 2012
* CakePHP 2.2.3
*/
class MySqlEnumFormHelper extends FormHelper
{
public function input($fieldName, $options = array())
{
if (!isset($options['type']) && !isset($options['options'])) {
$modelKey = $this->model();
if (preg_match(
'/^enum((.+))$/ui',
$this->fieldset[$modelKey]['fields'][$fieldName]['type'],
$m
)) {
$match = trim($m[1]);
$qOpen = substr($match, 0, 1);
$qClose = substr($match, -1);
$delimiter = $qOpen . ',' . $qClose;
preg_match('/^'.$qOpen.'(.+)'.$qClose.'$/u', $match, $m);
$_options = explode($delimiter, $m[1]);
$options['type'] = 'select';
$options['options'] = array_combine($_options, $_options);
}
}
return parent::input($fieldName, $options);
}
}
Cake试图成为数据库不可知论,因此这个问题不会被"纠正",因为它不是一个bug。例如,SQL server没有一个完全等价于MySQL的ENUM字段类型。
我建议像这样获取枚举值的可能列表:
YourController.php
// get column type
$type = $this->Model->getColumnType('field');
// extract values in single quotes separated by comma
preg_match_all("/'(.*?)'/", $type, $enums);
// enums
var_dump($enums[1]);
然后在视图中使用select
字段并将枚举作为选项传递。你已经拥有了当前的价值。听起来怎么样?
我是cakephp的新手,我找到了一些旧代码并拼凑了一个enum选择框供您欣赏
/**
* Behavior with useful functionality around models containing an enum type field
*
* Copyright (c) Debuggable, http://debuggable.com
*
*
*
* @package default
* @access public
*
* reworked by Nathanael Mallow for cakephp 2.0
*
*/
/*
*Use case:Add this (EnumerableBehavior.php) to app/Model/Behavior/
* -->in the Model add public $actsAs = array('Enumerable');
* -->in the *_controller add $enumOptions = $this->Categorie->enumOptions('Section');
* -->in the view add print $this->Form->input('{db_field_name}', array('options' => $enumOptions, 'label' => 'here'));
*
*
*/
class EnumerableBehavior extends ModelBehavior {
/**
* Fetches the enum type options for a specific field
*
* @param string $field
* @return void
* @access public
*/
function enumOptions($model, $field) {
//Cache::clear();
$cacheKey = $model->alias . '_' . $field . '_enum_options';
$options = Cache::read($cacheKey);
if (!$options) {
$sql = "SHOW COLUMNS FROM `{$model->useTable}` LIKE '{$field}'";
$enumData = $model->query($sql);
$options = false;
if (!empty($enumData)) {
$enumData = preg_replace("/(enum|set)('(.+?)')/", '\2', $enumData[0]['COLUMNS']['Type']);
$options = explode("','", $enumData);
}
Cache::write($cacheKey, $options);
}
return $options;
}
}
?>
如果你想用MySqlEnumFormHelper
代替normal,用$this->Form->
代替$this->MySqlEnumFormHelper
。您应该在控制器中添加这一行,将MySqlEnumFormHelper
别名为Form
。
public $helpers = array('Form' => array(
'className' => 'MySqlEnumForm'
));
/* 评论现在答案* * *
- 用例:添加这个(EnumerableBehavior.php)到app/Model/Behavior/
- ->在模型中添加公共$actsAs = array('Enumerable');
- ->在*_controller的动作中添加$enumOptions = $this->YourModelName->enumOptions('db_field_name');$ this ->设置(enumOptions, enumOptions美元);
- ->在视图中添加print $this->Form->input('{db_field_name}', array('options' => $enumOptions, 'label' => 'here'));**/
我认为行为方式很好…但数组键是整型
所以我像这样修改了这个函数
function enumOptions($model, $field) {
//Cache::clear();
$cacheKey = $model->alias . '_' . $field . '_enum_options';
$options = Cache::read($cacheKey);
$enumOptions = array();
if (!$options) {
$sql = "SHOW COLUMNS FROM `{$model->useTable}` LIKE '{$field}'";
$enumData = $model->query($sql);
$options = false;
if (!empty($enumData)) {
$enumData = preg_replace("/(enum|set)('(.+?)')/", '\2', $enumData[0]['COLUMNS']['Type']);
$options = explode("','", $enumData);
foreach ($options as $option) {
$enumOptions["$option"] = $option;
}
}
Cache::write($cacheKey, $enumOptions);
}
return $enumOptions;
}
以便在提交表单时能够在db字段中保存正确的值
我在AppController中创建了一个函数来处理这个。我综合了上面提供的一些信息。
用法:
$enumList = getEnumValues($ModelField) where ModelField is in this format: 'Model.Field'
我放在AppController中的函数:
function getEnumValues($ModelField){
// split input into Model and Fieldname
$m = explode('.', $ModelField);
if ($m[0] == $ModelField) {
return false;
} else {
(! ClassRegistry::isKeySet($m[0])) ? $this->loadModel($m[0]): false;
$type = $this->$m[0]->getColumnType($m[1]);
preg_match_all("/'(.*?)'/", $type, $enums);
foreach ($enums[1] as $value){$enumList[$value] = $value;}
return $enumList;
}
}