我使用苗条框架与照明数据库。
我想使用clausa进行JOIN
查询。假设给定了Sakila数据库。图表:
如何在雄辩模型中使用子句(not ON)进行连接?
SELECT film_id,title,first_name,last_name
FROM film_actor
INNER join film USING(film_id) -- notice
INNER join actor USING(actor_id) -- notice
我想要的是一个精确的1查询急切加载。API中描述的雄辩关系的使用并没有达到我的期望,因为任何渴望的关系都使用N 1查询。我想减少对数据库的IO。
电影演员模型:
class FilmActor extends Model
{
protected $table = 'film_actor';
protected $primaryKey = ["actor_id", "film_id"];
protected $increamenting = false;
protected $appends = ['full_name'];
// i need to make it in Eloquent model way, so it easier to manipulate
public function getFullNameAttribute()
{
$fn = "";
$fn .= isset($this->first_name) ? $this->first_name ." ": "";
$fn .= isset($this->last_name) ? $this->last_name ." ": "";
return $fn;
}
public function allJoin()
{
// how to join with "USING" clause ?
return self::select(["film.film_id","title","first_name","last_name"])
->join("film", "film_actor.film_id", '=', 'film.film_id')
->join("actor", "film_actor.actor_id", '=', 'actor.actor_id');
//something like
//return self::select("*")->joinUsing("film",["film_id"]);
//or
//return self::select("*")->join("film",function($join){
// $join->using("film_id");
//});
}
}
因此,在控制器中,我可以得到如下数据
$data = FilmActor::allJoin()
->limit(100)
->get();`
但是有一个缺点,如果我需要添加额外的行为(比如在哪里
或顺序
)。
$data = FilmActor::allJoin()
->where("film.film_id","1")
->orderBy("film_actor.actor_id")
->limit(100)
->get();`
我需要传递表名称以避免模糊字段。不好。所以我想进一步使用,我可以做
$kat = $request->getParam("kat","first_name");
// ["film_id", "title", "first_name", "last_name"]
// from combobox html
// adding "film.film_id" to combo is not an option
// passing table name to html ?? big NO
$search = $request->getParam("search","");
$order = $request->getParam("order","");
$data = FilmActor::allJoin()
->where($kat,"like","%$search%")
->orderBy($order)
->limit(100)
->get();`
在Eloquent中(我认为该功能在2018年已经可用),该功能不是使用命名为,而是使用
命名为,应该给出如下内容:
ForumActor::with(['film', 'actor'])->get();
当然,这必须适应您的情况,您甚至可以嵌套关系:
ForumActor::with('actor.contacts')->get();
例如。
看看:https://laravel.com/docs/8.x/eloquent-relationships#eager-loading即使它被标记为“急切加载”(顺便说一句),它也可以在没有急切加载的情况下工作,此外,当外键被正确设置(例如迁移)时,它只使用一个查询,这样远离N 1问题
。
您可以尝试在代码中查找可能使使用JOIN
,或添加一些代理字典:
$kat_dict = ["film_id" => "film.film_id", "title"=> 'title', "first_name" => 'first_name', "last_name" => 'last_name'];
$kat = $kat_dict[$request->getParam("kat","first_name")];
顺便说一句:更好的方法是使用像Arr::get($Arr,$index,$default)这样的函数(参见代码示例)
您可以通过select
$query = "SELECT
film_id,title,first_name,last_name
FROM
film_actor
INNER join film USING(film_id)
INNER join actor USING(actor_id)
WHERE
film.film_id = :filmId
ORDER BY film_actor.actor_id
LIMIT 0, 100";
$data = DB::select($query, [
'filmId' => 1
]);
// or like this, if not using default connection
/**
$data = DB::connection('test')->select($query, [
'filmId' => 1
]);
*/