Как мне использовать это косвенное отношение?

Я работаю над внедрением на свой сайт системы репутации, аналогичной SO. Вот как это устроено:

User hasMany Project
User hasMany Answer
Project hasMany Rating
Ответ hasMany Rating
Рейтинг принадлежит проекту, где Rating.parent_type = Project
Рейтинг принадлежит ответу, где Rating.parent_type = Answer

Поле значения рейтинга будет числом от 1 до 5. Пользователь должен получить +10 за каждый отзыв с 5 звездами, +5 за каждый отзыв с 4 звездами и +1 за каждый отзыв с 3 звездами. В настоящее время я настроил его следующим образом: действие recalcRep($id) в UsersController (наряду с другими действиями в других контроллерах, когда это необходимо) вызывает метод calcRep($id) внутри модели User, который должен вычислить репутацию пользователя с идентификатором $id.

public function calcRep($id) {
        $rep = 0;

        $data = $this->Rating->find('all'); //does not work, because it is not directly associated
        foreach($data as $rating) {
            if(($rating['Rating']['parent_type'] == 'Project' && $rating['Project']['user_id']==$id) or ($rating['Rating']['parent_type'] == 'Answer' && $rating['Answer']['user_id']==$id)) {
                if($rating['Rating']['value']==5) {
                    $rep += 10;
                } else if($rating['Rating']['value']==4) {
                    $rep += 5;
                } else if($rating['Rating']['value']==3) {
                    $rep += 2;
                }
            }
        }
        $data['User']['reputation'] = $rep;
        $this->save($data);
    }

Возможно, я подхожу к этому совершенно неправильно, но я не могу понять, как найти все рейтинги, принадлежащие любому из детей определенного пользователя.


person tyjkenn    schedule 04.05.2012    source источник


Ответы (1)


Я думаю, что cakePHP требует, чтобы, если вы собираетесь вызывать определение модели из контроллера, имя контроллера должно быть таким же, как у модели, например, поскольку вы вызываете $this->Rating, класс, вызывающий его, должен быть RatingController или что-то в этом роде. как это. Лучше всего вызвать find('all') внутри вашего RatingController и сохранить его во временной переменной, которую вы передаете calcRep(), т.е.:

<?php
class RatingsController extends AppController {
    function calcRep($id) {
        $rep = 0;

        $data = $this->Rating->find('all'); //should work now, as you're calling it from the defined controller
        foreach($data as $rating) {
            if(($rating['Rating']['parent_type'] == 'Project' && $rating['Project']['user_id']==$id) or ($rating['Rating']['parent_type'] == 'Answer' && $rating['Answer']['user_id']==$id)) {
                if($rating['Rating']['value']==5) {
                    $rep += 10;
                } else if($rating['Rating']['value']==4) {
                    $rep += 5;
                } else if($rating['Rating']['value']==3) {
                    $rep += 2;
                }
            }
        }
        $data['User']['reputation'] = $rep;
        $this->save($data);
    }

}

?>

Я полагаю, что есть также функция loadModel()? Возможно, если вы loadModel('Rating') заранее, это сработает.

Похоже, что модель интерпретации PHP для cakePHP не позволяет вам делать это внутри модели, поскольку то, что вы пытаетесь сделать, идеально подходит для контроллера.

person Luminous_Path    schedule 05.05.2012
comment
Тогда кажется, что я столкнулся бы с большим количеством проблем. Я хочу, чтобы в результате значение репутации кэшировалось в поле «репутация» в таблице пользователей. Кроме того, в конечном итоге рейтинги будут не единственным фактором, влияющим на репутацию, поэтому представляется более целесообразным хранить их в User. - person tyjkenn; 05.05.2012
comment
вы все еще манипулируете данными здесь, поэтому они должны быть в контроллере. Если вы хотите взять информацию из рейтинговой таблицы, манипулировать ею и сохранить в таблице пользователей, загрузите пользователя в контроллер, из которого вы это вызываете. Это должен быть контроллер, или вы должны сначала загрузить модели. Вы должны иметь возможность вызывать $this->loadModel('User');, а затем $this->User->save($data);, если хотите сохранить его в таблице пользователей. - person Luminous_Path; 06.05.2012