如何解决从预先加载的 Laravel 集合中加载特定列
考虑书籍和作者的关系。每本书属于一位作者和一位作者有许多本书。 Books 表有像(Id、Title、Version 等)这样的字段,而authors 有像(Id、Name、Address 等)这样的字段。注意 DB 列不遵循默认的 Laravel 命名约定。
现在;我想从两个表中获取一些字段。更具体的是,我想要标题、版本、姓名和地址字段。 这是所需的输出:
{
Title: "Oxford Maths",Version: "2.5",author: "John Doe",}
第一次试用:
return Book::with('author')->get()->map(function ($book) {
return collect($book)->only(
[
'Title','Version',"author"
]);
});
第一次试验输出:
{
Title: "Oxford Maths",author: {
Id: 1,Name: "John Doe",Address: "Tanzania",deleted_at: null
}
}
第二次试用:试过了;
return Book::with([
'author' => function($query){
$query->select('Name','Id');
}
])->get()->map(function ($data) {
return collect($data)->only(
[
'Title',"author"
]);
});
还有这个;
return Book::with('authority:name,Id')->get()->map(function ($data) {
return collect($data)->only(
[
'Title',"author"
]);
});
第二次试验输出:
{
Title: "Oxford Maths",author: {
Name: "John Doe",Id: 1
}
}
第三次审判:
return Book::with([
'author' => function($query){
$query->select('Name'); // *Removed foreignKey*
}
])->get()->map(function ($data) {
return collect($data)->only(
[
'Title',"author"
]);
});
第三次试验输出:
{
Title: "Oxford Maths",author: null
}
我该怎么做才能获得所需的输出?
解决方法
当然,您可以事后在集合上执行此操作,但直接在查询上执行此操作更有意义。您尝试在第三次试验中反映这一点。但是,在我看来,这是 Laravel behaves a bit odd。为了进行急切加载,您需要外键。尽管这是合乎逻辑的,但人们还是会忘记这一点。但是如果您忘记包含外键,Laravel 不会告诉您这一点,而是返回 null
。因此,请确保所有必要的主键和外键始终包含在您的关系中。
return Book::with([
'author' => function($query){
$query->select('id','Name'); // *Removed foreignKey*
}
])->get([ 'title','version' ]);
有一件事,当一个关系应该主要只返回它的一个值时,我喜欢做:
class Author extends Model
{
public function __toString()
{
return $this->Name;
}
}
要以这种方式自动序列化,您可以将 __toString()
更改为 jsonSerialize()
class Author extends Model implements JsonSerializable
{
public function jsonSerialize()
{
return $this->Name;
}
}
,
也许对你有帮助
在模型中
protected $appends = [
'author_name','address'
];
protected $fillable = [
'title','version',];
public function author(){
return $this->belongsTo(Author::class);
}
public function getAuthorNameAttribute(){
return $this->author->name;
}
public function getAddressAttribute(){
return $this->author->address;
}
在控制器中使用这个
return Book::query()->with('author')->first()->makeHidden(['author','author_id']);
输出:
{
"id": 1,"title": "book","version": "v1","created_at": null,"updated_at": null,"author_name": "komeyl","address": "Iran"
}
,
我最终使用了@komeyl-dev 建议的技巧。这是示例代码:
//Book.php
class Book extends Model
{
protected $appends = ['author_name']; // appended so I can access it as json
public function author(){
return $this->belongsTo(Author::class,'author_id');
}
public function getAuthorNameAttribute(){
return $this->author->name;
}
}
//Testing in web.php (Note: No eager loading here)
Route::get('url',function () {
return Book::get()->map(function ($data) {
return collect($data)->only(
[
'Title','Version',"author_name"
]);
});
});
谢谢@shaedrich 和@komeyl-dev
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。