laravel DB::raw 無法自動獲取構造器表名的前綴

在使用laravel查詢構造器的時候,需要用到mysql的一些函數,需要使用到DB::raw() 方法來處理,在處理過程中遇到的問題記錄一下:

寫法

DB::table('users')->select('users.*', DB::raw('CONCAT(rel.name, "=", rel.realname)'))->leftJoin('real as rel', function($join){
    $join->on('rel.id', '=', 'users.id')
        ->where('rel.status', '=', 1)
})->first();

實際sql:

select `tr_users.*`, CONCAT(rel.name, '=', rel.realname) from `tr_users` left join
`tr_real` as `tr_rel` on `tr_rel.id` =   `tr_users.id` and `tr_rel.status` = 1 

報錯:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'rel.name' in 'field list' 

問題原因:

查詢構造器在加入前綴的時候不會給DB::raw()函數中的字段添加,在思否中看到同樣的問題,說可以通過DB::getTablePrefix()來獲取前綴,於是來了靈感,做了如下修改問題解決

DB::table('users')->select('users.*', DB::raw('CONCAT('.DB::getTablePrefix().'rel.name, "=", '.DB::getTablePrefix().'rel.realname)'))->leftJoin('real as rel', function($join){
    $join->on('rel.id', '=', 'users.id')
        ->where('rel.status', '=', 1)
})->first();

注:根據源碼,表的別名添加的前綴是去不掉的,除非修改源碼,下面是warp源碼

public function wrapTable($table)
{
    if ($this->isExpression($table)) {
        return $this->getValue($table);
    }

    return $this->wrap($this->tablePrefix.$table, true);
}
    public function wrap($value, $prefixAlias = false)
    {
        if ($this->isExpression($value)) {
            return $this->getValue($value);
        }

        // If the value being wrapped has a column alias we will need to separate out
        // the pieces so we can wrap each of the segments of the expression on it
        // own, and then joins them both back together with the "as" connector.
        if (strpos(strtolower($value), ' as ') !== false) {
            $segments = explode(' ', $value);

            if ($prefixAlias) {
                $segments[2] = $this->tablePrefix.$segments[2];
            }

            return $this->wrap($segments[0]).' as '.$this->wrapValue($segments[2]);
        }

        $wrapped = [];

        $segments = explode('.', $value);

        // If the value is not an aliased table expression, we'll just wrap it like
        // normal, so if there is more than one segment, we will wrap the first
        // segments as if it was a table and the rest as just regular values.
        foreach ($segments as $key => $segment) {
            if ($key == 0 && count($segments) > 1) {
                $wrapped[] = $this->wrapTable($segment);
            } else {
                $wrapped[] = $this->wrapValue($segment);
            }
        }

        return implode('.', $wrapped);
    }
if (strpos(strtolower($value), ' as ') !== false) {
            $segments = explode(' ', $value);

            if ($prefixAlias) {
                $segments[2] = $this->tablePrefix.$segments[2];
            }

            return $this->wrap($segments[0]).' as '.$this->wrapValue($segments[2]);
        }

參考 https://segmentfault.com/q/1010000011378407

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章