Лучшая практика - Laravel Controller Eloquent слияния - PullRequest
2 голосов
/ 02 октября 2019

У меня есть область действия для моей модели поставщика, которая возвращает результаты, где active = true.

Это прекрасно работает при создании новых записей, так как я хочу, чтобы пользователь видел только активных поставщиков.

У текущих записей может быть неактивный поставщик;Когда я редактирую его, я хочу видеть всех активных поставщиков, а также текущего поставщика (если он неактивен)

У меня есть этот код в моем контроллере:

        $suppliers = Supplier::active()->get();
        if (!$suppliers->contains('id', $record->supplier->id))
        {
            $suppliers->add(Supplier::find($record->supplier->id));
        }

Два вопроса:это правильный способ сделать это? Этот код должен быть в моем контроллере или он должен быть где-то еще? (возможно область, но я не знаю, как это кодировать).


Редактировать:

Спасибо за помощь, ребята. Я применил совет по каждому из ответов и преобразовал свой код в новую область:

    public function scopeActiveIncluding($query, Model $model = null)
    {
        $query->where('active', 1);
        if ($model && !$model->supplier->active)
        {
            $query->orWhere('id', $model->supplier->id);
         }
    }

Ответы [ 3 ]

1 голос
/ 02 октября 2019

Я видел ответ @ Винса на первый вопрос, и я согласен с ним. О втором вопросе:

Напишите область действия в модели Поставщика следующим образом:

public function scopeActive($query){
    $query->where('active', 1); // for boolean type
}

Для хорошей практики вам необходимо написать логические части в сервисах, таких как «App \Услуги \ SupplierService.php». И там напишите нужную функцию:

public function activeSuppliersWithCurrent($record) {
    $suppliers = Supplier::active()->get();
    $supplier = Supplier::find($record->supplier->id);
    if (!$supplier->active) {
        $suppliers->add($supplier);
    }
}

В конструкторе вашего SupplierController введите экземпляр этой службы и используйте функцию, например:

use App\Servives\SupplierService;

protected $supplierService = null;

public function __construct(SupplierService $supplierService) {
    $this->supplierService = $supplierService;
}

public function getActiveSuppliersWithCurrent(...) {
   $result = $this->supplierService->activeSuppliersWithCurrent($record);
}

Как видите, позже вам не нужно ничего менять в контроллере. Если вам нужно изменить, например, запрос выбора поставщиков, вам просто нужно что-то изменить только в сервисе. Таким образом, ваши блоки кода будут отделены и короче. Также смысл этого паттерна: вам не нужен доступ к моделям из контроллера. Вся логика, связанная с моделями, будет реализована в сервисах. Для других проектов вы можете получить только сервисы или только контроллеры и реализовать другую часть иначе. Но в этом случае, если у вас есть все коды в контроллере, это помешает вам захватить части необходимых кодов, потому что, возможно, вы не помните, что делают каждый блок ...

1 голос
/ 02 октября 2019

Вы можете добавить предложение where к запросу, чтобы также найти этот идентификатор.

$suppliers = Supplier::active()->orWhere('id', $record->supplier->id)->get();

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

public function scopeActive($query, $id = null)
{
    $query->where('active', true);

    if ($id) {
        $query->orWhere('id', $id);
    }
}

Supplier::active($record->supplier->id)->get();

Или создайте другую область, которая делает это.

1 голос
/ 02 октября 2019

То, что вы написали, будет работать, но функция Collection::contains может быть довольно медленной, если коллекция большая.

Поскольку у вас есть идентификатор, я, вероятно, внесу следующее изменение:

$suppliers = Supplier::active()->get();
$supplier = Supplier::find($record->supplier->id);
if (!$supplier->active) {
  $suppliers->add($supplier);
}

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

Итак, вы должны учитывать:

  • является ли поставщик record более активным или неактивным?
  • - это размер коллекцииактивных поставщиков, достаточно крупных, чтобы оправдать очередной (потенциально потерянный) вызов в базу данных?

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


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

Если, однако, вы будетеВам нужен этот конкретный набор поставщиков в других частях вашего приложения, вам, вероятно, следует переместить этот код в другое место. В этом случае может иметь смысл создать функцию в связанной модели (независимо от типа $record ...), которая возвращает набор поставщиков этой модели. Что-то вроде:

public function getSuppliers()
{
  $suppliers = Supplier::active()->get();
  $supplier = $this->supplier;

  if (!$supplier->active) {
    $suppliers->add($supplier);
  }

  return $suppliers;
}
...