Gå til innhold

Bruk av Zend_Form når man skal redigere flere objekter


Anbefalte innlegg

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 av arex1337
Lenke til kommentar
Videoannonse
Annonse

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 av arex1337
Lenke til kommentar

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 av arex1337
Lenke til kommentar

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 konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...