Ашманные отношения и идентификатор от другой модели в CakePhp

StackOverflow https://stackoverflow.com/questions/3619891

  •  26-09-2019
  •  | 
  •  

Вопрос

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

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

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

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

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' => ''
    )
);

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

Есть идеи?

Спасибо!

Это было полезно?

Решение

Используйте содержательное поведение. 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' ) ) );

Другие советы

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

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

То, что я сделал, чтобы удовлетворить подобные потребности, это сочетание вещей, следующее:

Я использую свой 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, явно пересылаю информацию о сеансе обратной модели (вместо того, чтобы просить модель доступа к ней напрямую), при настройке условий запроса для использования значения сеанса каждый раз, когда каждый раз записи из модели извлекается, если у пользовательского назначения уже не участвует.

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

Попробуйте использовать BindModel из AppControllers Fromfilter.

...
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
                        ...
                    ),
                    ...
                ),
                ...
            ),
        );
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top