DBO Form Widget
这是一个十分有用的组件,可用于生成一个数据的编辑form,他是MST Library 3.1一个十分重要的组件,可以实现dbo form和dbo form的循环嵌套,而且控制在一个form中,同时支持dbo form中再次嵌套
这是一个十分有用的组件,可用于生成一个数据的编辑form,他是MST Library 3.1一个十分重要的组件,可以实现dbo form和dbo form的循环嵌套,而且控制在一个form中,同时支持dbo form中再次嵌套自定义的widget组件。
很多PHP框架,将form的生成写在函数,这是无可厚非的,但是你无法接收在生成一个form的时候,循环调用用户函数所付出的性能成本,这时候,构建一个php和html混编的代码,远比循环执行函数的性能要高。
而且,多数时候,我们知道一个数据对象的结构,也已经定义了数据对象的每个字段的值类型,我们真的没有必要再去手动写什么form,或者还要用代码去判断,这个用select,那个用textarea什么的。
很多PHP框架,将form的生成写在函数,这是无可厚非的,但是你无法接收在生成一个form的时候,循环调用用户函数所付出的性能成本,这时候,构建一个php和html混编的代码,远比循环执行函数的性能要高。
而且,多数时候,我们知道一个数据对象的结构,也已经定义了数据对象的每个字段的值类型,我们真的没有必要再去手动写什么form,或者还要用代码去判断,这个用select,那个用textarea什么的。
<?php // 要操作的對象的數據 // $target必須為基於MST_DBO的實例 if (!isset($data) || !is_object($data) || !$data instanceof MST_DBO) { echo '$data not a MST_DBO instance!'; } else { // 獲取關聯的模塊 $model = get_class($data); // 定義$columns // 如果未定義,默認根據MST_DBO的接口來取 if (!isset($columns)) $columns = $data->getFormColumns($data); if (empty($columns) || !is_array($columns)) { echo 'undefine form columns!'; } else { // 生成該模塊的前綴 if (!isset($prefix)) $prefix = strtolower($model); else $prefix = MST_String::tableize($prefix); if (!isset($id)) $id = $prefix . '_form'; if (!isset($class)) $class = $prefix . '-form'; $errors = $data->getErrors(); // 初始化Form配置 // 定制提交的action if (!isset($action)) $action = $this->params->uri; // method if (!isset($method)) $method = 'post'; else { $method = strtolower((string)$method); if ($method != 'get' && $method != 'post') $method = 'post'; } // 是否需要上傳 if (!isset($isUpload)) $isUpload = true; // 定制提交按鈕的文字 if (!isset($submitText)) $submitText = 'Submit'; // 定制label部分的寬度 if (!isset($headWidth)) $headWidth = 130; $headWidth = is_numeric($headWidth) && $headWidth > 0 ? $headWidth : 120; if (!isset($continueForm)) $continueForm = false; // 重載 if (!isset($lineStart)) $lineStart = 1; ?> <?php if (!$continueForm) { ?> <form id="<?php echo $id; ?>" action="<?php echo $action; ?>" method="<?php echo $method; ?>"<?php if ($isUpload) echo ' enctype="multipart/form-data"'; ?>> <table class="table-form <?php echo $class; ?>" border="0" cellpadding="0" cellspacing="0" width="100%"> <?php } ?> <?php $lineNum = $lineStart; $tinymceTimes = 0; foreach ($columns as $key => $column) { // 跳過$column[0]為空的部分 if (!isset($column[0])) continue; // 定制一行的$column常用變量 $key = strtolower(trim($key)); $columnId = $prefix . '_' . $key; $columnName = $prefix . '[' . $key . ']'; $columnClass = $prefix . '-' . $key; $columnText = empty($column['title']) ? ucfirst($key) : $column['title']; $columnValue = isset($data[$key]) ? (string)$data[$key] : (isset($column['default']) ? $column['default'] : null); if (isset($column['forceValue'])) $columnValue = (string)$column['forceValue']; $isDisabled = isset($column['disabled']) ? $column['disabled'] : false; $isReadonly = isset($column['readonly']) ? $column['readonly'] : false; if (is_object($column[0]) && $column[0] instanceof Closure) { $editType = 'closure'; } else { $editType = strtolower($column[0]); } ?> <?php if ($editType == 'dbo_form') { if (empty($column[1])) { // 缺少dbo_form重用說明 ?> <tr> <td colspan="2">Can't reuse dbo_form, please set the dbo_form options in $column[1].</td> </tr> <?php } else { $column[1]['continueForm'] = true; $this->widget('base/dbo_form', $column[1]); } ?> <?php } else if ($editType == 'custom') { ?> <tr> <th colspan="2" class="f-custom <?php echo $columnClass; ?>"> <?php if (!empty($column['content'])) echo $column['content']; ?> </th> </tr> <?php } else if ($editType == 'custom_widget') { ?> <tr> <td colspan="2" class="f-widget <?php echo $columnClass; ?>"> <?php $this->widget($column[1], $column[2]); ?> </td> </tr> <?php } else if ($editType == 'hidden') { ?> <input type="hidden" id="<?php echo $columnId; ?>" name="<?php echo $columnName; ?>" value="<?php echo $columnValue; ?>" /> <?php } else { ?> <?php $lineClass = $lineNum % 2 == 0 ? 'f-line f-line-odd' : 'f-line f-line-even'; ?> <tr id="<?php echo 'form_row_', $lineNum; ?>" class="<?php echo $lineClass; ?>"> <td class="f-head" width="<?php echo $headWidth; ?>"><label for="<?php echo $columnId; ?>"><?php echo $columnText; ?></label></td> <td class="f-body"> <?php // 開始生成form行 switch ($editType) { case 'text' : ?> <input type="text" id="<?php echo $columnId; ?>" name="<?php echo $columnName ?>" value="<?php echo $columnValue; ?>" class="f-text <?php echo $columnClass; ?>"<?php if (isset($column['max'])) echo ' maxlength="',$column['max'],'"'; if ($isDisabled) echo ' disabled="disabled"'; if ($isReadonly) echo ' readonly="readonly"'; ?>/> <?php break; case 'smalltextarea' : ?> <textarea id="<?php echo $columnId; ?>" name="<?php echo $columnName ?>" style="height:100px;width:650px" class="f-text <?php echo $columnClass; ?>"<?php if (isset($column['max'])) echo ' maxlength="'.$column['max'].'"'; if ($isDisabled) echo ' disabled="disabled"'; if ($isReadonly) echo ' readonly="readonly"'; ?>><?php echo $columnValue; ?></textarea> <?php break; case 'longtext' : ?> <input type="text" id="<?php echo $columnId; ?>" name="<?php echo $columnName ?>" value="<?php echo $columnValue; ?>" class="f-longtext <?php echo $columnClass; ?>"<?php if (isset($column['max'])) echo ' maxlength="',$column['max'],'"'; if ($isDisabled) echo ' disabled="disabled"'; if ($isReadonly) echo ' readonly="readonly"'; ?>/> <?php break; case 'upload' : ?> <input id="<?php echo $columnId; ?>" name="<?php echo $columnName ?>" type="file" name="ufile" value="Browse" /> <?php break; case 'password' : ?> <input type="password" id="<?php echo $columnId; ?>" name="<?php echo $columnName ?>" value="<?php echo $columnValue; ?>" class="f-text <?php echo $columnClass; ?>"<?php if (isset($column['max'])) echo ' maxlength="'.$column['max'].'"'; if ($isDisabled) echo ' disabled="disabled"'; if ($isReadonly) echo ' readonly="readonly"'; ?>/> <?php break; case 'textarea' : ?> <textarea id="<?php echo $columnId; ?>" name="<?php echo $columnName ?>" class="f-text <?php echo $columnClass; ?>"<?php if ($isDisabled) echo ' disabled="disabled"'; if ($isReadonly) echo ' readonly="readonly"'; ?>><?php echo $columnValue; ?></textarea> <?php break; case 'select' : $options = isset($column['options']) ? $column['options'] : array(); $optionsType = isset($column['optionsType']) ? $column['optionsType'] : 'map'; // 向前兼容:0 -> map, 1 -> list if (is_numeric($optionsType)) $optionsType = $optionsType > 0 ? 'list' : 'map'; ?> <select id="<?php echo $columnId; ?>" name="<?php echo $columnName ?>" class="f-select <?php echo $columnClass; ?>"<?php if ($isDisabled) echo ' disabled="disabled"'; ?>> <?php if (isset($column['firstOption'])) { ?> <option<?php if (empty($columnValue)) echo ' selected="selected"'; ?> value=""><?php echo $column['firstOption']; ?></option> <?php } ?> <?php foreach ($options as $key => $option) { ?> <?php if ($optionsType == 'map') { ?> <option<?php if ($key == $columnValue) echo ' selected="selected"'; ?> value="<?php echo $key; ?>"><?php echo $option; ?></option> <?php } else if ($optionsType == 'list') { ?> <?php $option = array_values((array)$option); if (isset($option[0])) { ?> <option<?php if ($columnValue == $option[0]) echo ' selected="selected"'; ?> value="<?php echo $option[0]; ?>"><?php echo isset($option[1]) ? $option[1] : $option[0]; ?></option> <?php } ?> <?php } ?> <?php } ?> </select> <?php break; case 'radiogroup' : $maps = isset($column['maps']) ? $column['maps'] : array(); $mapsType = isset($column['mapsType']) ? $column['mapsType'] : 'map'; // 向前兼容:0 -> map, 1 -> list if (is_numeric($mapsType)) $mapsType = $mapsType > 0 ? 'list' : 'map'; ?> <div class="f-inline-box"> <input type="hidden" name="<?php echo $columnName; ?>" value="<?php echo $columnValue; ?>" /> <?php $index = 0; foreach ($maps as $key => $map) { $index++; ?> <?php if ($mapsType == 'map') { ?> <input type="radio" name="<?php echo $columnName; ?>" id="<?php echo $columnId . "_{$index}"; ?>" class="f-radio" value="<?php echo $key; ?>"<?php if ($columnValue == $key) echo ' checked="checked"'; ?> /> <label for="<?php echo $columnId . "_{$index}"; ?>" class="f-label"><?php echo $map; ?></label> <?php } else if ($mapsType == 'list' && isset($map[0])) { ?> <input type="radio" name="<?php echo $columnName; ?>" id="<?php echo $columnId . "_{$index}"; ?>" class="f-radio" value="<?php echo $map[0]; ?>"<?php if ($columnValue == $map[0]) echo ' checked="checked"'; ?> /> <label for="<?php echo $columnId . "_{$index}"; ?>" class="f-label"><?php echo isset($map[1]) ? $map[1] : $map[0]; ?></label> <?php } ?> <?php } ?> </div> <?php break; case 'datetime': $format = empty($column['dateFormat']) ? 'Y-m-d H:i:s' : $column['dateFormat']; $jsFormat = empty($column['jsFormat']) ? '%Y-%m-%d %H:00' : $column['jsFormat']; $pickSize = isset($column['pickSize']) ? intval($column['pickSize']) : 2; if ($columnValue > 0) { if (is_numeric($columnValue)) { $dtStr = date($format, $columnValue); $dtVal = $columnValue; } else { $dtStr = $columnValue; $dtVal = MST_String::date2num($columnValue); } } else { $dtStr = 0; $dtVal = 0; } if (is_numeric($dtVal) && $dtVal > 0) $dtStr = date($format, $dtVal); ?> <input type="text" id="<?php echo $columnId; ?>_str" class="f-text f-dt <?php echo $columnClass; ?>" value="<?php echo $dtStr; ?>" <?php if ($isDisabled) echo ' disabled="disabled"'; ?> /> <input type="hidden" name="<?php echo $columnName; ?>" id="<?php echo $columnId; ?>" value="<?php echo $dtVal; ?>" <?php if ($isDisabled) echo ' disabled="disabled"'; ?> /> <script type="text/javascript"> Agi.DatePicker.init('<?php echo $columnId; ?>_str', { format: '<?php echo $jsFormat; ?>', pickTime: <?php echo $pickSize; ?>, onChange: function() { document.id('<?php echo $columnId; ?>').set('value', (Number(this.value) / 1000).toInt()); } }); </script> <?php break; case 'tinymce' : $tinymceTimes++; ?> <?php if ($tinymceTimes == 1) { ?> <?php $this->script('tiny_mce/tiny_mce.js'); ?> <?php } ?> <script type="text/javascript"> tinyMCE.init({ // General options mode : "exact", elements: "<?php echo $columnId; ?>", theme : 'advanced', plugins : "safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template,wordcount,tabfocus", language: 'en', skin : "o2k7", skin_variant : "black", theme_advanced_buttons1 : "cut,copy,paste,pastetext,pasteword,|,undo,redo,|,search,replace,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,|,outdent,indent,blockquote,|,ltr,rtl,|,removeformat,cleanup,visualaid,|,code,preview", theme_advanced_buttons2 : 'bold,italic,underline,strikethrough,|,forecolor,backcolor,|,styleselect,hr,|,link,unlink,anchor,image', theme_advanced_buttons3 : '', theme_advanced_toolbar_location : "top", theme_advanced_toolbar_align : "left", theme_advanced_statusbar_location : "bottom", theme_advanced_resizing : true, tab_focus : ':prev,:next', convert_urls: false /* style_formats : [ { title: '字体样式' }, { title: '10px', inline: 'span', styles: { 'font-size': '10px' } }, { title: '12px', inline: 'span', styles: { 'font-size': '12px' } }, { title: '14px', inline: 'span', styles: { 'font-size': '14px' } }, { title: '16px', inline: 'span', styles: { 'font-size': '16px' } }, { title: '18px', inline: 'span', styles: { 'font-size': '18px' } }, { title: '20px', inline: 'span', styles: { 'font-size': '20px' } }, { title: '22px', inline: 'span', styles: { 'font-size': '22px' } }, { title: '格式辅助' }, { title: '清除段落段首', block: 'p', styles: { 'text-indent': '0' } }, { title: '清除H2段首', block: 'h2', styles: { 'text-indent': '0' } }, { title: '清除H3段首', block: 'h3', styles: { 'text-indent': '0' } }, { title: '清除H4段首', block: 'h4', styles: { 'text-indent': '0' } }, { title: '清除H5段首', block: 'h5', styles: { 'text-indent': '0' } }, { title: '清除H6段首', block: 'h6', styles: { 'text-indent': '0' } }, { title: '默认样式套用' }, { title: '左边浮动', block: 'div', classes: 'l' }, { title: '右边浮动', block: 'div', classes: 'r' }, { title: '清除浮动', block: 'div', classes: 'c' } ], */ <?php if (!empty($column['width']) && is_numeric($column['width'])) echo ',width : '. $column['width']; if (!empty($column['height']) && is_numeric($column['height'])) echo ',height : '. $column['height']; ?> }); </script> <textarea mce_editable="true" id="<?php echo $columnId; ?>" name="<?php echo $columnName; ?>" class="f-text f-ta <?php echo $columnClass; ?>" style="width:100%;"><?php echo $columnValue; ?></textarea> <?php break; case 'widget' : $this->widget($column[1], $column[2]); break; } $lineNum++; ?> <?php if (!empty($column['after'])) { ?> <span class="f-after"><?php echo $column['after']; ?></span> <?php } ?> <?php if (!empty($errors[$key])) { ?> <div class="f-error" id="<?php echo $columnId . '_tip' ?>"><?php echo $errors[$key]; ?></div> <?php } elseif (!empty($column['tip'])) { ?> <div class="f-tip" id="<?php echo $columnId . '_tip' ?>"><?php echo $column['tip']; ?></div> <?php } ?> </td> </tr> <?php } ?> <?php } ?> <?php if (!$continueForm) { ?> <tr class="f-submit-line"> <td></td> <td class="f-submit"> <?php if (is_array($submitText)) { ?> <?php $index = 0; foreach ($submitText as $btnId => $btnText) { $index++; ?> <input id="<?php echo $formId, '_', $btnId; ?>" class="f-btn" type="<?php echo $index == 1 ? 'submit' : 'button'; ?>" value="<?php echo $btnText; ?>" /> <?php } ?> <?php } else { ?> <input type="submit" class="f-btn f-btn-submit" value="<?php echo $submitText; ?>" /> <?php } ?> <?php $this->validCode($prefix, 'input'); ?> </td> </tr> </table> </form> <?php } ?> <?php } } ?>
2. [代码]页面调用的实例 跳至 [1] [2] [3] [全屏预览]
<?php $this->widget('base/dbo_form', array( 'data' => $this->list, ));
3. [代码]一个DBO Model的实例 跳至 [1] [2] [3] [全屏预览]
<?php class Testimonial extends MST_DBO { protected static $columns = array( 'firstname' => array('text','title' => 'First Name', 'require' => 1, 'min' => 1, 'max' => 32), 'lastname' => array('text','title' => 'Last Name', 'require' => 1, 'min' => 1, 'max' => 32), 'avator' => array('title' => 'Avator', 'max' => 256), 'age_group' => array('title' => 'Age Group', 'require' => 1), 'secret' => array('textarea','title' => 'Secret', 'require' => 1, 'min' => 10, 'max' => 600), ); public function getFormColumns() { if (GB_PERSSIONS == Region::ROOT) { $columns['region_id'] = array( 'select', 'title' => ' region ', 'optionsType' => 'list', 'options' => Region::find('all', array('select' => 'id, name')), ); } else { $columns['region_id'] = array( 'hidden', 'default' => GB_PERSSIONS, ); } $columns = array_merge($columns,self::$columns); $columns['age_group'] = array('widget', 'base/age_group', array( 'prefix' => 'testimonial', ), 'title' => 'Age Group'); $columns['avator'] = array('widget', 'base/testmonial_upload', array( 'prefix' => 'testimonial', ), 'title' => 'Avator'); return $columns; } public function beforeCreate(& $data) { $data['created_at'] = time(); } public function getAge() { $ageGroup = array( 0 => '--', 1 => 'Under 18', 2 => '19 ? 25', 3 => '26 ? 35', 4 => '36 ? 45', 5 => '46 ? 55', 6 => '56 or above', ); return isset($ageGroup[$this['age_group']]) ? $ageGroup[$this['age_group']] : $ageGroup[0]; } public function getAvator() { return empty($this['avator']) ? httpUri('images/avator.png') : httpUri($this['avator']); } // 这是对MST_DBO的find的方法的重载 static public function find($args = array(), $params = null, $isArray = false) { if (defined('GB_PERSSIONS') && GB_PERSSIONS == Region::ROOT) { self::initFind($args, $params, $isArray); return parent::find($args, $params, $isArray); } else { self::initFind($args, $params, $isArray); if (isset($args['where'])) { $args['where'][0] .= ' AND region_id = ?'; $args['where'][] = GB_PERSSIONS; } else { $args['where'] = array('region_id = ?', GB_PERSSIONS); } return parent::find($args, $params, $isArray); } } }
精彩图集
精彩文章