Saturday, February 28, 2009

Complex model relationship problems

Hi bakers!

In my application I've got the concept of "Spaces" which are basically
directories. I also have User and Document models.

Space -> HABTM <- User (a user may have access to several spaces)
Space -> hasMany -> Document
Document -> HABTM <- User (a document can have several owners)

The HABTM relationships are set up according to the solution shown
here: http://www.cricava.com/blogs/index.php?blog=6&title=modelizing_habtm_join_tables_in_cakephp_&more=1&c=1&tb=1&pb=1

Space uses the Tree behavior and the spaces table is properly
configured to use it (lft, rght and parent_id columns). A Space
contains Documents, and both Space and Document can be created by a
User.

I've been trying for two days to try figuring out how to do this:

1. Get a tree of all rooms and documents that a specific user is
associated with
2. Do the same, but only for a sub-tree

This seems impossible to do because Cake thinks that it should look
for parent_id, lft, and rght in the table spaces_users when using the
following query:

$spaces = $this->SpacesUser->find('threaded', array(
'conditions' => array('User.id' => $user),
'contain' => array(
'User.id', 'User.username',
'Space.name', 'Space.description', 'Space.created',
'Space.parent_id', 'Space.lft', 'Space.rght',
'Document'
),
'order' => array('Space.name')
)
);

On the other hand, this is the only way I can think of that allows me
to get the spaces associated with the user. Cake gives the following
errors:

Model "SpacesUser" is not associated with model "Document" [CORE/cake/
libs/model/behaviors/containable.php, line 340]

Undefined index: parent_id [CORE/cake/libs/model/model.php, line
2163]

Note that when setting find('threaded'), the tree is not properly
built. Cake still returns a flat list.

Here are my models:

<?php
class Space extends AppModel {

var $name = 'Space';

var $actsAs = array('Tree');

var $hasAndBelongsToMany = array(
'User' => array(
'with' => 'SpacesUser'
)
);

var $hasMany = array(
'Document'
);

function get_structure($user = null) {
$spaces = $this->SpacesUser->find('threaded', array(
'conditions' => array('User.id' => $user),
'contain' => array(
'User.id', 'User.username',
'Space.name', 'Space.description', 'Space.created',
'Space.parent_id', 'Space.lft', 'Space.rght',
'Document'
),
'order' => array('Space.name')
)
);

return array('spaces' => $spaces);
}

}
?>

<?php
class User extends AppModel {

var $name = 'User';

var $hasAndBelongsToMany = array(
'Space' => array(
'with' => 'SpacesUser'
),
'Document' => array(
'with' => 'DocumentsUser'
)
);

}
?>

<?php
class Document extends AppModel {

var $name = 'Document';
var $hasAndBelongsToMany = array(
'User' => array(
'with' => 'DocumentsUser'
)
);

}
?>

<?php
class SpacesUser extends AppModel {

var $name = 'SpacesUser';
var $belongsTo = array('Space', 'User');

}
?>

<?php
class DocumentsUser extends AppModel {

var $name = 'DocumentsUser';
var $belongsTo = array('Document', 'User');

}
?>

<?php
class SpacesController extends AppController {

var $name = 'Spaces';
var $helpers = array('Html', 'Form', 'Time', 'Text');
var $components = array('RequestHandler');

var $paginate = array(
'order' => array('Space.name' => 'asc')
);

function index() {
$this->set('spaces', $this->Space->get_structure(7));
}

}
?>

I hope that someone will be able to help :) Thanks in advance!

- Dan
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "CakePHP" group.
To post to this group, send email to cake-php@googlegroups.com
To unsubscribe from this group, send email to cake-php+unsubscribe@googlegroups.com
For more options, visit this group at http://groups.google.com/group/cake-php?hl=en
-~----------~----~----~----~------~----~------~--~---

No comments: