龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > php编程 >

DBO Form Widget

时间:2014-07-22 14:52来源: 作者: 点击:
分享到:
这是一个十分有用的组件,可用于生成一个数据的编辑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
// 要操作的對象的數據
// $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);
		}
	}
}

4. [图片] 有图有真相    

精彩图集

赞助商链接