使用laravel基于多对多关系雄辩地搜索数据的查询逻辑

时间:2018-08-18 06:52:35

标签: database laravel database-design eloquent relational-database

我有guidesareas表,它们之间存在多对多关系,因此我有另一个表将它们连接起来,名为guidings。快速解释,在现实生活中,导游知道许多领域,许多导游可以知道一个领域。 我想根据用户发送给控制器的一系列区域搜索导游,但同时导游还必须在视图中附带他的专业领域信息(他知道)。

类似于以下表格:

guides
   - id       integer, primary key
   - name     string

areas
   - id       integer, primary key
   - name     string

guidings
   - guide_id integer, foreign key
   - area_id  integer, foreign key

我已经建立了如下模型:

model guide
   public function guides()
   {
     return $this->belongsToMany('App\Area', 'guidings', 'guide_id', 'area_id');
   }

model area
   public function users()
   {
      return $this->belongsToMany('App\User', 'guidings', 'area_id', 'guide_id');
   }

我的控制器看起来像这样

$areas = [1, 2, 3]; //actually this array i get from request, it based on id of area

$guides = Guide::with('areas')->where('id', '>' , 0);
$countGuide = count(Guide::all());
for ($i=0; $i < $countGuide; $i++) {
     $guides = $guides->orWhere(); //i stuck in here
}
$guides = $guides->get();

return response()->json($guides); //the data will be sent to ajax in view

所以我该如何基于用户发送给控制器的一系列区域来搜索导游,但同时导游还必须在视图中附带他的专业领域信息(他知道)。 有什么建议吗?谢谢

2 个答案:

答案 0 :(得分:0)

如果指南不需要匹配所有区域,那么您可能会遇到类似情况:

    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/background"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#f5aaaa"
        app:layout_constraintBottom_toBottomOf="@+id/button3_txt"
        app:layout_constraintLeft_toLeftOf="@+id/left_barrier"
        app:layout_constraintRight_toRightOf="@+id/right_barrier"
        app:layout_constraintTop_toTopOf="@+id/button1_txt" />

    <TextView
        android:id="@+id/button1_txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:elevation="8dp"
        android:padding="16dp"
        android:text="small"
        app:layout_constraintBottom_toTopOf="@+id/button2_txt"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <TextView
        android:id="@+id/button2_txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:elevation="8dp"
        android:padding="16dp"
        android:text="Bigggggeer"
        app:layout_constraintBottom_toTopOf="@+id/button3_txt"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button1_txt" />

    <TextView
        android:id="@+id/button3_txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:elevation="8dp"
        android:padding="16dp"
        android:text="Even Bigggggggggeer"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button2_txt" />

    <Button
        android:id="@+id/button1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="@+id/button1_txt"
        app:layout_constraintLeft_toLeftOf="@+id/left_barrier"
        app:layout_constraintRight_toRightOf="@+id/right_barrier"
        app:layout_constraintTop_toTopOf="@+id/button1_txt" />

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="@+id/button2_txt"
        app:layout_constraintLeft_toLeftOf="@+id/left_barrier"
        app:layout_constraintRight_toRightOf="@+id/right_barrier"
        app:layout_constraintTop_toTopOf="@+id/button2_txt" />

    <Button
        android:id="@+id/button3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="@+id/button3_txt"
        app:layout_constraintLeft_toLeftOf="@+id/left_barrier"
        app:layout_constraintRight_toRightOf="@+id/right_barrier"
        app:layout_constraintTop_toTopOf="@+id/button3_txt" />

    <android.support.constraint.Barrier
        android:id="@+id/right_barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="end"
        app:constraint_referenced_ids="button1_txt, button2_txt, button3_txt" />

    <android.support.constraint.Barrier
        android:id="@+id/left_barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="start"
        app:constraint_referenced_ids="button1_txt, button2_txt, button3_txt" />

</android.support.constraint.ConstraintLayout>

如果指南必须与所有区域匹配,则可以混合使用return Guide::with('area')->whereHas('areas', function ($query) use ($areas) { $query->whereIn('id', $areas); })->get(); where in来完成此操作:

having

此外,如果您只想将指南以JSON格式返回,则只需从控制器返回集合,Laravel就会自动为您将其转换为JSON(数组也是如此)。

答案 1 :(得分:0)

如果guide_idarea_id的每种组合只有一个枢轴行,则可以使用以下方法:

$guides = Guide::whereHas('areas', function($query) use($areas) {
    $query->whereIn('areas.id', $productIds);
}, '=', count($areas))->with('areas')->get();