laravel - 如何在 Laravel 中选择具有关系的自定义属性字段?
问题描述
我有表格emails
,email_attachments
如下所示:
Schema::create('emails', function (Blueprint $table) {
$table->id();
$table->string('email')->nullable(false);
$table->string('subject')->nullable(false);
$table->text('body')->nullable(false);
$table->timestamps();
});
Schema::create('email_attachments', function (Blueprint $table) {
$table->id();
$table->foreignId('email_id')->nullable(false);
$table->string('file_name')->nullable(false);
$table->string('file_path')->nullable(false);
$table->foreign('email_id')->references('id')->on('emails');
});
我的模型类Email
如下EmailAttachment
:
class Email extends Model
{
use HasFactory;
protected $fillable = ['email', 'subject', 'body'];
function attachments()
{
return $this->hasMany(EmailAttachment::class);
}
}
class EmailAttachment extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['email_id', 'file_name', 'file_path'];
protected $appends = ['url'];
function email()
{
return $this->belongsTo(Email::class);
}
public function getUrlAttribute()
{
return Storage::disk('public')->url($this->file_name);
}
}
这样做return Email::with('attachments')->get();
我得到了所有的回应:
{
"id": 1,
"email": "me@me.com",
"subject": "My Subject",
"body": "<html><body><h1>My test message.</h1></body></html>",
"created_at": "2021-02-26T23:32:08.000000Z",
"updated_at": "2021-02-26T23:32:08.000000Z",
"attachments": [
{
"id": 1,
"email_id": 1,
"file_name": "foo.jpg",
"file_path": "/home/user/laravel/storage/app/foo.jpg",
"url": "http://127.0.0.1:8000/storage/foo.jpg"
}
]
}
我return Email::with('attachments:file_name')->get();
得到attachments
一个空数组:
{
"id": 1,
"email": "me@me.com",
"subject": "My Subject",
"body": "<html><body><h1>My test message.</h1></body></html>",
"created_at": "2021-02-26T23:32:08.000000Z",
"updated_at": "2021-02-26T23:32:08.000000Z",
"attachments": []
}
我怎样才能得到这个?
{
"email": "me@me.com",
"subject": "My Subject",
"body": "<html><body><h1>My test message.</h1></body></html>",
"attachments": [
{
"url": "http://127.0.0.1:8000/storage/foo.jpg"
}
]
}
我已经尝试过:
return Email::with('attachments:url')->get(['email', 'subject', 'body']);
SQLSTATE [42S22]:找不到列:1054“字段列表”中的未知列“url”(SQL:从“email_attachments”中选择“url”,其中“email_attachments”。“email_id”在(0)中)”
return Email::with('attachments')->get(['email', 'subject', 'body', 'url']);
“SQLSTATE [42S22]:未找到列:1054 '字段列表'中的未知列 'url'(SQL:从“电子邮件”中选择“电子邮件”、“主题”、“正文”、“url”)”
return Email::with('attachments:url')->get(['email', 'subject', 'body', 'url']);
“SQLSTATE [42S22]:未找到列:1054 '字段列表'中的未知列 'url'(SQL:从“电子邮件”中选择“电子邮件”、“主题”、“正文”、“url”)”
PS.:我正在使用Laravel 8.29.0。
解决方案
在预先加载中加载特定字段时,您还应该选择用于映射相关记录的记录标识符。因此,在您的情况下,通过指向的(hasMany)
外键发送电子邮件附件email_id
Email
使用此功能时,您应该始终在要检索的列列表中包含 id 列和任何相关的外键列。
Email::with('attachments:email_id,file_name')->get();
现在这将为您提供附件关系中的 2 个字段
"attachments": [
{
"email_id": 1,
"file_name": "foo.jpg"
}
]
因此,如果您需要url
属性是自定义属性并且实际不存在于您的表中,您将需要欺骗查询构建器以生成包含url
属性的此类 SQL 查询,最初为空值,然后当此查询输出由 laravel 数据转换时转换您url
的访问器getUrlAttribute()
将使用您的预期输出填充此属性
Email::with(['attachments' => function ($query) {
$query->select(['email_id', 'file_name', \DB::raw('null as url')]);
}])->get();
现在附件集合中将包含以下数据
"attachments": [
{
email_id": 1,
"file_name": "foo.jpg",
"url": "http://127.0.0.1:8000/storage/foo.jpg"
}
]
推荐阅读
- oracle - Oracle 19c 安装错误:[INS-08802] 无法实例化视图 ID 'QuickInstallUI' 引用的视图类
- python - Python 如何使用 HTTP 身份验证从 Luno.com 查询 API
- java - 使用共享表发送带有预览的链接
- c# - 如何实现一种算法来搜索 Lucene Index for Equities?
- python - 导入和分析多个 CSV 文件
- python - Pandas DataFrame groupby,同时转换和计数
- azure-devops - ##[错误]必需:'ConnectedServiceNameARM' 输入 --- Azure DevOps
- mongodb - MongoDB 数据在哪里?
- html - 如何在导航栏中的下拉菜单中删除透明度,使其仅使用 CSS 不显示其后面的页面文本
- c++ - 无法弄清楚双变量