从 blade 视图中的第二个 table 关系中提取数据的正确方法是什么
What is the correct way to extract data from second table relationship in blade view
在我的 route.php 中,我定义了组路由资源:
Route::group(['middleware' => 'role:admin|staff|retailer|customer|spy'],
function()
{
Route::resource('profiles', 'ProfileController');
});
我的 User.php 模型包含这种关系
public function address ()
{
return $this->hasOne('App\Address', 'user_id');
}
我的 Address.php 模型包含这种关系
public function user ()
{
return $this->belongsTo('App\User');
}
在我的 ProfileController.php 中,我有一个名为 edit() 的 REST 方法,它发送 $user 变量以查看 blade
public function edit($id)
{
$user = Auth::user();
return view('profiles.edit')->with('user',$user);
}
事情是这样的:这是我的 /view/profiles/edit.blade.php。只是 2 个编辑字段的示例:
{!! Form::model($user, [
'method' => 'PATCH',
'route' => ['profiles.update', $user->id]
]) !!}
<div class="form-group">
{!! Form::label('lblfirst_name', 'First Name:', ['class' => 'control-label']) !!}
{!! Form::text('first_name', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('lbladdress_line1', 'Address line 1:', ['class' => 'control-label']) !!}
{!! Form::text('address_line1', $user->address->address_line1, ['class' => 'form-control']) !!}
</div>
{!! Form::close() !!}
注意
$user->address->address_line1
目前这就是我从地址 table 中提取数据的方式,使用这种方式,我发现此表单执行了 1 个额外的 sql 查询:
select * from addresses where addresses.user_id = '1' and addresses.user_id is not null limit 1
我的问题是,有更好的方法吗?我的意思是不做额外的查询,比如我如何提取上面的名字字段。
当您调用 Auth::user() 时,它会:
vendor/laravel/src/Illuminate/Auth/EloquentUserProvider.php:
/**
* Retrieve a user by their unique identifier.
*
* @param mixed $identifier
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveById($identifier)
{
return $this->createModel()->newQuery()->find($identifier);
}
它获取用户模型并执行 ->find($id),因此即使您更改 find() 函数的行为,您也必须发送第二个请求来检索相关数据。 Eloquent 就是这样。
你唯一能做的就是缓存第二个查询:
$user = Auth::user();
$address = Cache::remember('users::'.$user->id.'::address', 10, function() use ($user) {
return Address::where('user_id', $user->id)->first();
});
return view('profiles.edit', compact('user', 'address'));
在我的 route.php 中,我定义了组路由资源:
Route::group(['middleware' => 'role:admin|staff|retailer|customer|spy'],
function()
{
Route::resource('profiles', 'ProfileController');
});
我的 User.php 模型包含这种关系
public function address ()
{
return $this->hasOne('App\Address', 'user_id');
}
我的 Address.php 模型包含这种关系
public function user ()
{
return $this->belongsTo('App\User');
}
在我的 ProfileController.php 中,我有一个名为 edit() 的 REST 方法,它发送 $user 变量以查看 blade
public function edit($id)
{
$user = Auth::user();
return view('profiles.edit')->with('user',$user);
}
事情是这样的:这是我的 /view/profiles/edit.blade.php。只是 2 个编辑字段的示例:
{!! Form::model($user, [
'method' => 'PATCH',
'route' => ['profiles.update', $user->id]
]) !!}
<div class="form-group">
{!! Form::label('lblfirst_name', 'First Name:', ['class' => 'control-label']) !!}
{!! Form::text('first_name', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('lbladdress_line1', 'Address line 1:', ['class' => 'control-label']) !!}
{!! Form::text('address_line1', $user->address->address_line1, ['class' => 'form-control']) !!}
</div>
{!! Form::close() !!}
注意
$user->address->address_line1
目前这就是我从地址 table 中提取数据的方式,使用这种方式,我发现此表单执行了 1 个额外的 sql 查询:
select * from addresses where addresses.user_id = '1' and addresses.user_id is not null limit 1
我的问题是,有更好的方法吗?我的意思是不做额外的查询,比如我如何提取上面的名字字段。
当您调用 Auth::user() 时,它会:
vendor/laravel/src/Illuminate/Auth/EloquentUserProvider.php:
/**
* Retrieve a user by their unique identifier.
*
* @param mixed $identifier
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveById($identifier)
{
return $this->createModel()->newQuery()->find($identifier);
}
它获取用户模型并执行 ->find($id),因此即使您更改 find() 函数的行为,您也必须发送第二个请求来检索相关数据。 Eloquent 就是这样。
你唯一能做的就是缓存第二个查询:
$user = Auth::user();
$address = Cache::remember('users::'.$user->id.'::address', 10, function() use ($user) {
return Address::where('user_id', $user->id)->first();
});
return view('profiles.edit', compact('user', 'address'));