php - 使用带有 N 查询的 "USING"子句 Eloquent 地加入

标签 php mysql sql eloquent slim

我正在使用 Slim Framework with Illuminate Database .

我想使用USING 子句进行JOIN 查询。假设给定 Sakila数据库。图:

ER Diagram

如何在 Eloquent 模型中使用 USING 子句(不是 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 

我想要的是使用 EXACT 1 查询进行预加载API 中描述的 Eloquent 关系的使用不符合我的期望,因为任何急切的关系都使用 N+1 查询。我想减少对数据库的 IO。

FilmActor 模型:

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");
        //});
    }
}

所以,在 Controller 中我可以得到像这样的数据

$data = FilmActor::allJoin()  
        ->limit(100)  
        ->get();`  

但是有一个缺点,如果我需要添加额外的行为(比如whereorder)。

$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 年已经可用)该功能未命名为 using 而是 with 并且应该给出类似的东西:

    ForumActor::with(['film', 'actor'])->get();

当然这必须适应你的情况,你甚至可以嵌套关系:

   ForumActor::with('actor.contacts')->get();

例如。

看看:https://laravel.com/docs/8.x/eloquent-relationships#eager-loading 即使它被标记为“急切加载”(顺便说一句,这很棒)它也可以在没有急切加载的情况下工作,而且,当正确设置外键时(例如通过迁移),它只使用一个查询,这样就可以避免 N+1问题.

关于php - 使用带有 N 查询的 "USING"子句 Eloquent 地加入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48348366/

相关文章:

php - 您将如何测试使用全局变量的 PHP 代码?

php - 使用 PHP 从日志文件中提取数据

php - 计数和总计

mysql - 维护 MYSQL 中输入的约束

SQL 选择不同

c# - 将 Null 值插入到 SQL 表中

php - 重力形成多步 anchor 偏移

mysql - 多少表开销太多了?

php - 正则表达式解析 imdb 页面并获取名称

mysql - 带有别名的复杂 SQL 查询