最佳实践-Laravel控制器雄辩合并

最佳实践-Laravel控制器雄辩合并,laravel,eloquent,controller,Laravel,Eloquent,Controller,我的供应商模型上有一个作用域,它返回的结果为active=true 这在创建新条目时非常有效,因为我只希望用户看到活跃的供应商 当前条目可能有一个不活跃的供应商;编辑时,我希望看到所有活动供应商,加上当前供应商(如果是非活动供应商) 我的控制器中有以下代码: $suppliers=Supplier::active()->get(); 如果(!$suppliers->contains('id',$record->supplier->id)) { $suppliers->add(供应商::查找($r

我的供应商模型上有一个作用域,它返回的结果为
active=true

这在创建新条目时非常有效,因为我只希望用户看到活跃的供应商

当前条目可能有一个不活跃的供应商;编辑时,我希望看到所有活动供应商,加上当前供应商(如果是非活动供应商)

我的控制器中有以下代码:

$suppliers=Supplier::active()->get();
如果(!$suppliers->contains('id',$record->supplier->id))
{
$suppliers->add(供应商::查找($record->Supplier->id));
}
两个问题:这是正确的方法吗?这个代码应该在我的控制器中还是应该在其他地方?(可能是一个范围,但我不知道如何编写代码)


编辑:

谢谢你们的帮助。我应用了每个答案中的建议,并将代码重构到一个新的范围:

public函数范围包括($query,Model$Model=null)
{
$query->where('active',1);
如果($model&&!$model->supplier->active)
{
$query->orWhere('id',$model->supplier->id);
}
}

您所编写的内容将起作用,但是如果集合很大,则
Collection::contains
函数可能会非常慢

由于您有id,我可能会进行以下更改:

$suppliers = Supplier::active()->get();
$supplier = Supplier::find($record->supplier->id);
if (!$supplier->active) {
  $suppliers->add($supplier);
}
当然,这样做的缺点是,可能会对数据库进行不必要的查询

因此,你必须考虑:

  • 记录的供应商更可能是活跃的还是不活跃的
  • 活动供应商集合的大小是否足够大,足以证明对数据库的另一次调用(可能被浪费)是合理的
根据您对应用程序数据的了解,做出最有意义的选择


至于第二个问题,如果您在应用程序的这一部分中只需要这组特定的供应商,那么控制器是编写此代码的好地方

但是,如果您在应用程序的其他部分需要这组特定的供应商,您可能应该将此代码移到其他地方。在这种情况下,在相关模型(无论
$record
是什么类型)上创建一个返回该模型的供应商集的函数可能是有意义的。比如:

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

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

  return $suppliers;
}

我看到了@Vince对第一个问题的回答,我同意他的看法。 关于第二个问题:

在供应商模型中写入范围,如下所示:

为了获得良好的实践,您需要在“App\services\SupplierService.php”等服务中编写逻辑部分。然后写下你想要的函数:

在SupplierController的构造函数中,插入该服务的实例并使用该函数,例如:

正如您所看到的,稍后您将不需要更改控制器中的任何内容。例如,如果您需要更改供应商选择查询,您只需更改服务中的某些内容即可。这种方式将使代码块分离并缩短。 这种模式的另一个意义是:您不需要从控制器访问模型。所有与模型相关的逻辑都将在服务中实现。
对于其他项目,您只能获取服务或控制器,并以不同的方式实现另一部分。但在这种情况下,如果控制器中有所有代码,这将阻止您获取必要代码的部分,因为您可能不记得每个块都在做什么…

您可以在查询中添加一个
where
子句来查找该id

$suppliers=Supplier::active()->或where('id',$record->Supplier->id)->get();
您可以通过将“id”作为参数传递,潜在地将其滑入
活动的
范围

public函数scopeActive($query,$id=null)
{
$query->where('active',true);
如果($id){
$query->orWhere('id',$id);
}
}
供应商::活动($record->Supplier->id)->get();

或者制作另一个这样做的示波器。

这是一个很好的答案,谢谢。你对我问题的第二部分有什么想法吗?啊,我错过了第二部分。我会更新我的答案。
public function scopeActive($query){
    $query->where('active', 1); // for boolean type
}
public function activeSuppliersWithCurrent($record) {
    $suppliers = Supplier::active()->get();
    $supplier = Supplier::find($record->supplier->id);
    if (!$supplier->active) {
        $suppliers->add($supplier);
    }
}
use App\Servives\SupplierService;

protected $supplierService = null;

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

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