【问题标题】:Laravel return value of a specific column in a relationshipLaravel 返回关系中特定列的值
【发布时间】:2018-12-13 22:17:38
【问题描述】:

我对 Laravel 非常陌生。你可以帮我解决一个小问题: 我不能在集合中返回,只能返回模型中定义的关系中特定列的值。我会解释:

我有 2 张桌子:

1 - 托莫斯

2 - 文档

迁移:

1- 托莫斯

    private $table = 'tomos';

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create($this->table, function (Blueprint $table) {
            $table->increments('id');
            $table->string('name')->nullable(false);
            $table->text('description')->nullable(true);
            $table->boolean('active')->default(true);
            $table->timestamps();
        });
    }

2- 文件

private $table = 'documents';

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create($this->table, function (Blueprint $table) {
            $table->increments('id');
            $table->date('date')->nullable(false);
            $table->integer('provider_id');
            $table->integer('tomo_id');
            $table->string('folio')->nullable(false);
            $table->integer('user_id');
            $table->text('description');
            $table->timestamps();

            $table->foreign('provider_id')
                ->references('id')->on('providers');

            $table->foreign('tomo_id')
                ->references('id')->on('tomos');

            $table->foreign('user_id')
                ->references('id')->on('users');
        });
    }

关系

1- 托莫

public function document()
{
    return $this->hasMany(Document::class);
}

2- 文档

public function tomo()
{
    return $this->belongsTo(Tomo::class);
}

控制器

class Documents extends Controller
{
    public function read(Request $request)
    {
        $provider = $request->only('id');

        $documents = Document::select(['id', 'date', 'tomo_id', 'description'])
            ->with([
                'tomo' => function ($query) {
                    $query->select('id', 'name');
                }
            ])->orderBy('date', 'ASC')
            ->paginate(25);

        return $documents;
    }
}

我收到以下 JSON 响应:

current_page    1
    data    […]
        0   {…}
            id  2
            date    2018-12-01
            tomo_id 1
            description 1
            tomo    {…}
                id  1
                name    Tomo 1

但是......我不希望键('tomo')返回一个对象,我希望它以字符串的形式返回列('name')的值。示例:

current_page    1
    data    […]
        0   {…}
            id  2
            date    2018-12-01
            tomo_id 1
            description 1
            tomo Tomo 1

非常感谢您..

【问题讨论】:

  • 最快的方法是使用join而不是relation,我会想办法解决这个问题。
  • 哦,你可以使用自定义属性,我现在写一个答案

标签: laravel relationship


【解决方案1】:

首先您需要添加protected $appends = array('tomo_name'); 作为属性,因为这是模型表中不存在的属性。

 public function getTomoNameAttribute()
{
    return $this->tomo()->name;  
}

在此之后,您可以像这样访问 tomo 名称->tomo_name

我不能 100% 确定此代码仅适用于复制粘贴,但您可能会明白并进一步处理它。

哦,请注意,加载属性时,每次都会在数据库中查询该“tomo”。

【讨论】:

    【解决方案2】:

    非常感谢:PeterMunteanu Petrisor

    特别是:Munteanu Petrisor

    我已经能够使用您向我提出的解决方案解决我的问题,之前我使用 'join' 实现了它:

    class Documents extends Controller
    {
        public function read(Request $request)
        {
            $provider = $request->only('id');
    
            $documents = Document::join('tomos', 'documents.tomo_id', '=', 'tomos.id')
                ->join('users', 'documents.user_id', '=', 'users.id')
                ->where(['provider_id' => $provider])
                ->paginate(25, array(
                    'documents.id',
                    'documents.date',
                    'documents.folio',
                    'documents.description',
                    'tomos.name as tomo',
                ));
    
            return $documents;
        }
    }
    

    现在在您的帮助下,使用属性可以创造奇迹:

    文档模型

    protected $appends = [
        'tomo_name',
        'user_fullname'
    ];
    
    public function getTomoNameAttribute()
    {
        return $this->tomo()->first()->name;
    }
    
    public function getUserFullNameAttribute()
    {
        return $this->user()->first()->first_name . ' ' . $this->user()->first()->last_name;
    }
    

    文档控制器

    class Documents extends Controller
    {
        public function read(Request $request)
        {
            $provider = $request->only('id');
    
            $documents = Document::select(['id', 'date', 'tomo_id', 'user_id', 'folio', 'description'])
                ->where(['provider_id' => $provider])
                ->orderBy('date', 'ASC')
                ->paginate(25);
    
            return $documents;
        }
    }
    

    现在它以我预期的方式返回数据

    data    […]
        0   {…}
            id  2
            date    2018-12-01
            tomo_id 1
            user_id 1
            folio   1
            description 1
            tomo_name   1
            user_fullname   First Last
    

    非常感谢!

    【讨论】:

      【解决方案3】:

      在您的控制器中,尝试:

      $documents->getCollection()->transform(function ($item) {
          $item->tomo = $item->tomo->name;
          return $item;
      });
      return $documents;
      

      【讨论】:

      • 我认为这很糟糕,因为他必须获取所有文档并循环它们以更改属性。
      • 也许,但他只获得了 25 条记录。集合的存在是有原因的,它是一个有效的用例。您提出的属性解决方案也很好,但正如您所说,它也有缺点。
      • 您的解决方案具有完全相同的缺点,哦,在这两种情况下您都可以之前加载关系,这样您可能会减少查询的数量。另一件事,那个 paginate(25) 可以是任何数字,通常是 10,15,25, 50 和 100 。 100 相当大,因为对象本身的大小以及您想用它们做什么
      • 您的解决方案是有效的,它有效,但我认为它只适用于数量较少的集合,例如“设置”或静态且不太可能变大的东西跨度>
      猜你喜欢
      • 1970-01-01
      • 2021-07-11
      • 2016-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      相关资源
      最近更新 更多