0

会社とプロジェクトの ID を保持する company_projects という名前のリンク テーブルにクエリを実行して、「関連する」リンク モデルを取得しようとしています (プロジェクトは一種の製品カテゴリです)。

この場合、関連プロジェクトを決定するために使用されるフローは次のとおりです。

  1. あなたと同じプロジェクト(「製品カテゴリ」)にある会社を取得します。
  2. それらの会社にリンクされている他のプロジェクト IDを見つけます
  3. 最後のステップで取得されたリンクされたプロジェクトの情報を取得します


私がやろうとしていることは、次の生のクエリですでに機能しています:

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 = 現在のプロジェクトの ID (「製品カテゴリ」)
Y = 現在の「ユーザー」の ID (会社)


しかし、私の本当の質問は、Laravel Eloquent (現在 v4.2) でこれをエレガントに行う方法です。試してみましたが、今のところ運がありません...

更新:
複数のプロジェクトで Eloquent とモデルを使用した経験があることに注意してください。ただし、何らかの理由で、この特定のクエリで失敗します。だから、説明された解決策を見たいと思っていました。私の考えが間違っている可能性があり、答えは比較的簡単です。

4

1 に答える 1

1

これを達成するには、雄弁な関係を利用する必要があります。(あなたが使っているのは 4.2 のドキュメントにリンクしていることですが、Laravel を 5.1 にアップグレードすることを強くお勧めします)

「会社」と「プロジェクト」モデルがすでにあると仮定しています。これらの各モデル内で、他のモデルとの関係を参照するメソッドを定義する必要があります。あなたの説明に基づくと、この 2 つは多対多の関係にあるように思えます。つまり、1 つの企業が複数のプロジェクトを持つことができ、1 つのプロジェクトが複数の企業に属することもできます。2 つをリンクするデータベース テーブルが既にあります。Eloquent ORM では、このリンク テーブルはピボット テーブルと呼ばれます。モデルでリレーションシップを定義するときは、そのピボット テーブルの名前を 2 番目の引数として渡す必要があります。それがあなたを探す方法は次のとおりです。

会社のモデル:

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

モデルにこれらの関係が定義されている場合は、ビューや他の場所で簡単に参照できます。たとえば、ID が 1234 の会社に属するすべてのプロジェクトを検索する場合は、次のようにします。

$company = Company::find(1234);
$projects = $company->projects;

さらに良いことに、eager loadingと呼ばれるものを利用できます。これにより、データ ルックアップが 1 行に削減されます (これは主に、データをビューに渡し、ビュー内の関連するモデルをループする場合に役立ちます)。したがって、上記のステートメントは次のように書き換えることができます。

$company = Company::with('projects')->find(123);

これにより、関連するすべての製品をプロパティとして持つ Company モデルが返されます。熱心な読み込みは、ドット表記でネストすることもできることに注意してください。これは、メイン モデルにリンクするすべてのモデルを検索し、それらのモデルのすべてのモデルを検索できることを意味します

これらすべてを念頭に置いて、具体的に達成したいことを見てみましょう。

このメソッドが、ルートからプロジェクト ID を渡されるコントローラーで発生すると仮定します。

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);
}

モデルでリレーションを定義したら、クエリ全体を 1 行で実行できます。

于 2015-10-20T19:38:57.780 に答える