Buscar una edad según una fecha de nacimiento

Buenas noches, tengo un problema y no sé como solucionarlo.

En mi base de datos almaceno en un campo la fecha de nacimiento de una persona, logré calcular la edad para todas las vistas incluyendo en el admin, pero ahora, quiero hacer una búsqueda en el admin y que no sea por la fecha de nacimiento si no por la edad.

Leo sus comentarios y muchas gracias.

PD: Soy nuevo en Yii.

Dejo aquí como hacer la edad en las vistas.

Habitante.php

public function attributeLabels()

{


	return array(


		'edad' => 'Edad',


	);


}

admin.php

<?php $this->widget(‘zii.widgets.grid.CGridView’, array(

'id'=&gt;'habitante-grid',


'dataProvider'=&gt;&#036;model-&gt;search(),


'filter'=&gt;&#036;model,


'columns'=&gt;array(


		array(


		'header' =&gt; 'Edad',


		'name' =&gt; 'fechaNacimiento',


		'value' =&gt; 'calculaEdad(&#036;data-&gt;fechaNacimiento)',


		),


	array(


		'class'=&gt;'CButtonColumn',


	),


),

));

function calculaEdad($fecha)

{

&#036;datetime1 = new DateTime(&#036;fecha);


&#036;datetime2 = new DateTime();


&#036;diff = &#036;datetime1-&gt;diff(&#036;datetime2);





return &#036;edad = &#036;diff-&gt;y;

}

_view.php

$datetime1 = new DateTime($data->fechaNacimiento);

$datetime2 = new DateTime();

$diff = $datetime1->diff($datetime2);

$edad = $diff->y;

<b><?php echo CHtml::encode($data->getAttributeLabel(‘edad’)); ?>:</b>

&lt;?php echo CHtml::encode(&#036;edad); ?&gt;


&lt;br /&gt;

view.php

$datetime1 = new DateTime($model->fechaNacimiento);

$datetime2 = new DateTime();

$diff = $datetime1->diff($datetime2);

$edad = $diff->y;

<?php $this->widget(‘zii.widgets.CDetailView’, array(

'data'=&gt;&#036;model,


'attributes'=&gt;array(


	array(


      'label' =&gt; 'Edad',


      'value' =&gt; &#036;edad,


    ),

Y donde no sé como solucionar…

Habitante.php

$criteria=new CDbCriteria;

$criteria->compare(‘fechaNacimiento’,$this->fechaNacimiento,true);

//Aquí necesito buscar por edad y no por fecha, quisiera no agregar el campo de edad en la base de datos.

Hola jojuchatru1993, viendo tu mensaje es fácil hacer ese cambio, NO QUIERES AGREGAR UN CAMPO A LA DB, no es necesario agregarlo, ¿cómo?, fácil, simple y bonito usa una consulta.

Dentro de tu model en el método Search usa criteria para esto:




$criteria->select = "TUS DATOS SELECT CAMPO1, CAMPO2, CAMPO3";



Dentro de este select es donde pondras todos los campos que deseas mostrar en el grid, al igual desde mysql si es que usas este motor genera la edad desde aqui mismo y al final ponle como alias la fecha que tienes almacenada.

EJEMPLO




$criteria->select = "YEAR(CURDATE())-YEAR(F_NACIMIENTO) + IF(DATE_FORMAT(CURDATE(),'%m-%d') > DATE_FORMAT(F_NACIMIENTO,'%m-%d'), 0, -1) fechaNacimiento";

$criteria->alias = "ESTE ES EL ALIAS QUE LE DAS A TU TABLA PADRE, SINO LO INDICAS YII pondra un alias que no correspondera";

$criteria->join = "SI USAS JOINS o quieres usar a futuros aqui va tal cual INNER JOIN TABLA ALIAS ON ID = ID ";



con esto solo es necesario dejar tus compare que desees.




//$criteria->compare('si usas alias ponlo aqui ',$this->fechaNacimiento,true) EJEMPLO

$criteria->compare('fechaNacimiento',$this->fechaNacimiento,true); // RECUERDA QUE TRUE ES PARA BUSCAR POR LIKE



Si con esto no te funciona en ocasiones es necesario que indiques la consulta tal cuál ejemplo.




$criteria->compare('YEAR(CURDATE())-YEAR(F_NACIMIENTO) + IF(DATE_FORMAT(CURDATE(),'%m-%d') > DATE_FORMAT(F_NACIMIENTO,'%m-%d'), 0, -1)',$this->fechaNacimiento,true); // RECUERDA QUE TRUE ES PARA BUSCAR POR LIKE



Si te fijaste bien solo copie y pegue la parte que hara el calculo de la edad, pero no le puse el alias, con esto te deberia de funcionar, como tip si quieres mostrar datos ajenos a tu tabla, antes declara propiedades public $nuevaPropiedad;

y a esa propiedad le indicas algo a mostrar en tu consulta y le pones el alias


SELECT nombre nuevaPropiedad * FROM TABLA

y dentro de compare haces instancia a esa propiedad


$criteria->compare('nuevaPropiedad',$this->nuevaPropiedad);

y con esto en tu gridView solo mandas llamar array(‘nuevaPropiedad’) ó array(‘name’=>‘nuevaPropiedad’), como tu gustes y te detectara yii el campo a mostrar con tu calculo recuerda que si no funciona indicando el puro alias, a veces debes de poner la parte que deseas del select, si usas alias solo indicalo asi


$criteria->compare('alias.campo',$this->campo);

Al hacer esto no te funcionará el filtro para ordernar por mayor o menor, pero al rato te pongo el código para eso, es que no lo tengo a la mano, jeje perdona…

Espero haberte ayudado.

Saludos.

Lo prometido es deuda te dejo la otra parte del código lml.





class Usuarios extends CActiveRecord

{

  public $tipo; //esta es la propiedad que te comentaba, recuerda que si esta propiedad no la pones en rules sobre search para buscar no te buscara por mas que quieras intentar buscarle solo ponla dentro de rules.


  public function rules()

  {

    return array(

     array('c05_id', 'safe', 'on'=>'search'), // en ocasiones la debes de indicar dentro de safe una linea antes de esta en tu model, pero es en especifico para enviar via post, fuerzas que se envie post o get si es que usas propiedades para guardar, bonito no?.

    );

  }


  public function search()

  {

    $criteria=new CDbCriteria;

    $criteria->select = "u.id, u.nombre, d.consecutivo, IF(d.tipo = 1,'FISICO','MORAL') tipo";

    $criteria->alias = "u"; // u es como una tabla usuarios es el alias, es un ejemplo

    $criteria->join = "inner join detalle d on d.id_user = u.id"; // Pon los INNER, LEFT o RIGHT que se te antojen recuerda no se te olviden los alias lml.

    $criteria->group = "u.id"; //AGRUPACION


    //COMPARES OBSERVA COMO LE INDICO CON LOS ALIAS

    $criteria->compare('u.id',$this->id);

    $criteria->compare('u.nombre',$this->nombre,true);

    $criteria->compare('d.consecutivo',$this->consecutivo,true);

    $criteria->compare('IF(d.tipo = 1,"FISICO","MORAL")',$this->consecutivo,true); // Fijate como puse el IF no pongas el alias y asi ya puedes buscar por el texto lml, mas chido no?.

    


    return new CActiveDataProvider($this, array(

        'criteria'=>$criteria,

        'sort'=>array(

             'attributes'=>array(

                   'u.nombre'        => array('asc'=>'1','desc'=>'1 DESC',),

                   'd.consecutivo'   => array('asc'=>'2','desc'=>'2 DESC',),

                   'alias'	     => array('asc'=>'3','desc'=>'3 DESC',), // aqui si pones el alias

             ),

             'defaultOrder'=>array(

		   'u.id' => false, // te fijaste que no lo puse arriba?, el false es para decir que no se auto ordene

	     )

        }, // este cierra sort

    ));

}



CON ESTE ejemplo te aclaro todo el choro que te puse arriba, pero era necesaria la explicación, te fijas?, SIMPLE Y ELEGANTE lml jajajaa FRASE DE CALL OF DUTY jajaja.

ESPERO TE SIRVA AUN MAS ESTO.

P.D. en el grid para la propiedad que declaraste arriba tipo solo asi ponla en tu CGridView como pondrias en este caso consecutivo en el array, solo ponle tipo y listo ya la mandas llamar lml, claro ponle el attributesLabels().

Saludos.

shaolin

Muchas gracias por tu ayuda, quedé muy sorprendido. Espero seguir aprendiendo cada día más.