【问题标题】:Laravel 5.6 Nested Querying RelationshipLaravel 5.6 嵌套查询关系
【发布时间】:2019-03-30 17:45:37
【问题描述】:

大家好,我需要查询一段深厚的关系......

我的store 模特

<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Store extends Model
{
    protected $table = 'stores';

    public function address(){

        return $this->morphOne('App\Model\Address', 'addressable');
    }

}

我的Address 模特

class Address extends Model
{
    protected $table = 'address';
    protected $fillable = [
        'province_id',
        'city_id',
        'brgy_id',
        'street_lot_blk',
        'longitude',
        'latitude'
    ];

    public function addressable(){

         return $this->morphTo();
    }

    public function province(){

        return $this->hasOne('App\Model\Province', 'id', 'province_id');
    }

    public function city(){

        return $this->hasOne('App\Model\City', 'id', 'city_id');
    }

     public function brgy(){

        return $this->hasOne('App\Model\Brgy', 'id', 'brgy_id');
    }
}

我的province 模特

<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Province extends Model
{

    protected $table = 'refprovince';
}

我的查询

$request = app()->make('request');

        return response()->json([
                'stores' => Store::where('name', 'LIKE', '%'. $request->name . '%')
                    ->with(['address.province', 'address.city', 'address.brgy'])
                    ->take(10)->get()
            ]);

result 见附图

问题是如果用户输入商店的名称,它只会返回商店的名称,如果用户输入“Camarines”,它只会返回在省内有“Camarines”字样的商店。

我的代码看起来像这样......但它不起作用。

 $results = Store::where('name', 'LIKE', '%'. $request->name . '%')
                    ->with(['address.province' => function($query) use ($request) {

                        $query->where('provDesc', 'LIKE', '%'. $request->name . '%');

                    }])
                    ->take(10)->get();

        return response()->json([
                'stores' => $results
            ]);

我不知道这是否可能,请告诉我,以便我可以重新构建我的数据库。 TY

更新:仍然无法使用这些代码。

$request = app()->make('request');

         $stores = Store::where('name', 'LIKE', "%{$request->name}%")
        ->orWhereHas('address.province', function ($query) use ($request) {
            $query->where('provDesc', 'LIKE', "%{$request->name}%");
        })
        ->with(['address.province', 'address.city', 'address.brgy'])
        ->get();

【问题讨论】:

  • 那么您想要名称匹配的商店或 provDesc 匹配的商店?
  • 是的...但它不起作用。这可能吗?

标签: laravel relationship


【解决方案1】:

两件事:

  1. 您需要有一个 OR 子句来搜索其中一个或另一个条件为真的记录(商店名称与搜索匹配或省 provDesc 与搜索匹配)。您可以使用orWhere()OR 子句添加到查询中。

https://laravel.com/docs/5.6/queries#where-clauses

  1. 商店是你这里的主要结果,省份是相关记录。 with() 方法不会过滤主要结果,它只会过滤与主要结果一起返回的相关模型。要通过对相关记录的查询过滤主要结果,请使用whereHas()(或orWhereHas()whereDoesntHave() 等)。

https://laravel.com/docs/5.6/eloquent-relationships#querying-relationship-existence

试试这样的:

$results = Store::whereHas('province', function($query) use ($request) {
    $query->where('provDesc', 'LIKE', '%'. $request->name . '%');
})->orWhere('name', 'LIKE', '%'. $request->name . '%');

【讨论】:

  • 它不起作用...我试过了。可能是因为多态关系或急切加载with()
【解决方案2】:

您的代码的问题在于with() 没有限制或向查询添加条件。它只告诉 Laravel 在第一个查询运行后稍后(在单独的查询中)加载哪些关系。您传递的回调是限制在辅助查询期间加载的模型,而不是在决定要检索哪些 Store 时。

目前是这样写的:

  • 加载名称类似于 %name% 的前(最多)10 个商店
    • 为返回的(最多)10 个 ID 中的每一个加载地址(对 ID 运行 whereIn() 查询)
      • 为每个地址加载省份,但前提是 provDesc 是 LIKE %name%(再次使用 whereIn() 查询地址 ID)

解决方案:添加 orWhereHas() 到商店的查询中:

Store::where('name', 'LIKE', "%$foo%")

    ->orWhereHas('address.province', function ($query) {
        $query->where('provDesc', 'LIKE', "%$foo%");
    });

但仍使用with() 来包含您要使用的关系:

$stores = Store::where('name', 'LIKE', "%{$request->name}%")
    ->orWhereHas('address.province', function ($query) use ($request) {
        $query->where('provDesc', 'LIKE', "%{$request->name}%");
    })
    ->with('address.province')
    ->take(10)
    ->get();

或者,如果您希望地址的省份关系仅在匹配时加载%name%:

$stores = Store::where('name', 'LIKE', "%{$request->name}%")
    ->orWhereHas('address.province', function ($query) use ($request) {
        $query->where('provDesc', 'LIKE', "%{$request->name}%");
    })
    ->with(['address.province' => function ($query) use ($request) {
        $query->where('provDesc', 'LIKE', "%{$request->name}%");
    }])
    ->take(10)
    ->get();

【讨论】:

  • @Rbex 店铺总是需要加载省与地址的关系,还是只是为了找到合适的店铺?
  • 不...应该是 orWhere 但我很好...我可以更改它。两者都应该使用orWhere...商店和省。 address.city 怎么样,我也将它添加到with 中?
  • 是的,如果你也想加载 address.city 也可以包含它:with('address.city', 'address.province')with(['address.city', 'address.province'])
  • 还是不行……可能是多态关系?
  • 您的请求参数称为search (?search=ceb),但您的代码使用的是name。尝试$request-&gt;search,并验证它不为空(如果您正在检查LIKE %%,它将返回所有匹配项 - 这可能是它现在正在做的事情。意思是, $request->name 可能是空的,导致一切都是返回。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
相关资源
最近更新 更多