Estoy tratando de crear una consulta Elocuente para encontrar un modelo que tenga relaciones en las que su columna sea igual a uno de los valores dados, pero ningún otro. Por ejemplo, un modelo podría tener varias relaciones cuya columna contiene uno de los valores dados, pero tener otra relación que no lo hace y, por lo tanto, debe omitirse.
Todo lo que tengo hasta ahora es una consulta whereHas que encuentra los modelos cuyas relaciones contienen los valores. Esto funciona exactamente como debería, pero quiero omitir los modelos que contienen una relación sin estos valores, incluso si tienen una relación que sí los tiene.
$query->whereHas('conditions', function($query) use ($category_ids) { $query->where('conditionable_type', EmployeeCategoryOption::class) ->whereIn('conditionable_id', $category_ids); });
He buscado en los documentos pero no puedo encontrar ningún método Eloquant que haga lo que busco.
Gracias por tu tiempo.
EDITAR (escenario de ejemplo)
Tabla de condiciones:
id | conditionable_id | option_id 1 | 1 | 1 2 | 2 | 1 3 | 3 | 1 4 | 3 | 2 5 | 4 | 3
Me gustaría obtener todas las opciones que tienen una condición con conditionable_id igual a 3 o 4 y ninguna otra. En la tabla anterior, esto devolvería las opciones 2 y 3, ya que la opción 1 también tiene conditionable_id 1 y 2.
Si tiene el opuesto de $category_id
como $notCategoryIds
$query->whereDoesntHave('conditions', function($query) use ($notCategoryIds) { $query->where('conditionable_type', EmployeeCategoryOption::class) ->whereIn('conditionable_id', $notCategoryIds); })->whereHas('conditions', function($query) { $query->where('conditionable_type', EmployeeCategoryOption::class); })
Si no tiene la lista de categorías invertidas, hágalo así.
$query->whereDoesntHave('conditions', function($query) use ($category_id) { $query->where('conditionable_type', EmployeeCategoryOption::class) ->whereIn( 'conditionable_id', \DB::table('conditionable_option')->where('conditionable_type', EmployeeCategoryOption::class) ->whereNotIn('conditionable_id', $category_id) ->pluck('conditionable_id')->toArray(); ); })->whereHas('conditions', function($query) { $query->where('conditionable_type', EmployeeCategoryOption::class); })
Puede cambiar esa consulta de extracción interna a un formulario de generador de consultas en lugar de una consulta de obtención de resultados para hacerlo más rápido utilizando algunas uniones y alias.
Puede usar addSelect()
para agregar solo los modelos que necesita según su consulta.
$query->whereHas('conditions', function($query) use ($category_ids) { $query->where('conditionable_type', EmployeeCategoryOption::class) ->whereIn('conditionable_id', $category_ids); })->addSelect(['conditions' => Condition::select('field') ->whereColumn('your_field_id', 'condition.id') ->where('conditionable_type', EmployeeCategoryOption::class) ->whereIn('conditionable_id', $category_ids); ]);
Podría refactorizar addSelect()
a una función de alcance personalizada en su modelo.