Я пытаюсь получить «связанные» связанные модели, запрашивая таблицу ссылок с именем company_projects, которая содержит (как вы ожидаете) идентификаторы компаний и проектов (проекты являются своего рода категориями продуктов).
В этом случае используемый поток для определения связанного проекта:
То, что я пытаюсь сделать, уже работает в следующем сырье запрос:
SELECT
*
FROM
projects
WHERE
projects.id IN
(
SELECT cp1.project_id
FROM company_projects cp1
WHERE cp1.company_id IN
(
SELECT cp1.company_id
FROM projects p
LEFT JOIN company_projects cp2 ON cp2.project_id = p.id
WHERE p.id = X AND cp2.company_id != Y
)
)
AND projects.id != X
X = идентификатор текущего проекта («категория продукта»)
Y = идентификатор текущего пользователя (компании)
Но мой реальный вопрос заключается в том, как сделать это элегантно в Laravel Eloquent (в настоящее время v4.2). Я попробовал, но пока мне не повезло …
Обновить:
Должен отметить, что у меня есть опыт использования Eloquent и Models в нескольких проектах, но по какой-то причине у меня просто не получается выполнить этот конкретный запрос. Так что надеялся увидеть объяснение решения. Возможно, я ошибаюсь и ответ относительно прост.
Вам нужно будет использовать Красноречивые отношения чтобы добиться этого. (Обратите внимание, что я ссылаюсь на 4.2 документа, так как это то, что вы используете, но я настоятельно рекомендую обновить Laravel до 5.1)
Я предполагаю, что у вас уже есть модели «Компания» и «Проект». Внутри каждой из этих моделей вам нужно определить метод, который связывает его отношение с другой моделью. Исходя из вашего описания, звучит так, что у обоих есть Много ко многим отношения, что означает, что компания может иметь много проектов, и проект может также принадлежать многим компаниям. У вас уже есть таблица базы данных, связывающая их. В Eloquent ORM эта таблица ссылок называется сводная таблица. Когда вы определяете ваши отношения в модели, вам нужно будет передать имя этой сводной таблицы в качестве второго аргумента. Вот как это может выглядеть для вас.
Модель компании:
class Company extends Model
{
/**
* Get the projects attached to a Comapny. Many To Many relationship.
*/
public function projects()
{
return $this->belongsToMany('Project','company_projects');
}
}
Модель проекта:
class Project extends Model
{
/**
* Get the companies this project belongs to. Many To Many relationship.
*/
public function companies()
{
return $this->belongsToMany('Company','company_projects');
}
}
Если в ваших моделях эти отношения определены, вы можете легко ссылаться на них в своих представлениях и в других местах. Например, если вы хотите найти все проекты, принадлежащие компании с идентификатором 1234, вы можете сделать это:
$company = Company::find(1234);
$projects = $company->projects;
Еще лучше, вы можете использовать то, что называется нетерпеливая загрузка, что сократит ваш поиск данных до одной строки (это в основном полезно при передаче данных в представления, и вы будете перебирать связанные модели в представлении). Таким образом, эти утверждения выше могут быть переписаны как:
$company = Company::with('projects')->find(123);
Это вернет модель вашей компании со всеми сопутствующими продуктами как собственность. Обратите внимание, что готовая загрузка может быть даже вложена с точечной нотацией. Это означает, что вы можете найти все модели, которые связаны с вашей основной моделью, а затем все модели для те модели и тд и тп.
Имея все это в виду, давайте посмотрим, чего конкретно вы хотите достичь.
Предположим, что этот метод встречается в контроллере, которому передается идентификатор проекта из маршрута.
public function showCompaniesAndProjects($id)
{
//Get all companies in the same project as you
//Use eager loading to grab the projects of all THOSE companies
//Result will be a Project Object with all Companies
//(and those projects) as Eloquent Collection
$companies = Project::with('companies.projects')->find($id);
//do something with that data, maybe pass it to a view
return view('companiesView')->with('companies',$companies);
}
После определения ваших отношений в ваших моделях вы можете выполнить весь запрос в одной строке.
Других решений пока нет …