Yii Framework Forum: ordenar por un campo que no está en el modelo - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

ordenar por un campo que no está en el modelo Rate Topic: -----

#1 User is offline   Juan Pablo Sala 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 65
  • Joined: 16-June 09

Posted 07 October 2010 - 05:33 PM

Hola a todos,
Estoy haciendo un sistemita de tickets para aprender a usar el yii (de paso lo necesito en un cliente!!).
Tengo un gridview con los tickets, todo bien hasta ahí, se me ocurrió que sería interesante que aparezcan diferenciadas las filas con comentarios que el usuario activo no vio todavía, eso lo voy a dejar para otra iteración porque se me hace un poco difícil, lo que sí tengo ganas de hacer es mostrar una columna con la fecha del último comentario y su autor, hasta ahí bien, agregué un par de métodos al modelo ticket y todo aparece bien en el grid.
Lo que me gustaría hacer y para eso les pido una mano, es poder ordenar por esta columna, no solo es importante para este proyecto, sino que me parece un conocimiento interesante para tener :)
Si alguien puede darme un poco de dirección, ni que hablar de un poco de código!, si es así avisen y postéo el código que tengo hasta ahora (si hace falta)

Muchas gracias
Juan
0

#2 User is offline   nancoder 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 21
  • Joined: 14-June 10
  • Location:Querétaro, Mx

Posted 11 October 2010 - 10:57 PM

Hola Juan, es muy sencillo en realidad lograr lo que tu buscas, lo malo es que no viene casi nada de documentación al respecto en el sitio de Yii.



Te dejo un ejemplo comentado:




class File extends CActiveRecord {

    public $category; // OJO: esta variable es el campo que deseamos utilizar en la ordenación y lo tomamos de otra tabla.

   //...

    public function rules() {
        return array(
            array('node_id, name', 'required'),
            array('node_id', 'length', 'max' => 10),
            array('name', 'length', 'max' => 45),
            array('description', 'length', 'max' => 1000),
            array('path', 'file', 'types' => 'jpg, png, gif, pdf, doc, docx, pps, ppsx, ppt, pptx, xls, xlsx'),
            array('node_id, name, description, path, category', 'safe', 'on' => 'search'), // Hay que poner nuestra variable category como safe.
        );
    }

    public function relations() {
        return array(
            'node' => array(self::BELONGS_TO, 'Node', 'node_id', 'with' => array('category')), // Nuestra relación con el otro modelo tambien debe de estar en nuestro codigo.
        );
    }

    public function behaviors() {
        return array('CAdvancedArBehavior',
            array('class' => 'ext.CAdvancedArBehavior')
        );
    }

    public function attributeLabels() {
        return array(
            'node_id' => Yii::t('app', 'Node'),
            'name' => Yii::t('app', 'Name'),
            'description' => Yii::t('app', 'Description'),
            'path' => Yii::t('app', 'Path'),
            'category' => Yii::t('app', 'Category'), // Aqui puedes cambiar el nombre de tu campo en el label de tu grid.
        );
    }
//....


/**
* Aqui viene la parte importante
*/

    public function search() {
        $criteria = new CDbCriteria;

        $criteria->compare('node_id', $this->node_id, true);

        $criteria->compare('name', $this->name, true);

        $criteria->compare('description', $this->description, true);

        $criteria->compare('path', $this->path, true);

        $criteria->compare('category.name', $this->category, true);  //Agregamos a $criteria nuestro nuevo campo, esto nos sirve para realizar búsquedas dentro del CGridView

        $criteria->with = array('node');


        //Creamos un nuevo sort y añadimos nuestro campo relacionado

        $sort = new CSort();
        $sort->attributes = array(
                        'node_id',
                        'name',
                        'description',
                        'path',
                        'category' => array(   //<---------------- Aqui agregamos el campo relacionado
                            'asc'=>'category.name',
                            'desc'=>'category.name DESC',
                        ),
                );

        return new CActiveDataProvider(get_class($this), array(
            'criteria' => $criteria,
	    'sort' => $sort, // Pasamos la variable sort a nuestro [size=3]CActiveDataProvider[/size]
        ));
    }

}








Ahora solamente en nuestro CGridView tenemos que poner lo siguiente:




<?php $this->widget('zii.widgets.grid.CGridView', array(
                'id'=>'file-grid',
                'dataProvider'=>$model->search(),
                'filter'=>$model,
                'columns'=>array(
                		'node_id',
                    array('name'=>'category',
                            'value' => '$data->node->category->name'),
		'name',
		'description',
		'path',
                                array(
                                        'class'=>'CButtonColumn',
                                ),
                        ),
                )); ?>





Y listo, ya podemos hacer un sort con nuestro campo relacionado.

Espero te sirva, cualquier duda me avisas!

Saludos!
Configure your app enviroment with this Easy Enviroment Class

Follow me on Twitter | LinkedIn
0

#3 User is offline   Juan Pablo Sala 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 65
  • Joined: 16-June 09

Posted 15 October 2010 - 07:46 AM

No había visto tu respuesta, ahora mismo la leo, pero desde ya MUCHAS gracias

Juan
0

#4 User is offline   Juan Pablo Sala 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 65
  • Joined: 16-June 09

Posted 15 October 2010 - 10:17 AM

Nancoder, gracias por tu código, hay algo que no se como hacer, en realidad, el campo por el que quiero buscar no forma parte del query, es un método de mi clase ($data->ultimoComentario->fecha). Lo que me gustaría es que forme parte del query y ahí si usar tu código.
Acá te dejo un query que representa mas o menos lo que quiero:
select t.*, e.texto as estado, p.texto as prioridad,
    (select fecha from comentario c where c.ticket_id = t.id order by fecha desc  limit 1) as ultimoComentarioFecha,
    (select u.username 
        from comentario c 
            inner join usuario u on u.id = c.usuario_id
            where c.ticket_id = t.id order by fecha desc  limit 1
    ) as ultimoComentarioPor
    from ticket t
        inner join estado e on e.id = t.estado_id
        inner join prioridad p on p.id = t.prioridad_id
    

Me gustaría lograr lo mismo pero sin los subselect, con inner joins y limit 1, pero eso puede esperar :) el paso ahora es lograr que el query tenga el campo por el que quiero ordenar

Alguna idea???
0

#5 User is offline   Juan Pablo Sala 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 65
  • Joined: 16-June 09

Posted 15 October 2010 - 11:22 AM

últimos avances :)
Agregué una relación en la clase ticket de esta manera:
  'ultimoComentario' => array(self::HAS_ONE, 'Comentario', 'id',
                    'with' => 'usuario',
                    'order' => 'fecha DESC'),
            ),

También un sort en el método search de la clase ticket:
    $sort = new CSort();
    $sort->attributes = array(
        ....
        'ultimoComentarioFecha' => array(
            'asc' => 'ultimoComentario.fecha',
            'desc' => 'ultimoComentario.fecha DESC',
        ),
        'ultimoComentarioPor' => array(
            'asc' => 'ultimoComentario.usuario.username',
            'desc' => 'ultimoComentario.usuario.username DESC',
        ),);

Por último, en las opciones de la llamada al CGridView agregué simplemente:
            array(
                'name' => 'ultimoComentarioFecha',
                'value' => '$data->ultimoComentario->fecha',
                'filter' => '',
                'cssClassExpression' => '$data->leido ? null:"leido"',
//                'htmlOptions' => array('width' => '70px'),
            ),
            array(
                'name' => 'ultimoComentarioPor',
                'value' => '$data->ultimoComentario->usuario->username',
                'filter' => '',
                'cssClassExpression' => '$data->leido ? null:"leido"',
                'htmlOptions' => array('width' => '50px'),
            ),


Ya está todo muuuucho mejor que antes, lo único que no funciona es el orden por "ultimoComentarioPor", me dice:
Column not found: 1054 Unknown column 'ultimoComentario.usuario.username' in 'order clause'</p>

A pesar que tengo un 'with' con usuario en la relación.
Alguna idea???
0

#6 User is offline   Juan Pablo Sala 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 65
  • Joined: 16-June 09

Posted 15 October 2010 - 03:41 PM

>>"ultimoComentarioPor", me dice:

>>Column not found: 1054 Unknown column 'ultimoComentario.usuario.username' in 'order clause'</p>


>>A pesar que tengo un 'with' con usuario en la relación.
>>Alguna idea???

mi error, por supuesto, era usuario.username y no ultimoComentario.usuario.username

todo perfecto, que bien el yii!! lo amo jaja
0

#7 User is offline   nancoder 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 21
  • Joined: 14-June 10
  • Location:Querétaro, Mx

Posted 16 October 2010 - 07:41 PM

View PostJuan Pablo Sala, on 15 October 2010 - 03:41 PM, said:

>>"ultimoComentarioPor", me dice:

>>Column not found: 1054 Unknown column 'ultimoComentario.usuario.username' in 'order clause'</p>


>>A pesar que tengo un 'with' con usuario en la relación.
>>Alguna idea???

mi error, por supuesto, era usuario.username y no ultimoComentario.usuario.username

todo perfecto, que bien el yii!! lo amo jaja


Que bueno que te haya servido Juan! Posted Image

Saludos!



Configure your app enviroment with this Easy Enviroment Class

Follow me on Twitter | LinkedIn
0

#8 User is offline   mauricioschneider 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 152
  • Joined: 16-August 10
  • Location:Santiago, Chile

Posted 18 October 2010 - 11:32 PM

Bastante útil el aporte nancoder, deberías agregarlo a la wiki. :rolleyes:
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users