2014-02-18 3 views
0

У меня есть следующие схемы баз данных: Person 1 - 1 Контакт 1 - * АдресEloquent Модель ID missmatch от присоединиться к

Существует также другой объект, который является контактным, поэтому контакт таблицы необходим.

я получить доступ к списку лиц, как это:

$persons = Person::with('contact.addresses') 
      ->filter($string) 
      ->withoutCompany() 
      ->orderBy('persons.surname', 'ASC') 
      ->get(); 

Проблема заключается в том, что красноречивая модели, которая возвращается перезаписывает поле идентификатора личности с идентификатором контакта таблицы. Это происходит из-за масштабов запросов фильтра ($ строка), которую можно увидеть ниже:

public function scopeFilter($query, $parameter) { 
    return $query 
      ->join('contacts', 'persons.contact_id', '=', 'contacts.id') 
      ->join('addresses', 'addresses.contact_id', '=', 'contacts.id') 
      ->where(function($q) use($parameter) { 
       $q->where('addresses.city', 'like', $parameter) 
       ->orWhere('persons.surname', 'like', '%' . $parameter . '%') 
       ->orWhere('persons.name', 'like', '%' . $parameter . '%') 
       ->orWhere('addresses.postcode', 'like', $parameter . '%'); 
      }); 
} 

public function scopeWithoutCompany($query) { 
    return $query->whereRaw('persons.id not in (select company_person.person_id from company_person)'); 
} 

Эта проблема уже обратился here

Он утверждает, что следует использовать оператор выбора, потому что, если тот же столбец имя выбирается несколько раз, последний будет перезаписывать прецеденты при использовании объединений для заполнения красноречивой модели. Но когда я использую оператор select в области запроса, например. выбирая только persons.* и addresses.* - Я получаю ошибку Cardinality violation: 1241 Operand should contain 23 column(s) другой модели, где я использую область действия в условиях интенсивного ограничения загрузки (Person и Address вместе имеют 23 столбца).

Я исправил эту проблему уродливым обходным путем, снова присоединившись к таблице «Персоны» в качестве последнего соединения, чтобы перезаписать идентификатор личности. Но это не может быть решением моей проблемы. Кто-нибудь знает, как я могу это решить?

Это обходной путь от моего лица :: фильтр ($ строки) область видимости запроса:

return $query 
      ->select(array('persons.*', 'addresses.*')) 
      ->join('contacts', 'persons.contact_id', '=', 'contacts.id') 
      ->join('addresses', 'addresses.contact_id', '=', 'contacts.id') 
      ->join('persons as p', 'p.id', '=', 'persons.id') 
      ->where(function($q) use($parameter) { 
       $q->where('addresses.city', 'like', $parameter) 
       ->orWhere('persons.surname', 'like', '%' . $parameter . '%') 
       ->orWhere('persons.name', 'like', '%' . $parameter . '%') 
       ->orWhere('addresses.postcode', 'like', $parameter . '%'); 
      }); 

Для справки:

Это код, который приводит к ошибке нарушения кардинального (sehcma базы данных Компания * - * Лицо):

$companies = Company::with(array('persons' => function($q) use ($string) 
     { 
      $q->filter($string); 
     }) 
     )->whereHas('persons', function($q) use ($string) 
     { 
      $q->filter($string); 
     }) 
     ->orderBy('name', 'ASC') 
     ->get(); 
+0

Почему бы не использовать Тесные отношения? Это делает вашу жизнь намного проще (: – jah

+0

вы можете сделать пример красноречивого отношения, которое имеет тот же результат, что и мой фильтр выше? Мне нужно будет использовать whereHas, если я прав, но я не могу поставить это ограничение на адресная таблица, поскольку она напрямую не связана с Лицом –

ответ

1

Спасибо пользователю Kindari на Laravel.io У меня есть решение сейчас. Я не устанавливаю условие непосредственно в свою адресную таблицу, но у меня есть предложения where в области запроса в моей модели Address.

В моей модели Persn в области запроса я сначала извлекаю все соответствующие адреса. Я помещаю идентификаторы в список и ограничиваю своих Лиц только теми, кто живет по адресам. С этим у меня есть еще один запрос, но у меня нет никакого соединения. См решение ниже

public function scopeFilter($query, $parameter) { 
    $contact_ids = Address::filter($parameter)->lists('contact_id'); 
    $query->with('contact') 
      ->where(function($q) use ($parameter, $contact_ids) { 
       $q->where('persons.surname', 'like', '%' . $parameter . '%') 
       ->orWhere('persons.name', 'like', '%' . $parameter . '%'); 
       if($contact_ids) { 
        $q->orWhereIn('contact_id', $contact_ids); 
       } 
      }); 


    return $query; 
} 

Эта часть

$q->where('addresses.city', 'like', $parameter) 
      ->orWhere('addresses.postcode', 'like', $parameter . '%'); 

теперь входит в объем запроса модели адреса.

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

Смежные вопросы