I checked the source code, union seems to be kind of hardcoded, in way that's not easy to use ->union(...)
but substitute 'intersect' under the hood.
that said, you can manually do it long-form like this:
$q = DB::table('items')->where('id','>', 1)->union(DB::table('items')->where('id', '<', 5));
DB::select(str_replace('union', 'intersect', $q->toSql()), $q->getBindings());
or better:
$q1 = DB::table('items')->where('id','>', 1);
$q2 = DB::table('items')->where('id', '<', 5);
DB::select($q1->toSql().' intersect '.$q2->toSql(), array_merge($q1->getBindings(), $q2->getBindings()));
With Eloquent:
$q1 = Item::query()->where('id','>', 1);
$q2 = Item::query()->where('id', '<', 5);
Item::query()
->fromRaw(
'(SELECT * FROM ('.$q1->toSql().' intersect '.$q2->toSql().') AS items) AS items',
array_merge($q1->getBindings(), $q2->getBindings())
)
->where(...)
->get();