Trabalhar Com Datas I18N [Resolvido]

Pessoal, boa tarde !

Sabe quando a solução parece simples, mas ficamos agarrados sem conseguir resolver… pois é. Segue abaixo o meu problema:

Cenário:

  • Estou trabalhando com MySQL, com os campos no formato Date.

  • Tenho um cadastro de Vendas, com 3 Models (cabeçalho, Itens e Pagamentos)

  • Utilizo a extension i18n-datetime-behavior

  • Na actionUpdate (por exemplo), após o $model_cabecalho passar pelo método ->save(), se houver algum erro encontrado nos dois outros Models, preciso emitir uma mensagem de erro, fazer um rollback() e voltar ao formulário para o usuário arrumar o problema.

Erro:

O $model_cabecalho volta com a data no formato do MySQL (yyyy-MM-dd).

Analisando o behavior, entendo que isso foi feito pelo evento: "public function beforeSave($event){"

Tentei executar o comando abaixo, logo antes do render da actionUpdate… para devolver o formato para i18n, mas agora ele força a data atual no campo, ao invés de mostrar o conteúdo do que estava no model.




$model_cabec->data = Yii::app()->dateFormatter->formatDateTime(

                CDateTimeParser::parse($model_cabec->data, 'yyyy-MM-dd'),'medium',null);

		

$this->render('update',array( 

....




Alguém pode me ajudar a entender o que está acontecendo ?

Tem algum behavior / extension mais atualizada, mais completa ?

Muito obrigado.

Referências:

http://www.yiiframework.com/forum/index.php/topic/3238-problema-trabalhando-com-datas/page__view__findpost__p__115785

http://www.yiiframework.com/doc/guide/1.1/en/topics.i18n

e outras pesquisas…

Olá Gustavo!

Tenta converter assim:


date('d/m/Y', CDateTimeParser::parse('1990-02-15', 'yyyy-MM-dd'));

Quando trabalho com transação eu chamo primeiro os métodos validate() de cada modelo, se todos passarem pela validação eu chamo o save(), nesse caso a data nem chega a ir para o formato yyyy-MM-dd, pois o validador da data utiliza o padrão dd/MM/yyyy.

Flw!

Olá Thiago, obrigado pela dica.

Funcionou !!

Eu fiz uma função para facilitar diversos casos que terei.

Mas existe uma melhor forma de descobrir em qual formato ( yyyy-mm-dd ou dd/mm/yyyy ) a data está ?

Acredito que essa função possa melhorar para ficar mais "estável".




	public function getDate_i18n_format($sdate)	{

                if ($sdate =='')  return $sdate;

		

		// Verificando se a data está no formato yyyy-mm-dd

		if (strpos($sdate, '-')) {

			list($y, $m, $d) = explode('-', $sdate);

			if(checkdate($m, $d, $y))

				// Se estiver no formato, faz a conversão

				return date('d/m/Y', CDateTimeParser::parse($sdate, 'yyyy-MM-dd'));

			else 

				return $sdate;  // senão, devolve o que estava na variável

		} else 

			return $sdate;

	}



Neste caso a dúvida é mais de PHP do que Yii. Mas se puder ajudar!?!

Muito obrigado !

Gustavo, não depurei este método, mas se está quebrando teu galho é oq vale. São muitas as maneiras pra vc fazer isso. A forma que utilizo muito é com com expressão regular.

Eu tb utilizo essa extensão (i18n-datetime-behavior), mas quando os valores não passam pela validação as datas retornam como inseridas no "_form.php", ou seja, eu não preciso fazer essa conversão q vc faz.

Passa como está em seu controlador, vou dar uma olhada, as vezes tú nem precisa esquentar com essa conversão.

Flw! Abraço.

Olá Thiago,

Obrigado pela ajuda.

Eu faço um validate() antes do save(). Mas como é um Master-Detail, o save() do cabeçalho acontece antes de gravar os registros "detalhes" (itens e pagamentos). Segue o código para você verificar. Agraço as críticas !! Valeu !

Até pensei em passar o save do cabeçalho, depois que houver sucesso na gravação dos detalhes (depois de todas as validações). Talvez assim, não precise de fazer a conversão da data.




	/**

	 * Updates a particular model.

	 * If update is successful, the browser will be redirected to the 'view' page.

	 * @param integer $id the ID of the model to be updated

	 */

	public function actionUpdate($id)

	{

		$model_cabec=$this->loadModel($id);

		$model_itens=new Vendas02;

		$model_pgtos=new Contasreceber;

		$dp_itens=$this->loadModel_itens($id);

		$dp_pgtos=$this->loadModel_pgtos($id);

		$readonly = FALSE;


		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['Vendas01']))

		{

			$model_cabec->attributes=$_POST['Vendas01'];

			// Montando o array com os campos da View

			$gridItens = $this->itens_from_post();

			$gridPgtos = $this->pgtos_from_post();

			$dp_itens  = $this->cria_dataprovider_itens($gridItens);

			$dp_pgtos  = $this->cria_dataprovider_pgtos($gridPgtos);

			$success1 = false;

			$success2 = false;

			$success3 = false;


			if ($model_cabec->validate()) {

				$transaction = Yii::app()->db->beginTransaction();

				$success1 = $model_cabec->save(false);


				//Pré-Validações

				$form_validado = $this->f_valida_form($model_cabec, $model_itens, $model_pgtos, $gridItens, $gridPgtos);

				if ($form_validado) {


					// Exclui todos os itens e pagamentos existentes 

					$this->delete_Itens($model_cabec->id);

					$this->delete_Pgtos($model_cabec->id);

	

					// Grava os novos registros

					$success2 = true;

					foreach($gridItens as $i=>$item) {

						$model_itens_save=new Vendas02;

						$model_itens_save->unsetAttributes();

						$model_itens_save->id_venda 	= $model_cabec->id;

						$model_itens_save->id_item 		= $item["id_item"];

						$model_itens_save->id_produto 	= $item["id_produto"];

						$model_itens_save->qtde 		= $item["qtde"];

						$model_itens_save->desconto		= $item["desconto"];

						$model_itens_save->valor 		= $item["valor"];

	

						// Salva e Valida os submodels

						if ($model_itens_save->validate()) 

							$model_itens_save->save(false);

						else 

							$success2 = false;

						}					

					

					// Grava os novos registros

					$success3 = true;

					foreach($gridPgtos as $i=>$pgto) {

						$model_pgtos_save=new Contasreceber;

						$model_pgtos_save->unsetAttributes();

						$model_pgtos_save->id_venda 		= $model_cabec->id;

						$model_pgtos_save->id_parcela 		= $pgto["id_parcela"];

						$model_pgtos_save->id_tipopgto 		= $pgto["id_tipopgto"];

						$model_pgtos_save->id_cartaocred 	= $pgto["id_cartaocred"];

						$model_pgtos_save->id_operatef		= $pgto["id_operatef"];

						$model_pgtos_save->numdoc 			= $pgto["numdoc"];

						$model_pgtos_save->parc_data 		= $pgto["parc_data"];

						$model_pgtos_save->parc_valor 		= str_replace(',', '.', $pgto["parc_valor"]);

						

						// Valida e Salva os submodels

						if ($model_pgtos_save->validate())  

							$model_pgtos_save->save(false);

						else 

							$success3 = false;

					}				

				}


				// Verificando o resultado das validações

				

				$success = $success1 && $success2 && $success3;

				

				if ($success) { 

					$transaction->commit();

					// redireciona para visualização

					$this->redirect(array('view','id'=>$model_cabec->id));

				}        	

				else

					$transaction->rollBack();

			}

		}




		// Convertendo o formato da data, pois pode chegar com formato y-m-d

		$model_cabec->data = $this->getDate_i18n_format($model_cabec->data); 

		

		$this->render('update',array(

			'model_cabec'=>$model_cabec,

			'model_itens'=>$model_itens,

			'model_pgtos'=>$model_pgtos,

			'dp_itens'=>$dp_itens,

			'dp_pgtos'=>$dp_pgtos,

			'readonly'=>$readonly,

		));	

	}




Opa Gustavo!

Li o código. Acredito tb que se vc fizer isso q pensou não haverá necessidade de converter a data, já que o método save do $model_cabec não será executado caso a gravação dos detalhes não ocorra.

Pelo fato da extensão interpretar os modelos individualmente, e converter a(s) data(s) antes de salvar, se, e somente se, a validação for bem sucedida ou quando não há validação ($model->save(false)), ocorrerá isso msm.

Flw!

Beleza Thiago !!

Muito obrigado pela ajuda.