Hallo zusammen,
ich bin gerade dabei ein größeres Datenbankmodell zu entwickeln und gleichzeitig die CRUD templates etwas auszubauen.
Dazu würde mich eine rege Diskussion freuen, da ich bei vielen Punkten noch keine gute Idee habe.
Dazu noch vorweg: Es gibt sicherlich unterschiedliche Ansatzpunkte, viele werden wohl das Erstellen von CRUDs als einmalige Angelegenheit betrachten.
Allerdings gibt es auch Projekte, bei denen auch das Model zunächst einer größeren Entwicklung bedarf und zu Beginn des Projektes noch keine händischen Änderungen vorgenommen werden (sollen).
ich will keine eierlegende Wollmilchsau, sondern nur ein paar "convenience-addons".
Dann mal weiter zur Idee. Die nun folgende Beschreibung bezieht sich noch auf yiic, sollte aber mit gii analog funktionieren.
Ich habe das bestehende CrudCommand nach P2CrudCommand erweitert und die generateInputField() methode überschrieben.
public function generateInputField($modelClass,$column) {
// omit PK
if($column->isPrimaryKey)
return "''";
// render checkbox
else if($column->type==='boolean')
return "CHtml::activeCheckBox(\$model,'{$column->name}')";
// render relation dropdown
else if($column->isForeignKey) {
$model = new $modelClass;
foreach($model->relations() AS $name => $relation) {
if ($relation[2] == $column->name) {
return "CHtml::activeDropDownList(\$model,'{$column->name}', CHtml::listData({$relation[1]}::model()->findAll(), 'id', 'title'), array('prompt'=>'Select ...'));";
}
}
}
// render file autocomplete
else if(stripos($column->name,'p2File')!==false) {
return "P2Helper::widget('application.modules.p2.components.P2AutoComplete',
array(
'model' => \$model,
'attribute' => '".$column->name."',
'searchModel' => 'P2File',
'mode' => P2AutoComplete::MODE_SELECT,
'class' => 'ui-widget',)
);";
}
// render textarea input (with RTE)
else if(stripos($column->dbType,'text')!==false) {
$code = "CHtml::activeTextArea(\$model,'{$column->name}',array('rows'=>6, 'cols'=>50));";
// tiny addon
if(stripos($column->name,'html')!==false)
$code .= "\$this->widget('P2Editor',
array(
'name'=>'".$modelClass."_".$column->name."',
'type'=> Yii::app()->params['editor']['type'],
'height' => Yii::app()->params['editor']['height'],
'toolbar' => Yii::app()->params['editor']['toolbar'],
'config' => Yii::app()->params['editor']['config']
)
);";
return $code;
}
// render datepicker
else if(stripos($column->dbType,'date')!==false) {
$code = "P2Helper::widget('system.zii.widgets.jui.CJuiDatePicker',
array(
'model'=> \$model,
'attribute'=> '{$column->name}',
'htmlOptions'=>array('size'=>10),
'options' => array(
'dateFormat' => 'js:$.datepicker.ISO_8601'
)
)
);";
return $code;
}
// render normal input
else {
if(preg_match('/^(password|pass|passwd|passcode)$/i',$column->name))
$inputField='activePasswordField';
else
$inputField='activeTextField';
if($column->type!=='string' || $column->size===null)
return "CHtml::{$inputField}(\$model,'{$column->name}')";
else {
if(($size=$maxLength=$column->size)>60)
$size=60;
return "CHtml::{$inputField}(\$model,'{$column->name}',array('size'=>$size,'maxlength'=>$maxLength))";
}
}
}
Wie man sieht werden bei bestimmten Datentypen und/oder Feldnamen spezielle Inputs generiert. Das funktioniert soweit prima.
Auch die Relations, zumindest solange die BELONGS_TO sind, sind recht einfach über ein Dropdown abzubilden.
Ich habe auch mal diese Extension versucht: http://www.yiiframework.com/extension/relation/ aber bisher ohne den ganz großen Erfolg.
Anbei meine Vorschläge, welche UI-Komponenten im Idealfall zur Relation generiert werden sollen:
BELONGS_TO: Dropdown mit allen Einträgen aus der Fremdtabelle, wenn die Gegenseite HAS_ONE ist, dann wäre es schön, wenn man die Auswahl nur auf die verfügbaren Elemente einschränken würde.
HAS_MANY: Nur read-only Liste, mit Links zu den Einträgen (eventuell in der Sidebar, wenn überhaupt)
MANY_MANY: Checkboxliste/MultiselectListBox mit allen Einträgen der "Gegenseite". Speicherung der Daten über ein ActiveRecordBehavior?
So weit so gut, any comments?
Oder gibt es gar jemanden, der das schon geschrieben hat ?
Grüße
schmunk