【问题标题】:Eloquent model add extra column by defaultEloquent 模型默认添加额外的列
【发布时间】:2015-04-04 04:28:39
【问题描述】:

我有一个名为 Book 的模型,我想在默认 SQL 中添加一个额外的列。

目前默认的sql是这样的:

SELECT * FROM `books`

但我希望默认 SQL 看起来像这样:

SELECT *, "Hello" as `greeting` FROM `books`

这样我就可以做到以下几点:

// in a controller function...
$book = Book::find(1);
echo $book->greeting; // Hello

$books = Book::all();
foreach($books as $book){
    echo $book->greeting; // Hello
}

有什么方法可以实现吗?

非常感谢

【问题讨论】:

  • 你为什么不把它添加到类定义本身而不是假装它来自 SQL 动态?从本质上讲,您似乎会将属性隐藏在真正应该定义的地方。
  • 这是一个简化的例子。我想要做的实际上是为我的模型添加一个新的score 属性。 score 属性计算为另一个表中的投票总和。生成的 SQL 非常复杂,我不希望它影响问题,即如何向模型的默认查询添加额外的 SQL 列。
  • 为什么不为此目的将书籍模型与乐谱模型相关联?如果您在问题中实际解释了该用例,您也可能会得到与您的实际用例更相关的答案。
  • 一本书的分数计算为votes 表中vote_amount 列的总和(一本书可能有很多票)。我想要做的是能够最终做这样的事情:Book::orderBy('score', 'asc')->get()。我找不到通过关系来做到这一点的方法。
  • 你会在每个模型中定义 hasMany 和 hasOne 关系,然后你会做类似Book::find(1)->scores()->groupBy('book_id')->get(arrat('field1', 'field2', DB::RAW('SUM(score)'));

标签: php sql laravel eloquent


【解决方案1】:

尽管我想知道这背后的原因是什么,但您可以在模型中覆盖 newQuery

public function newQuery(){
    $query = parent::newQuery();
    return $query->selectRaw('*, "Hello" AS greeting');
}

另一种方法是使用scope:

public function scopeWithGreeting($query){
    return $query->selectRaw('*, "Hello" AS greeting');
}

用法:

$book = Book::withGreeting()->find(1);

如果您真的每次都想要范围,可以使用global scope,这样您就不必一直调用withGreeting

【讨论】:

  • scopeWith... 看起来可能是实现我想要做的事情的可行方法!谢谢。
  • 不客气。如果您需要更多信息,请告诉我...顺便说一句,您可以随意调用您的范围。只需在方法名称前面加上scope
  • 我希望你没有用“即使我想知道......”来断言。改变 SQL 语句比让 Laravel 做 Legwork 更好的理由有一百万零一个。不过,您的答案是我遇到的最佳解决方案。 newQuery() 似乎做到了这一切!
【解决方案2】:

我认为 ORM 不能很好地管理,所以你迟早会遇到麻烦,如果你不能修改你的书模型但仍然想完成它,我建议你创建一个新的指向用

构造的视图的模型
SELECT *, 'Hello' as `greeting` FROM `books`

【讨论】:

  • 这是一个想法。但是,这样做的问题是您不能使用相同的模型来更新视图(因为视图整体上不可更新)。这可能会使这个解决方案变得很麻烦。
【解决方案3】:

使用an accessor。如果模型没有设置问候语,则此返回 $book->greeting 的“Hello”:

public function getGreetingAttribute($value) {
  if(empty($value)) { return 'Hello'; } else { return $value; }
}

【讨论】:

  • 谢谢,但我特别希望这个额外的属性来自 SQL 查询。
  • @ThomasClayson 出于好奇,你为什么在乎?
【解决方案4】:

你可以使用$appends这里是例子

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
    ];

    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = ['greeting'];

    public function getGreetingAttribute()
    {
        return 'Hello';
    }
}

您不需要为此编写任何 SQL 了解更多 https://github.com/laravel/framework/blob/5.5/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L59-L64

【讨论】:

    猜你喜欢
    • 2015-09-11
    • 2018-10-21
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 2018-08-05
    • 2016-02-20
    相关资源
    最近更新 更多