Laravel фильтрует отношение один ко многим

Я пытаюсь отфильтровать запрос по модели с отношением один ко многим, но это не работает. Правильный вывод должен удалить все запасы с истекшим сроком годности, но он возвращает все доступные запасы.

Товар: hasMany(Stock::class)
Запас: принадлежит(Продукт::класс)

код:

$keyword = $request->keyword;
$data = Product::with('stocks')
            ->where([
                ['pharmacy_id', '=', auth()->user()->pharmacy->id],
            ])
            ->where(function($productModel) use($keyword) {
                $productModel->where('name', 'LIKE', "%$keyword%")->orWhere('sku', 'LIKE', "%$keyword%");
            })
            ->whereHas('stocks', function($stockModel) {
                $stockModel->where('expiry', '>', Carbon::now()->format('Y-m-d'));
            })->get();

Текущий выход:

[
  {
    "id": 1,
    "sku": "xpzidfa1454995",
    "name": "Jaqueline Will",
    "category": "medicine",
    "type": "manufactured",
    "selling_price": "1.00",
    "pharmacy_id": 1,
    "created_at": "2020-12-22T11:40:32.000000Z",
    "updated_at": "2020-12-22T11:40:32.000000Z",
    "stocks": [
      {
        "id": 3,
        "product_id": 1,
        "expiry": "2025-10-10",
        "amount": 40,
        "supplier_id": 1,
        "pharmacy_id": 1,
        "created_at": "2020-12-22T11:45:39.000000Z",
        "updated_at": "2020-12-22T11:45:39.000000Z"
      },
      {
        "id": 5,
        "product_id": 1,
        "expiry": "2020-10-10",
        "amount": 40,
        "supplier_id": 1,
        "pharmacy_id": 1,
        "created_at": "2020-12-22T11:45:39.000000Z",
        "updated_at": "2020-12-22T11:45:39.000000Z"
      }
    ]
  }
]

Правильный вывод:

[
  {
    "id": 1,
    "sku": "xpzidfa1454995",
    "name": "Jaqueline Will",
    "category": "medicine",
    "type": "manufactured",
    "selling_price": "1.00",
    "pharmacy_id": 1,
    "created_at": "2020-12-22T11:40:32.000000Z",
    "updated_at": "2020-12-22T11:40:32.000000Z",
    "stocks": [
      {
        "id": 3,
        "product_id": 1,
        "expiry": "2025-10-10",
        "amount": 40,
        "supplier_id": 1,
        "pharmacy_id": 1,
        "created_at": "2020-12-22T11:45:39.000000Z",
        "updated_at": "2020-12-22T11:45:39.000000Z"
      }
    ]
  }
]

Модель запаса:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Stock extends Model
{
    use HasFactory;

    protected $fillable = [
        'product_id',
        'expiry',
        'amount',
        'supplier_id',
        'pharmacy_id',
    ];

    public function pharmacy() {
        return $this->belongsTo(Pharmacy::class);
    }

    public function product() {
        return $this->belongsTo(Product::class);
    }
}

Я не думаю, что вам нужно форматировать объект Carbon в Laravel. Просто используйте Carbon::now()

Daan 22.12.2020 15:45

@Даан, о, ладно, не знал, спасибо! Однако это не решает мою проблему.

sula7ifa 22.12.2020 15:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
2
570
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, вы должны сопоставить дату, используя whereDate.

Попробуй это,

$keyword = $request->keyword;
$data = Product::with('stocks')
            ->where([
                ['pharmacy_id', '=', auth()->user()->pharmacy->id],
            ])
            ->where(function($productModel) use($keyword) {
                $productModel->where('name', 'LIKE', "%$keyword%")->orWhere('sku', 'LIKE', "%$keyword%");
            })
            ->whereHas('stocks', function($stockModel) {
                $stockModel->whereDate('expiry', '>', Carbon::now()->format('Y-m-d'));
            })->get();

Проверьте эту ссылку, чтобы узнать больше

Дополнительные предложения Laravel Where

Я пробовал это, но это все тот же вывод

sula7ifa 22.12.2020 15:48

Тогда просто используйте now(). Вместо даты форматирования.

Maulik Shah 22.12.2020 15:49

Все тот же выход. Я предполагаю, что цепочка предложений where неверна, но я не могу найти правильный способ сделать это.

sula7ifa 22.12.2020 15:52
Ответ принят как подходящий

Чтобы удалить записи о запасах, срок действия которых истек, необходимо наложить ограничение на нетерпеливую загрузку.

$keyword = $request->keyword;
$data = Product::with(['stocks' => fn($query) => $query->whereDate('expiry', '>', now())])
    ->where([
        ['pharmacy_id', '=', auth()->user()->pharmacy->id],
    ])
    ->where(function($productModel) use($keyword) {
        $productModel->where('name', 'LIKE', "%$keyword%")->orWhere('sku', 'LIKE', "%$keyword%");
    })
    ->get();

Это сработало! Вы знаете, хорошо это для производительности или нет?

sula7ifa 22.12.2020 15:57

При нетерпеливой загрузке проблема запроса N+1 избегается. Так что нетерпеливая загрузка на самом деле хороша для производительности. В зависимости от контекста вашего приложения и количества записей для модели продукта вы можете использовать разбиение на страницы вместо выборки всех записей.

Donkarnash 22.12.2020 15:59

Другие вопросы по теме