Ich habe eine Lösung dieses Problem. Es ist nicht das beste, aber es ist genug für mich jetzt.
Zuerst benötigen Sie ein gültiges Array, das Sie übergeben, um zu bilden. , wenn Sie Daten aus der Datenbank auswählen, werden Sie Ihre Array ähnliche Struktur haben:
array(
0=>array(
'id'=>1,
'name'=>'Top level 1',
'parent_id'=>0
)
1=>array(
'id'=>2,
'name'=>'Top level 2',
'parent_id'=>0
)
2=>array(
'id'=>3,
'name'=>'Sub level 1',
'parent_id'=>1
)
3=>array(
'id'=>4,
'name'=>'Sub level 2',
'parent_id'=>1
)
4=>array(
'id'=>5,
'name'=>'Sub level 1',
'parent_id'=>2
)
5=>array(
'id'=>6,
'name'=>'Sub level 1',
'parent_id'=>2
)
)
Sie brauchen dieses Array zu transformieren. Ich habe Filter dafür verwendet:
class My_Filter_Array_ParentRelation implements Zend_Filter_Interface {
public function __construct() {
}
public function filter($arr) {
$data = array();
foreach ($arr as $value) {
$data[$value['parent_id']][$value['id']] = $value['name'];
}
$data = $this->create($data, 0,0);
return $data;
}
public function create($data, $pid=0,$l) {
$new_data = array();
if ($data[$pid]) {
foreach ($data[$pid] as $id => $value) {
$new_data[$id] = str_repeat('---',$l).$value;
if(isset($id)) {
$temp_data = $this->create($data, $id,$l+1);
$new_data = $new_data + $temp_data;
}
}
}
return $new_data;
}
}
Was macht dieser Filter? Sie gibt ein sortiertes eindimensionales Array relativ zum übergeordneten Element zurück. Verschachtelte Ebene ist als "---" markiert. Beispiel:
array(
1=>'Top level 1',
3=>'---Sub level 1',
4=>'---Sub level 2',
2=>'Top level 2',
5=>'---Sub level 1',
6=>'---Sub level 2'
)
Dann erstelle ich Form. Es hat ein spezifisches Element category_id. Ich werde den View-Helfer dafür einstellen.
class My_Form_Product extends Zend_Form {
protected $_categories = array();
public function init() {
$this
->addElement('multiCheckbox', 'category_id', array('label' => 'Category:', 'required' => true, 'multiOptions' => $this->getCategories()));
$this->category_id->helper = 'MultiCheckbox';
}
public function setCategories($categories = array()) {
$this->_categories = $categories;
return $this;
}
public function getCategories() {
return $this->_categories;
}
}
Dann brauchen Sie View Helfer Code:
class My_View_Helper_MultiCheckbox extends Zend_View_Helper_FormElement
{
protected $_inputType = 'checkbox';
protected $_isArray = false;
public function MultiCheckbox($name, $value = null, $attribs = null,
$options = null, $listsep = "\n")
{
$info = $this->_getInfo($name, $value, $attribs, $options, $listsep);
extract($info); // name, value, attribs, options, listsep, disable
$listsep = "\n";
// retrieve attributes for labels (prefixed with 'label_' or 'label')
$label_attribs = array();
foreach ($attribs as $key => $val) {
$tmp = false;
$keyLen = strlen($key);
if ((6 < $keyLen) && (substr($key, 0, 6) == 'label_')) {
$tmp = substr($key, 6);
} elseif ((5 < $keyLen) && (substr($key, 0, 5) == 'label')) {
$tmp = substr($key, 5);
}
if ($tmp) {
// make sure first char is lowercase
$tmp[0] = strtolower($tmp[0]);
$label_attribs[$tmp] = $val;
unset($attribs[$key]);
}
}
$labelPlacement = 'append';
foreach ($label_attribs as $key => $val) {
switch (strtolower($key)) {
case 'placement':
unset($label_attribs[$key]);
$val = strtolower($val);
if (in_array($val, array('prepend', 'append'))) {
$labelPlacement = $val;
}
break;
}
}
// the radio button values and labels
$options = (array) $options;
// build the element
$xhtml = '';
$list = array();
// should the name affect an array collection?
$name = $this->view->escape($name);
if ($this->_isArray && ('[]' != substr($name, -2))) {
$name .= '[]';
}
// ensure value is an array to allow matching multiple times
$value = (array) $value;
// XHTML or HTML end tag?
$endTag = ' />';
if (($this->view instanceof Zend_View_Abstract) && !$this->view->doctype()->isXhtml()) {
$endTag= '>';
}
// add radio buttons to the list.
$filter = new Zend_Filter_Alnum();
foreach ($options as $opt_value => $opt_label) {
// Should the label be escaped?
if ($escape) {
$opt_label = $this->view->escape($opt_label);
}
// is it disabled?
$disabled = '';
if (true === $disable) {
$disabled = ' disabled="disabled"';
} elseif (is_array($disable) && in_array($opt_value, $disable)) {
$disabled = ' disabled="disabled"';
}
// is it checked?
$checked = '';
if (in_array($opt_value, $value)) {
$checked = ' checked="checked"';
}
// generate ID
$optId = $id . '-' . $filter->filter($opt_value);
// Wrap the radios in labels
$wrapper_start = '';
$wrapper_end = '</label><br >';
$level = substr_count($opt_label,'---');
$opt_label = str_replace('---','',$opt_label);
$label = '<label '. $this->_htmlAttribs($label_attribs) . ' for="' . $optId . '">' .$opt_label;
$radio = (('prepend' == $labelPlacement) ? $label : '')
. str_repeat(' ',$level).'<input type="' . $this->_inputType . '"'
. ' name="' . $name . '"'
. ' id="' . $optId . '"'
. ' value="' . $this->view->escape($opt_value) . '"'
. $checked
. $disabled
. $this->_htmlAttribs($attribs)
. $endTag .' '
. (('append' == $labelPlacement) ? $label : '');
$text = $wrapper_start . $radio . $wrapper_end;
// add to the array of radio buttons
$list[] = $text;
}
// done!
$xhtml .= implode($listsep, $list);
return $xhtml;
}
}
Dieser Helfer wird die Marke '---' finden und stellen drei Abstandshalter (
) vor Checkbox.
So bleiben Sie nur Anzeige Controller-Aktion. Sie erhalten die Kategorienliste von db, filtern sie in ein neues Array, erstellen dann ein Formular und senden es zur Bildung des gefilterten Arrays:
$categories = Something::getCategories();
$filterCategory = new My_Filter_Array_ParentRelation();
$form = new Admin_Form_Product(array(
'name' => 'Form',
'categories' => $filterCategory->filter($categories->toArray()),
));
$this->view->form = $form;