在Laravel查询生成器中,我想在Eloquent中实现诸如Scope之类的东西。 参考:Laravel Queries: Adding custom feature like Soft Deletes。
我有一些复杂的查询(带有联接,没有联接),但我希望能够轻松地应用如下的WHERE条件:
原始
:Select * from t1 join t2 ... join t3 ... etc
Where t1.c1 = x OR t3.c4 like "%like"
想要
:Select * from t1 join t2 ... join t3 ... etc
Where (t1.c1 = x OR t3.c4 like "%like") AND (t1.isTest = false AND t3.isTest = false)
我写了以下方法:
public static function scopeNoTest($query, $tables=[false])
{
if (!is_array($tables)) $tables = [$tables];
foreach ($tables as $table)
{
$field = ($table) ? $table . '.isTest' : 'isTest';
$query = $query->where(function ($q) use ($query, $field)
{
$q->where($field, false)
->orWhereNull($field);
}
);
}
return $query;
}
它像这样运行:
$select = <parameter driven select statement>
$where[$role] = <array of different where condition based on passed in parameter?
$bindings = <query bindings based on passed in parameters>
$query = DB::table('Transactions AS trans')
->leftJoin('Buyers AS b', 'trans.ID', '=', 'b.Transactions_ID')
->leftJoin('Sellers AS s', 'trans.ID', '=', 's.Transactions_ID')
->leftJoin('Agents AS ba', 'trans.BuyersAgent_ID', '=', 'ba.ID')
->leftJoin('Agents AS sa', 'trans.SellersAgent_ID', '=', 'sa.ID')
->leftJoin('TransactionCoordinators AS btc', 'trans.BuyersTransactionCoordinators_ID', '=', 'btc.ID')
->leftJoin('TransactionCoordinators AS stc', 'trans.SellersTransactionCoordinators_ID', '=', 'stc.ID')
->leftJoin('lu_UserRoles AS lu_ur', 'trans.ClientRole', '=', 'lu_ur.Value')
->leftJoin('Properties AS p', 'trans.Properties_ID', '=', 'p.ID')
->selectRaw($select);
// ... Adds code to Only Select records with isTest NOT True
$query = Model_Parent::scopeNoTest($query, ['trans', 'ba', 'sa', ]);
$query->whereRaw($where[$role].$whereUser, $bindings)->distinct();
$transactions = $query->get();
此代码的问题在于,它不会将原始[传入的]查询放在括号中-因此查询为 错误! 。
代码创建的位置是:
where
(`trans`.`isTest` = 0 or `trans`.`isTest` is null)
and (`ba`.`isTest` = 0 or `ba`.`isTest` is null)
and (`sa`.`isTest` = 0 or `sa`.`isTest` is null)
and trans.BuyersTransactionCoordinators_ID = 1 OR trans.SellersTransactionCoordinators_ID = 1
OR trans.CreatedByUsers_ID = 1 OR trans.OwnedByUsers_ID = 1
我想要
where
(`trans`.`isTest` = 0 or `trans`.`isTest` is null)
and (`ba`.`isTest` = 0 or `ba`.`isTest` is null)
and (`sa`.`isTest` = 0 or `sa`.`isTest` is null)
and (trans.BuyersTransactionCoordinators_ID = 1 OR trans.SellersTransactionCoordinators_ID = 1
OR trans.CreatedByUsers_ID = 1 OR trans.OwnedByUsers_ID = 1)
有没有办法做到这一点?
答案 0 :(得分:1)
看起来是以下行引起的:
$query->whereRaw($where[$role].$whereUser, $bindings)->distinct();
我认为有两种解决方法:
// 1
->whereRaw('(' . $where[$role].$whereUser . ')', $bindings)->
// 2
->where(function ($query) use (...) {
$query->whereRaw(...);
})->