当前位置: 首页 > 知识库问答 >
问题:

如何在Laravel中选择具有关系的自定义属性字段?

荆学民
2023-03-14

我有如下表格电子邮件电子邮件附件

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');
});

我的型号分类如下:EmailEmailAttachment

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);
    }
}

这样做返回电子邮件::('附件')-

{
    "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"
        }
    ]
}

返回Email::with('attachments:file\u name')-

{
    "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'))-

    SQLSTATE[42S22]:找不到列: 1054字段列表中未知的列'url'(SQL:从'email_attachments'中选择'url',其中'email_attachments'.'email_id'在(0)中)"

    return Email::with('attachments'))-

    “SQLSTATE[42S22]:未找到列:“字段列表”中的1054未知列‘url’(SQL:选择‘电子邮件’、‘主题’、‘正文’、‘电子邮件’中的‘url’)”

    return Email::with('attachments:url'))-

    “SQLSTATE[42S22]:未找到列:“字段列表”中的1054未知列‘url’(SQL:选择‘电子邮件’、‘主题’、‘正文’、‘电子邮件’中的‘url’)”

    附言:我使用Laravel 8.29.0。


  • 共有2个答案

    段恩
    2023-03-14

    在“即时加载”中加载特定字段时,还应选择用于映射相关记录的记录的标识符。因此,在您的案例中,电子邮件(有许多)附件,通过外键电子邮件id指向电子邮件

    请参见加载特定列

    使用此功能时,应始终在希望检索的列列表中包含id列和任何相关外键列。

    Email::with('attachments:email_id,file_name')->get();
    

    现在,这将为您提供附件关系中的两个字段

    "attachments": [
        {
            "email_id": 1,
            "file_name": "foo.jpg"
        }
    ]
    

    因此,如果你需要url属性,这是一个自定义属性,而不是物理上存在于你的表中,你需要欺骗查询生成器来产生这样的SQL查询,其中包含url属性,最初为空值稍后,当此查询输出通过laravel数据转换转换时,您的url的访问器getUrlAt0016()将用您期望的输出填充此属性

    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"
        }
    ]
    
    牟星火
    2023-03-14

    有几种方法可以实现这一点,通常在其他框架中,这些对象通常称为“DTO对象”(数据传输对象)

    对于Laravel,您可以简单地从数据库中获取结果查询,并使用集合()API对其执行简单的数组转换。

    例如:

    $collection = Email::with('attachments')->get();
    $collection->map(function ($record) {
      return ['email' => $record->email, 'subject' => $record->subject, 'attachments' => $record->attachments ];
    });
    

    现在,您只需将此返回为响应:

    $response = $collection->map(...);
    return response()->json($response, 200);
    

    从你的控制器。

    虽然您应该知道这些转换发生在PHP中,而不是SQL端,但是用户不知道您从数据库返回了哪个字段。https://laravel.com/docs/8.x/queries#select-声明

    您可以添加-

    所以你可以这样做:

    Email::with('attachments')->select('my_field','my_field2')->get();
    

    请记住,这适用于任何查询生成器方法。https://laravel.com/docs/8.x/queries

    最后,您可以查看API资源,因为它们提供了一种格式化响应的方法。文档将用比我更好的工作来解释它:https://laravel.com/docs/8.x/eloquent-resources

     类似资料:
    • 我正在尝试使用Javascript选择此复选框 下面的代码可以工作,但并不理想 我试过这些 但它们并不起作用。有什么想法能让这件事成功吗? 数据值未硬编码的更新代码

    • 问题内容: 请考虑以下代码: 如何选择具有属性的所有标签? 谢谢 问题答案: 使用“具有属性”选择器: 或选择一个该属性具有特定值的属性: “属性值起始于”,“属性值包含”等还有其他选择器。

    • 我有一个数据库结构,其中我有一个用户和公司之间的多对多关系表。为此,我有一个交叉引用表company_user。此外,每个用户在公司中都有一定的角色,因此交叉引用表也有role_id。问题是,由于某种原因,当我试图从交叉引用表中检索角色时,我会出现异常。 以下是我如何定义公司模型中的关系: 现在,如果我只是尝试从pivot获取角色id,一切都会正常工作: 但是我还需要角色的数据,所以我在自定义透视

    • 我使用JAXB根据一些XSD模式生成java类。对于以下元素: <代码> jaxb生成以下代码: 问题是我们需要使用一些依赖于getter/setter方法命名约定的专有XML工具,例如,对于字段REC_LOC他们希望使用名为getRecLoc(String value)和setRecLoc()的方法,而不是getRECLOC()。 有没有办法自定义jaxb生成的方法名?

    • 问题内容: 在XML文档中,我具有共享相同名称的元素,但是属性的值定义了它是什么类型的数据,并且我想从文档中选择所有具有特定值的元素。我是否需要使用XPath(如果可以,您是否可以建议正确的语法)还是有更优雅的解决方案? 这是一些示例XML: 我想选择类型为的所有子代标签的内容。 PS-我正在尝试使用PHP与Netflix API进行接口-这对我的问题无关紧要,但是如果您想提出一种更好的方法,我非

    • 本文向大家介绍jquery 属性选择器(匹配具有指定属性的元素),包括了jquery 属性选择器(匹配具有指定属性的元素)的使用技巧和注意事项,需要的朋友参考一下 jQuery 选择器 在前面的章节中,我们展示了一些有关如何选取 HTML 元素的实例。 关键点是学习 jQuery 选择器是如何准确地选取您希望应用效果的元素。 jQuery 元素选择器和属性选择器允许您通过标签名、属性名或内容对 H