2
votes

To explain the issue I'm having, I'll use an example. Let's say that I'm building a system where students can sign up for one or more afterschool courses, but a school official has to approve the sign-up in order for it to be valid. So I have these models:

  • Course (belongs to "Teacher", hasAndBelongsToMany "Student")
  • Student (hasAndBelongsToMany "Course")
  • Teacher (hasMany "Course")

Now let's say I want to see a list of all of the unapproved sign-ups that are for ninth-graders. That's easy:

$this->request->data = $this->Student->CoursesStudent->find('all', array(
    'conditions' => array(
        'CoursesStudent.is_approved' => null,
        'Student.grade' => 9
    )
));

The thing that I'm struggling with is pulling the teacher's data as well (more than just their ID). I've tried this:

$this->request->data = $this->Student->CoursesStudent->find('all', array(
    'conditions' => array(
        'CoursesStudent.is_approved' => null,
        'Student.grade' => 9
    ),
    'contain' => array(
        'CoursesStudent',
        'Course' => array(
            'Teacher' => array(
                'fields' => array(
                    'Teacher.id',
                    'Teacher.name'
                )
            )
        ),
        'Student'
    )
));

But it doesn't have any effect whatsoever on the returned array. To make it easy for you to throw this into an existing CakePHP project to play with, here is the database schema and data and here is what you can paste into a random action of an existing CakePHP project. This is what I'm trying to get (notice that the teacher's data is there):

Array
(
    [0] => Array
        (
            [CoursesStudent] => Array
                (
                    [id] => 1
                    [course_id] => 1
                    [student_id] => 1
                    [is_approved] => 
                    [created] => 2012-12-11 00:00:00
                    [modified] => 2012-12-11 00:00:00
                )

            [Course] => Array
                (
                    [id] => 1
                    [teacher_id] => 1
                    [title] => Introduction to Improvisation
                    [start_date] => 2012-12-17
                    [end_date] => 2012-12-21
                    [created] => 2012-12-11 00:00:00
                    [modified] => 2012-12-11 00:00:00
                    [Teacher] => Array
                        (
                            [id] => 1
                            [first_name] => John
                            [last_name] => Doe
                            [created] => 2012-12-11 00:00:00
                            [modified] => 2012-12-11 00:00:00
                        )

                )

            [Student] => Array
                (
                    [id] => 1
                    [first_name] => Bill
                    [last_name] => Brown
                    [grade] => 9
                    [created] => 2012-12-11 00:00:00
                    [modified] => 2012-12-11 00:00:00
                )

        )

)

Thanks!

1
Out of curiosity, what are your intentions with saving the model find to $this->request->data That object is reserved for the data that gets submitted through a form.Tim Joyce
first: you may have recursive set to 0 or -1. second: remove contain, that only helps you narrow down data that you know is coming through the model. Contain will not help you query for additional data. third: Your models may not be setup correctly if the first option here is correct. Let's get a glimpse at those.Tim Joyce
@TimJoyce It's my understanding that with an edit form, for example, data that is in $this->request->data will be used to populate the form. You can also use $this->data, though, right? Perhaps that is more correct.Nick
yes... that is correct.. I am used to that magic happening by itself!Tim Joyce
If you run $this->Student->find('all'); and you see your Teacher results coming through, change your find models to $this->Student->Course->find('all'); They don't show this documentation in the new 2.x book but it is in the 1.2 book. book.cakephp.org/1.2/view/83/hasAndBelongsToMany-HABTMTim Joyce

1 Answers

1
votes

You must set $recursive to -1 before using contain() will work.

Also, make sure your model is set to use the Containable Behavior. In this case, since 'Course' is also containing something, it needs to use the Containable behavior too.

(You could think about setting the below $actsAs in your AppModel to make Containable available to every model.)

//in your CoursesStudent model (and in your Course model)
public $actsAs = array('Containable');

And here's your find, but with setting recursive first:

$this->Student->CoursesStudent->recursive = -1;
$this->request->data = $this->Student->CoursesStudent->find('all', array(
    'conditions' => array(
        'CoursesStudent.is_approved' => null,
        'Student.grade' => 9
    ),
    'contain' => array(
        'CoursesStudent',
        'Course' => array(
            'Teacher' => array(
                'fields' => array(
                    'Teacher.id',
                    'Teacher.name'
                )
            )
        ),
        'Student'
    )
));