tags:

views:

94

answers:

1

I am working on a book review application and I am using autoComplete to search for titles in when creating a review. The review model has an associated book_id field and the relationship is setup as the review hasOne book and a book hasMany reviews.

I am trying to pass the Book.id (into the book_id field), but I want to display Book.name for the user to select from. With the default setup (accomplished via CakePHP's tutorial), I can only pass Book.name. Is it possible to display the name and pass the id?

Also, I am passing it via the following code in the create() action of the review controller:

$this->data['Review']['book_id'] = $this->data['Book']['id'];

Is that the proper way to do it in CakePHP? I know in Ruby on Rails, it is automatic, but I can't seem to make it work automagically in CakePHP. Finally, I am not using the generator because it is not available in my shared hosting environment... so if this is the wrong way, what do I need other than associates in my models to make it happen automatically?

Thanks for the help and I promise this is my question for awhile...

UPDATE- I tried the following, but it is not working. Any ideas why?

    function autoComplete() {
    $this->set('books', $this->Book->find('all', array(
        'conditions' => array(
            'Book.name LIKE' => $this->data['Book']['name'].'%'
        ),
        'fields' => array('id','name')
    )));
    $this->layout = 'ajax';
}

The problem is that when I use the code above in the controller, the form submits, but it doesn't save the record... No errors are also thrown, which is weird.

UPDATE2:

I have determine that the reason this isn't working is because the array types are different and you can't change the array type with the autoComplete helper. As a workaround, I tried the follow, but it isn't working. Can anyone offer guidance why?

function create() {
    if($this->Review->create($this->data) && $this->Review->validates()) {
        $this->data['Review']['user_id'] = $this->Session->read('Auth.User.id');
        $this->Book->find('first', array('fields' => array('Book.id'), 'conditions' => array('Book.name' => $this->data['Book']['name'])));
        $this->data['Review']['book_id'] = $this->Book->id;
        $this->Review->save($this->data);
        $this->redirect(array('action' => 'index'));
    } else {
        $errors = $this->Review->invalidFields();
    }
}

FINAL UPDATE:

Ok, I found that the helper only takes the find(all) type or array and that the "id" field wasn't passing because it only applied to the autoComplete's LI list being generated. So, I used the observeField to obtain the information and then do a database lookup and tried to create a hidden field on the fly with the ID, but that didn't work. Finally, the observeField would only take the characters that I put in instead of what I clicked, due to an apparent Scriptaculous limitation. So, I ended up going to a dropdown box solution for now and may eventually look into something else. Thanks for all of the help anyway!

A: 

First of all, $this->data will only contain ['Book']['id'] if the field exists in the form (even if it's hidden).

To select something by name and return the id, use the list variant of the find method, viz:

    $selectList = $this->Book->find('list', array(
                                               'fields' => array(
                                                              'id', 
                                                              'name'
                                            )));
    $this->set('selectList', $selectList);

In the view, you can now use $selectList for the options in the select element:

    echo $form->input('Book.id', array('type' => 'hidden'));
    echo $form->input('template_id', array(
                                        'options' => $selectList,
                                        'type' => 'select'
                                     ));
Leo
I just had one question that I posted above. Not sure why both fields aren't passing? Is the syntax correct there? If so, I can check other things, but I didn't see any typos in my controllers or anything.
Justin
You're using find('all'...) rather than find('list'...). I don't know the logic of your application, but try using a debug($this->data) statement just before the save statement to see what the form is returning.
Leo
I am just using the AjaxHelper for autoComplete as standard in CakePHP. When I switch to "list" instead of "all" it says "Cannot Use String Offset as an Array" in the ajax dropdown. This may be related to the fact it is using a LIKE query?
Justin
What did the debug tell you? You could also use the Firebug plugin in Firefox to have a look at what is getting set when you select a book.
Leo
It leads me to believe that it is because the helper handles the data in a specific way and the array format for "list" and "all" find() are different. The error for the dropdown is "Cannot Use String Offset as an Array", do you know what that error means?
Justin
Leo
Ok, I determined the problem here (you can't use find(all) with that helper). I tried an alternative solution but am still having problems. Do you know why this wouldn't work? (Shows no errors upon submit, but data doesn't save) Also, I have $uses defined to the Books model in the Review controller...
Justin
debug($this->data); and post the results.
Leo