Nested models NxN

Olá galera, estou adorando o yii porém até agora nao encontrei nenhum helper para ajudar com relacionamentos NxN do tipo Pessoa => Pessoa_Telefone <= Telefone

Qual seria o caminho mais facil de conseguir algo assim?

pra fazer isso + - estou tentando criar o metodo a seguir




    public function link_to_add($form, $new_obj_of_required_type, $partial, $div_to_add_the_item='nxn') {

    	try {

			$controller = new CController('helper');

	    	$array_obj_name = strtolower(print_r($new_obj_of_required_type));

	    	$array = array($array_obj_name => $new_obj_of_required_type,

	    	               'form'=>$form,);

	    	

	    	$page = $controller->renderPartial('../'.$partial, $array);

	    	$page = $this->html_to_js_append($page);

	    	return '';

		}

		catch( Exception $e ) {

			return 'erro';

		}

    }



esse metodo iria criar um botao que adiciona dentro de um div uma parcial que eu escolher, porem ele esta mostrando na tela um objeto automaticamente, provavelmente o metodo renderPartial, tem como segurar esse resultado sem mostrar ele na pagina automaticamente?

Acho que você pode fazer isso utilizando algum metodo em ajax, semelhante ao metodo utilizado para fazer dropdown em cascata, vc no caso precisaria de dois metodos dinâmicos, um deles para inserir e outro para excluir.

ficaria algo semelhante ao que pode-se utilizar em criação de regras de restrição de usuário, com User e Role, um usuário pode ter muitas regras e uma regra pode ter muitos usuários, no meio dos dois teria a tabela de User_Role.

É mais ou menos isso que você quer fazer? Eu nunca fiz isso no Yii, mas acho que vou precisar fazer isso estes dias e podemos nos ajudar se for isso mesmo que você quer fazer.

é exatamente isso, eu estou trabalhando nesse metodo e ja esta quase pronto ;)




<?php

/*

 * Created on 15/03/2011

 *

 */

 

class NestedHtmlHelper extends CWidget

{

    public function link_to_add($form, $new_obj_of_required_type, $partial, $div_to_add_the_item='telefone') 

    {

    	try 

    	{

		$controller = new CController('helper');

		$array_obj_name = 'Telefone';//TODO: pegar uma string com nome da classe

	    	$array = array($array_obj_name => $new_obj_of_required_type,

			       'form'          => $form,);

	    	

	    	$page = $controller->renderPartial("../$partial", $array, true);

	    	$page = $this->html_to_append_in_js($page);

	    	$link = "<script type='text/javascript' language='javascript'>

	    	                 function add_nxn_form(link) {

	    	                 	jQuery(link).parent().find('div.novos').before('$page');

				 }

			 </script>";

	    	$link = "<a href='javascript:' onclick='add_nxn_form(this);'> Novo </a>$link";

	    	return $link;

	    	

	} catch( Exception $e ) {

		die($e);

	}

    }

    

    public function html_to_append_in_js($string) {

    	    $string = str_replace('\'',  '"', $string);

	    $string = str_replace('  ', ' ',  $string);

	    $string = str_replace(' ', ' ',   $string);

	    $string = str_replace('\r', ' ',  $string);

	    $string = str_replace('\n', ' ',  $string);

	    $string = str_replace('\r\n', '', $string);

	    $string = str_replace('/' , '\/', $string);

	    $string = str_replace('\t' , '',  $string);

	    $string = preg_replace('/\s/',' ',$string);

	    return $string;

    }

    

}


?>




bom fiz esse metodo que faz tudo direitinho, claro que precisa de algumas fixes mais ok, o que eu preciso é que no meu partial eu consigo fazer um form que retorne um array legal, porque o yii nao tem um jeito facil de eu fazer um form com varios elementos, ou se tiver alguem me ajude pls

meu codigo partial de add telefones é o seguinte :




<?

if (!isset($telefone)) {

    $telefone = new Telefone;

    $telefone->id = 'new';

}

?>

<div id="telefone" class="telefone">

    <?= $form->errorSummary($telefone); ?>

    <?= $form->hiddenField($telefone, "Telefones[$telefone->id]id") ?>

    <div class="row">

        <?= $form->labelEx($telefone, "Tipo"); ?>

        <?= $form->textField($telefone, "Telefones[$telefone->id]tipo", array("size" => 60, "maxlength" => 255)); ?>

        <?= $form->error($telefone, "tipo"); ?>	</div>

    <div class="row">

        <?= $form->labelEx($telefone, "Numero"); ?>

        <?= $form->textField($telefone, "Telefones[$telefone->id]numero", array("size" => 20, "maxlength" => 10)); ?>

        <?= $form->error($telefone, "numero"); ?>

    </div>

    <div class="row">

        <?= $form->labelEx($telefone, "Complemento"); ?>

        <?= $form->textField($telefone, "Telefones[$telefone->id]complemento", array("size" => 60, "maxlength" => 255)); ?>

        <?= $form->error($telefone, "complemento"); ?>

    </div>

    <div class="opcoes">

    </div>


</div>

<hr />



vamos ajudar rapido ae galera

Não to acompanhando o tópico mas "form facil" pra mim é o Form Builder: http://www.yiiframework.com/doc/guide/1.1/en/form.builder

Ah, também tem o yiiadmin forms diretos do modelo: http://www.yiiframework.com/extension/yiiadmin/

entao eu quero usar para nxn

pelo que entendi do formbuilder ele é pronto pra 1x1 correto?

estou tentando uma solucao para um has_many :throught do rails só pra exemplificar

Vinicius, não sei se entendi o que você quer.

Está tentando dinamicamente carregar views parciais que contém o outro lado da relacao N:N dentro de um div na página?

Bom, se for isso, talvez eu possa ajudar (embora não agora).

é exatamente isso, eu ja conclui meu codigo depois eu posto e esta ok, só estou apanhando do activerecord do yii.

quando puder poste seu codigo pra galera que deve se interessar bastante pelo assunto tbm.

código atualizado:




<?php

/*

 * Created on 15/03/2011

 *

 */

 

class NestedHtmlHelper extends CWidget

{

    public function link_to_add($form, $new_obj_of_required_type, $partial, $div_to_add_the_item='telefone') 

    {

    	try 

    	{

            //die(print_r($new_obj_of_required_type));

		$controller = new CController('helper');

		$array_obj_name = get_class($new_obj_of_required_type);

	    	$array = array($array_obj_name => $new_obj_of_required_type,

			       'form'          => $form,);

	    	

	    	$page = $controller->renderPartial("../$partial", $array, true);

	    	$page = $this->html_to_append_in_js($page);

	    	$link = "<script type='text/javascript' language='javascript'>

	    	                 function add_nxn_form(link) {

                                        var new_id = new Date().getTime();

                                        var regexp = new RegExp('new', 'g')

	    	                 	jQuery(link).parent().find('div.novos').before('$page'.replace(regexp, new_id));

				 }

			 </script>";

	    	$link = "<a href='javascript:' onclick='add_nxn_form(this);'> Novo </a>$link";

	    	return $link;

	} catch( Exception $e ) {

		die($e);

	}

    }

    

    public function html_to_append_in_js($string) {

    	    $string = str_replace('\'',  '"', $string);

	    $string = str_replace('  ', ' ',  $string);

	    $string = str_replace(' ', ' ',   $string);

	    $string = str_replace('\r', ' ',  $string);

	    $string = str_replace('\n', ' ',  $string);

	    $string = str_replace('\r\n', '', $string);

	    $string = str_replace('/' , '\/', $string);

	    $string = str_replace('\t' , '',  $string);

	    $string = preg_replace('/\s/',' ',$string);

	    return $string;

    }

    

}


?>




view partial de telefones :

não é necessario o [telefones] nos ids, mais é totalmente necessario o new




<?

if (!isset($telefone)) {

    $telefone = new Telefone;

    $telefone->id = 'new';

}


$form->actionPrefix = 'Telefones'

?>

<div id="telefone" class="telefone">

    <?= $form->errorSummary($telefone); ?>

    <?= $form->hiddenField($telefone, "[telefones][$telefone->id]id") ?>

    

    <div class="row">

        <?= $form->labelEx($telefone, "Numero"); ?>

        <?= $form->textField($telefone, "[telefones][$telefone->id]numero", array("size" => 20, "maxlength" => 10)); ?>

        <?= $form->error($telefone, "numero"); ?>

    </div>

    <div class="row">

        <?= $form->labelEx($telefone, "Complemento"); ?>

        <?= $form->textField($telefone, "[telefones][$telefone->id]complemento", array("size" => 60, "maxlength" => 255)); ?>

        <?= $form->error($telefone, "complemento"); ?>

    </div>

    <div class="row">

        <?= $form->labelEx($telefone, "Tipo"); ?>

        <?= $form->textField($telefone, "[telefones][$telefone->id]tipo", array("size" => 60, "maxlength" => 255)); ?>

        <?= $form->error($telefone, "tipo"); ?>

    </div>

    <div class="opcoes">

    </div>


</div>

<hr />



na view eu faço o seguinte :




<?= $helper->link_to_add($form, new Telefone, 'telefones/_telefone'); ?>



e não esquecer de usar jquery ;)

Então Vinicius, acho que não estamos falando da mesma coisa pois a solução que uso é extremamente menor. Acho que sua necessidade é outra realmente.

Mas vou explicar o que faço quando preciso buscar uma view e renderizar ela na página dinamicamente, via ajax.

  1. Na página principal, onde a view será renderizada, executo uma função ajax qualquer que tem como alvo, por exemplo, Controlador/obterViewX. Essa função jquery deve pegar o valor retornado e ‘jogá-lo’ no destino desejado (via #id por ex.), como de praxe.

  2. No controller crio uma action assim:




public function actionObterViewX()

	{

    	if($_POST['nome_da_view_ou_meio_de_acha-la'])

    	{

        	$view= .... // aqui vai alguma lógica pra definir o nome da view certinho, se preciso;

        	$model= ... // new ou find pra obter


             //aqui é onde a view realmente é retornada

        	echo $this->renderPartial($view, array('model'=>$model), TRUE, TRUE);

    	}

	}

Os dois parametros true em renderPartial são, respectivamente, um para retornar o resultado da renderização em vez de ‘echoa-lo’, e o outro true usei pra resolver o problema que tive quando a view parcial tinha seus próprios scripts registrados. Sem esse true (pós-processamento) esses scripts não eram registrados.

Obs: chamar o renderPartial direto nesse caso não funcionou para mim, embora acho que devia ter funcionado pois ele imprimiria o conteúdo também.

No caso, se precisasse de várias renderizações, bastaria usar um loop com alguma lógica também.

E é só. Tenho quase certeza de que não estamos falando da mesma coisa. Mas mesmo assim isso pode servir pra alguém que está começando.

T+

é você esta usando uma solução com AJAX e eu fiz uma solução com javascript que nao faz requisições ao servidor para requisitar parciais, unica diferenca.

só precisava mesmo agora é de uma solução legal pra salvar esses relacionamentos no banco, porque é meio complicado e pelo que parece o ActiveRecord do yii nao salva os relacionamentos automaticamente

cara vc resolveu este problema?

att,