addSelect()Builder方法如何在Laravel中工作

ggd*_*ras 6 php eager-loading laravel laravel-5

说我有这些模型:

用户模型

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'User';

    protected $fillable =
    [
       'username', 'favoriteColor'
    ];          

    public function flights()
    {
        return $this->hasMany('App\Flight');
    }
}
Run Code Online (Sandbox Code Playgroud)

飞行模型

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'Flight';

    protected $fillable =
    [
       'flightName', 
    ];              
}   
Run Code Online (Sandbox Code Playgroud)

每当我这样做时,我都会尝试用急切的加载做一些事情:

$usersWithFlights = User::with(['flights'])->get();
Run Code Online (Sandbox Code Playgroud)

我得到这样的数据:(如果没问题,那就是我的期望)

{
    "userID": 1,
    "favoriteColor": green
    "flights": 
    [
       {
           "flightID": 2240,
           "flightName" : "To Beijing fellas"
       },
       {
           "flightID": 4432,
           "flightName" : "To Russia fellas"
       },       
    ]
}
Run Code Online (Sandbox Code Playgroud)

但后来我想用这样的选择原始添加一个列:(不要考虑1 as number它是多么愚蠢,它只是为了这个例子.

$usersWithFlights = User::with(['flights'])->addSelect(DB::raw('1 as number'))->get();
Run Code Online (Sandbox Code Playgroud)

我得到这样的数据:

[
    {
        "userID": 1,
        "favoriteColor": green
        "flights": []
    }
]
Run Code Online (Sandbox Code Playgroud)

是否为这种行为制作了addSelect()方法?如果没有其他工作来实现这一目标?

注意

我知道我可以添加select方法,Flights.*, Users.*但我想知道addSelect方法是否以这种方式工作

小智 19

如果你需要select中的默认值并添加一些额外的值,你可以使用这种结构:

$ usersWithFlights = User :: with(['flights'])- > select() - > addSelect(DB :: raw('1 as number')) - > get();


The*_*pha 7

先来看看addSelect方法:

public function addSelect($column)
{
    $column = is_array($column) ? $column : func_get_args();
    $this->columns = array_merge((array) $this->columns, $column);
    return $this;
}
Run Code Online (Sandbox Code Playgroud)

这只是通过与现有的选定列合并来添加列。所以,当你使用这样的东西时:

$usersWithFlights = User::with(['flights'])->addSelect(DB::raw('1 as number'))->get();
Run Code Online (Sandbox Code Playgroud)

查询变为select 1 as number from flights并且由于您的关系取决于父查询中的列值,因此如果没有任何实际列值,则不会检索到相关记录。要检查查询,您可以尝试以下操作:

\DB::enableQueryLog();
$usersWithFlights = User::with(['flights'])->addSelect(DB::raw('1 as number'))->get();
dd(\DB::getQueryLog());
Run Code Online (Sandbox Code Playgroud)

此外,如果您在添加选择中使用真实的列名,并且例如,如果您没有选择相关列,那么如果您使用,addSelect('someString')那么您将不会获得任何相关记录,因为您还必须选择使关系,在这种情况下,你可以尝试这样的事情:

$usersWithFlights = User::with(['flights'])->addSelect(['id', 'someString']))->get();
Run Code Online (Sandbox Code Playgroud)

测试:

这是DB::getQueryLog()我使用类似但在我的表中使用不同表的测试结果DB

Post->with('comments')->addSelect(DB::raw('1 as number'))->get();
dd(DB::getQueryLog());
Run Code Online (Sandbox Code Playgroud)

结果:

0 => array:3 [?
  "query" => "select 1 as number from "posts""
  "bindings" => []
  "time" => 9.0
  ]
1 => array:3 [?
  "query" => "select * from "comments" where "comments"."post_id" in (?)"
  "bindings" => array:1 [?
    0 => null
  ]
  "time" => 1.0
]
Run Code Online (Sandbox Code Playgroud)

更新:

addSelect当您手头有一个带有一些选定字段的查询对象并且稍后您想在选择列表中添加更多字段时,该方法很有用,因此示例可能如下所示:

$userWithFlights = User::with('flights')->select(['id', 'someColumn']);
// Some code ... 
if(SomeCondition) {
    // So, now the query will be something like this:
    // ->select(['id', 'someColumn', 'anotherField'])
    $userWithFlights->addSelect('anotherField');
}

$result =  $userWithFlights->get();
Run Code Online (Sandbox Code Playgroud)

如果要指定要选择的某些字段,则可以select($fieldsArray)改用。你也可以尝试这样的事情:

$userWithFlights = User::with('flights')->get(['id', 'someColumn']);
Run Code Online (Sandbox Code Playgroud)

你也可以尝试这样的事情:

$userWithFlights = User::with(['flights' => function($query) {
    $query->select('user_id', 'flight_title');
}])->get(['id', 'someColumn']);
Run Code Online (Sandbox Code Playgroud)