Отношения HasMany и ID из другой модели в CakePHP - PullRequest
1 голос
/ 01 сентября 2010

Мне интересно, возможно ли создать отношение hasMany в модели, которая использует идентификатор зарегистрированного пользователя.

Пример: один совет имеет много голосов (от разных пользователей).Это просто:

public $hasMany = array(
   'TipVoting' => array(
        'className' => 'TipVoting',
        'foreignKey' => 'tip_id',
        'dependent' => false,
        'conditions' => '',
        'fields' => '',
        'order' => '',
        'limit' => '',
        'offset' => '',
        'exclusive' => '',
        'finderQuery' => '',
        'counterQuery' => ''
    ));

Теперь я хочу получить все Советы, но хочу знать, проголосовал ли зарегистрированный пользователь уже за этот Совет.Поэтому я хотел бы создать Realtionship, которое выглядит следующим образом:

public $hasMany = array(
   'MyTipVoting' => array(
        'className' => 'TipVoting',
        'foreignKey' => 'tip_id',
        'dependent' => false,
        'conditions' => array('TipVoting.user_id' => $loggedinUser_id),
        'fields' => '',
        'order' => '',
        'limit' => '',
        'offset' => '',
        'exclusive' => '',
        'finderQuery' => '',
        'counterQuery' => ''
    )
);

Как мне получить $ loggedinUser_id в этой модели?Или это плохой способ реализации этой проблемы?Должен ли я пойти на отдельную находку по модели TipVoting?

Есть идеи?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 01 сентября 2010

Используйте сдерживаемое поведение. http://book.cakephp.org/view/474/Containable

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

Используя только отношение TipVoting, в вашей модели сделайте следующее:

var $actsAs = array( 'Containable' );

в вашем действии контроллера сделайте это:

$this->TipVoting->find( 'all', array( 
 'contain' => array( 
   'Vote' => array( 
    'conditions' => array( 
      'TipVoting.user_id' => $this->Auth->User('id') ), 
    'order' => 'TipVoting.id DESC' ) ) );
0 голосов
/ 02 сентября 2010

Попробуйте использовать bindModel из appControllers beforeFilter.

...
public function beforeFilter( ){
    parent::beforeFilter( );
    if( $this->Auth->user( )){
        $this->User->bindModel(
            'hasMany' => array(
                'MyTipVoting' => array(
                    'className' => 'TipVoting',
                    'foreignKey' => 'tip_id',
                    'conditions' => array(
                        'MyTipVoting.user_id' => $this->Auth->user( 'id' ),
                        //note the use of the aliased name here, not TipVoting but MyTipVoting
                        ...
                    ),
                    ...
                ),
                ...
            ),
        );
    }
}
0 голосов
/ 01 сентября 2010

Если я понимаю вопрос, то, что вы действительно ищете, это способ определения условия один раз , а не способ определения условия соединения.Поведение Containable будет обрабатывать последнее, но не первое.С этой целью ...

Я не знаю ни одного способа использования значений переменных в вашем определении соединения.Так как это переменные класса, я подозреваю, что это невозможно сделать (отказ от ответственности: я не пробовал).У вас также есть дополнительная сложность при попытке получить доступ к тому, что обычно является значением сеанса (авторизованным пользователем) на уровне модели - что-то вроде MVC «нет-нет» в самом строгом смысле.

Что я сделалЧтобы удовлетворить аналогичные потребности, существует следующая комбинация:

Я использую мой AppController для пересылки аутентифицированной информации о пользователе:

# AppController
# You may or may not want to use the conditional
if( !empty( $this->data ) ) {
  $this->data['User'] = $this->Auth->user();
}

В вашей модели создайте обратный вызов beforeFind()это изменит структуру запроса:

# Your model, e.g. TipVoting
# The data[] array will probably be keyed differently
public function beforeFind( $query ) {
  if( array_key_exists( 'active', $this->_schema ) ) {
    $conditions = !empty( $query['conditions'] ) ? $query['conditions'] : array();

    if( !is_array( $conditions ) ) {
      $conditions = array( $conditions );
    }

    if( !isset ( $conditions['user_id'] ) && !isset( $conditions[$this->alias . '.user_id'] ) ) {
      $conditions[$this->alias . '.user_id'] = $this->data['User']['Administrator'];
    }

    $query['conditions'] = $conditions;
  }

  return $query;
}

Этот код является просто фрагментом кода, который удовлетворяет потребности аналогично вашему, поэтому он может не работать напрямую, но он должен дать вам представление очто возможно, и я думаю, что это может быть довольно близко к тому, что вы после.Просто имейте в виду, что вам, вероятно, придется внести некоторые изменения здесь и там.

Ключ заключается в том, что вы сохраняете «правильную» структуру MVC, явно перенаправляя информацию о сеансе в модель (вместо того, чтобы запрашиватьмодель для непосредственного доступа к нему) при настройке условия запроса на использование значения сеанса каждый раз, когда извлекаются записи из модели, если только условие, ориентированное на пользователя, уже не задействовано.

Это не идеально подходит для того, что выпосле, но это не должно занять слишком много времени, чтобы адаптировать его к вашим потребностям.

...