Laravel 5.6 Вложенные отношения запроса - PullRequest
0 голосов
/ 26 октября 2018

Привет, ребята, мне нужно запросить глубокие отношения ...

Моя 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 см. Прилагаемое фото

enter image description here

Проблема в том, что если пользователь введет имя магазина, он вернет только имя магазина, а если пользователь введет «Камарины», он вернет магазин, у которого в провинции есть слово «Камарины».

Мой код выглядит следующим образом ... но он не работает.

 $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();

enter image description here

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Проблема с вашим кодом заключается в том, что with() не ограничивает и не добавляет условий в запрос.Он только сообщает Laravel, какие отношения загружать позже (в отдельном запросе) после запуска первого запроса.Вызов, который вы передаете, ограничивает модели, загруженные во время вторичного запроса, но не решает, какие хранилища извлечь.

В настоящее время он выглядит так:

  • Загрузка первого (до) 10 магазинов, в которых имя похоже на% name%
    • Загрузка адреса для каждого из (до) 10 возвращенных идентификаторов (выполнение запроса whereIn () по идентификаторам)
      • Загрузка провинциидля каждого из этих адресов, но только если provDesc было LIKE% name% (снова с запросом whereIn () по идентификаторам адресов)

Решение: добавьте 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();
0 голосов
/ 26 октября 2018

2 вещи:

  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 . '%');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...