arex1337 Skrevet 25. januar 2009 Del Skrevet 25. januar 2009 (endret) Jeg utvikler en applikasjon som bruker blant annet Zend Framework og Doctrine (ORM). Så langt har jeg brukt Zend_Form for alle skjemaer. Jeg har for eksempel UserForm-klassen som definerer et skjema jeg bruker ved oppretting av ny bruker og redigering av eksisterende bruker: <?php class UserForm extends Zend_Form { public function init() { $this->addElementPrefixPath('LystadOnline', 'LystadOnline'); $first_nameOptions = array( 'filters' => array('StringTrim'), 'label' => 'Fornavn' ); $first_name = $this->addElement('text', 'first_name', $first_nameOptions); $last_nameOptions = array( 'filters' => array('StringTrim'), 'label' => 'Etternavn' ); $last_name = $this->addElement('text', 'last_name', $last_nameOptions); $usernameOptions = array( 'filters' => array('StringTrim'), 'validators' => array('Alnum', 'UniqueUsername'), 'required' => true, 'label' => 'Brukernavn' ); $username = $this->addElement('text', 'username', $usernameOptions); $passwordOptions = array( 'filters' => array('StringTrim'), 'validators' => array('Alnum'), 'required' => true, 'label' => 'Passord' ); $password = $this->addElement('text', 'password', $passwordOptions); $roleModel = new RoleModel(); $roles = $roleModel->getAll(); if (count($roles) > 0) { foreach ($roles as $role) { $multiOptionsRoles[$role->id] = $role->name; } } $roleOptions = array( 'label' => 'Rolle', 'multiOptions' => $multiOptionsRoles ); $role = $this->addElement('select', 'role_id', $roleOptions); $submitOptions = array( 'required' => false, 'ignore' => true, 'label' => 'Lagre' ); $submit = $this->createElement('submit', 'updateUser', $submitOptions); $submit->setDecorators(array( 'ViewHelper', 'Errors', 'Description', array('HtmlTag', array('tag' => 'dd')), )); $this->addElement($submit); $decorators = array( 'FormElements', array('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')), array('Description', array('tag' => 'p', 'class' => 'hint')), 'Form' ); $this->setDecorators($decorators); } } For å populere redigeringsskjemaet for en eksisterende bruker har jeg følgende relevante kode: $user = $this->getModel()->getOneById($id); $form = new UserForm(); $form->populate($user->toArray()); For å lagre endringene har jeg følgende relevante kode: $this->getModel()->updateById($id, $form->getValues()); Pent og lettvint. Men dette skjemaet tar seg bare av ett objekt om gangen. Nå ønsker jeg å lage et skjema som skal redigere flere objekter. Nærmere bestemt et skjema som kan redigere alle tillatelser (f.eks. lese/skrive/slette) for alle ressurser (f.eks. brukere/roller/artikler) for en bestemt rolle (f.eks. administrator). Hvordan skal et skjema som skal redigere flere objekter defineres og populeres? Endret 26. januar 2009 av arex1337 Lenke til kommentar
arex1337 Skrevet 26. januar 2009 Forfatter Del Skrevet 26. januar 2009 (endret) Jeg har nå tatt i bruk subforms for modularitet og flyttet all logikk ut i kontrolleren der den hører hjemme: $form = new RoleForm(); $form->setAction($this->_helper->url('update', $request->getControllerName(), $request->getModuleName(), array('id' => $id))); $resourceModel = new ResourceModel(); $resources = $resourceModel->getAll(); $permissionModel = new PermissionModel(); $permissions = $permissionModel->getByRole_id($id); foreach ($resources as $resource) { foreach ($permissions as $permission) { if ($permission->resource_id == $resource->id) { $rolePermissionSubForm = new RolePermissionSubForm(); $rolePermissionSubForm->getDisplayGroup("permissions")->setLegend("$resource->name"); $rolePermissionSubForm->populate($permission->toArray()); $form->addSubForm($rolePermissionSubForm, $permission->id); } } } $this->view->form = $form; $form->populate($role->toArray()); RolePermissionSubForm: class RolePermissionSubForm extends Zend_Form { public function init() { $can_readOptions = array( 'label' => 'Read' ); $can_read = $this->addElement('checkbox', 'can_read', $can_readOptions); $can_writeOptions = array( 'label' => 'Write' ); $can_write = $this->addElement('checkbox', 'can_write', $can_writeOptions); $can_modifyOptions = array( 'label' => 'Modify' ); $can_modify = $this->addElement('checkbox', 'can_modify', $can_modifyOptions); $can_deleteOptions = array( 'label' => 'Delete' ); $can_delete = $this->addElement('checkbox', 'can_delete', $can_deleteOptions); $can_publishOptions = array( 'label' => 'Publish' ); $can_publish = $this->addElement('checkbox', 'can_publish', $can_publishOptions); $this->addDisplayGroup(array("can_read", "can_write", "can_modify", "can_delete", "can_publish"), "permissions"); } } Jeg er noe ukomfortabel med å bygge skjemaer i kontrolleren på denne måten. Jeg liker heller ikke å ha denne type presentasjonslogikk i kontrolleren, men jeg antar at man kan se på RolePermissionSubForm som et partial view og denne linjen bare passerer data til viewet: $rolePermissionSubForm ->getDisplayGroup("permissions") ->setLegend("$resource->name"); Hvordan bør man passere data til instanser av Zend_Form? Kanskje jeg skulle passere alt det nødvendige til RoleForm og bygge skjemaet der isteden for i kontrolleren? Endret 26. januar 2009 av arex1337 Lenke til kommentar
arex1337 Skrevet 26. januar 2009 Forfatter Del Skrevet 26. januar 2009 (endret) Løsningen ble å kvitte seg med RoleForm- og RolePermissionSubForm-klassene og lage en hjelpemetode i kontrolleren som genererer skjemaet på element-til-element-basis: public function getRoleForm($role_id) { $role = $this->getModel()->getOneById($role_id); $form = new Zend_Form(); $nameOptions = array( 'filters' => array('StringTrim'), 'required' => true, 'label' => 'Navn', 'value' => $role->name ); $form->addElement('text', 'name', $nameOptions); $descriptionOptions = array( 'filters' => array('StringTrim'), 'required' => true, 'label' => 'Beskrivelse', 'value' => $role->description ); $form->addElement('text', 'description', $descriptionOptions); $resourceModel = new ResourceModel(); $resources = $resourceModel->getAll(); $permissionModel = new PermissionModel(); foreach ($resources as $resource) { $permission = $permissionModel->getOne("role_id = $role_id AND resource_id = {$resource->id}"); $form->addElement('checkbox', "can_read_{$resource->id}", array('label' => 'Read', 'value' => $permission->can_read)); $form->addElement('checkbox', "can_write_{$resource->id}", array('label' => 'Write', 'value' => $permission->can_write)); $form->addElement('checkbox', "can_modify_{$resource->id}", array('label' => 'Modify', 'value' => $permission->can_modify)); $form->addElement('checkbox', "can_delete_{$resource->id}", array('label' => 'Delete', 'value' => $permission->can_delete)); $form->addElement('checkbox', "can_publish_{$resource->id}", array('label' => 'Publish', 'value' => $permission->can_publish)); $form->addDisplayGroup(array("can_read_{$resource->id}", "can_write_{$resource->id}", "can_modify_{$resource->id}", "can_delete_{$resource->id}", "can_publish_{$resource->id}"), "permissions_{$resource->id}", array('legend' => $resource->name)); } $saveOptions = array( 'required' => false, 'ignore' => true, 'label' => 'Lagre' ); $form->addElement('submit', 'save', $saveOptions); return $form; } Det fungerer, men jeg liker det dårlig fordi det bryter med MVC-prinsippet. Setter stor pris på forslag til en bedre løsning. Endret 2. februar 2009 av arex1337 Lenke til kommentar
serrghi Skrevet 26. januar 2009 Del Skrevet 26. januar 2009 (endret) Er selv på utkikk etter samme løsning, skal si ifra om jeg finner ut av noe - (har ikke hatt tid til å se over all koden din enda, skal kikke på det senere!) Endret 26. januar 2009 av serrghi Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå