Mostrando entradas con la etiqueta relaciones. Mostrar todas las entradas
Mostrando entradas con la etiqueta relaciones. Mostrar todas las entradas

jueves, 28 de agosto de 2008

Usar condiciones al definir asociaciones de modelos

En todo el tiempo que llevo usando CakePHP nunca había probado hasta hoy el introducir condiciones en las relaciones entre Models. Es decir, al definir una relación (del tipo que sea) podemos poner condiciones que ha de cumplir el Model relacionado.

De este modo puedes tener dos Modelos relacionados de distintas formas y obtener datos de un modo incluso más fácil que pasando condiciones a un método find. Aunque no he explorado ni mucho menos las posibilidades de esta forma de trabajar, me voy a permitir poner un ejemplo útil de cómo funciona.

Supongamos dos modelos Autor y Post, de modo que Author hasMany Post (y Post belongsTo Author). Ahora supongamos también que Post tiene un campo published para indicar el estado de publicación del Post.

La relación "normal" en Author la definiríamos (minimalísticamente si seguimos todas las convenciones de CakePHP) como:

var $hasMany = array('Post')


Pero ahora, supongamos que nos interesa poder acceder a todos los Post de Author que estén publicados. De acuerdo, podríamos utilizar un find, pero ¿y si definimos una relación basada en esa condición?

'PostPublished' => array(
'className' => 'Post',
'joinTable' => 'posts_authors',
'foreignKey' => 'author_id',
'associationForeignKey' => 'post_id',
'conditions' => 'Posts.published = 1',
)


Pues lo que ocurre es que al hacer una búsqueda de Author, nos devolverá registros relacionados tanto en Post, como en PostPublished. En este caso, todos los Post y todos los Post publicados. En cierto modo, PostPublished es un modelo relacionado "virtual" que podemos manejar igual que uno definido realmente.

En este caso, debemos especificar las claves de la relación para asegurarnos de que se establece correctamente, ya que el nombre de la misma no respeta las convenciones.

(Nota: un uso de esta técnica es una típica página "home" de usuario, en la que mostremos todos sus objetos que cumplan cierta condición. Por ejemplo, tareas pendientes, posts sin publicar, etc.)

Combinado con bindModel y unbindModel o el Containable behavior (para restringir las relaciones y optimizar las query) puedes recabar con facilidad datos sin necesidad de recurrir a condiciones de búsqueda triviales o incluso complejas si las intentamos hacer en asociaciones habtm.

Precisamente ahora estoy estudiando un caso en el que las condiciones de búsqueda resultan bastante complicadas de establecer y los resultados no son los deseados y parece que aplicando esta idea, el problema podría quedar fácilmente resuelto. Ya contaré qué tal me va.