返回Laravel过滤器只返回模型的特定字段,而不是整个模型

hjzp0vay  于 2023-06-25  发布在  其他
关注(0)|答案(3)|浏览(188)

**我的尝试:**我想从一个有多个条目的模型中构建一个集合。该模型有一个关系(组),我不想输出一个组('Lorem Ipsum')。由于关系组有许多表列,而我只有id和name,所以我Map我的结果,并使用only()输出这两列。

我试着给一个函数添加一个条件。我想知道是否有一个Laravel函数filter()的函数,你只能得到特定的字段。例如$someModel->only(['id', 'name'])
目前我在filter()之后用map()解决它

$filtered = MainModel::with('relationA')->get()->map(fn (MainModel $mainModel $mainModel) => [
            'id' => $mainModel->getRouteKey(),
            'name' => $mainModel->name,
            'relationAFiltered' => $mainModel->relationA->filter(fn (SomeModel $someModel) => 
    $someModel->name !== 'Lorem Ipsum')->map(fn($g) => $g->only(['id', 'name'])),
xu3bshqb

xu3bshqb1#

我认为你所寻找的是只包括关系的某些列,但不包括任何东西,除非它有一个特定的名称?
要从相关模型中选择包含哪些列并应用条件,可以使用with()方法和闭包。

MainModel::with([
    "relationA" => fn ($q) => $q->select("id", "name")->where("name", "Lorem Ipsum")
])
    ->get();
txu3uszq

txu3uszq2#

为什么要将模型转换为数组?是为了回应吗?如果是响应,那么你应该使用资源,在这种情况下,你可以分离你的代码。例如:

namespace App\Http\Resources;

class MainModelResource extends JsonResource {
    public function toArray($request): array {
        return [
            'id' => $this->resource->id,
            'name' => $this->resource->name,
            'relationA' => $this->whenLoaded(
                'relationA',
                fn() => RelationAResource::collection(
                    $this->resource->relationA->filter(
                        fn(RelationA $relationA) => $relationA->name !== 'Lorem Ipsum'
                    )
                ),
            ),
        ];
    }
}

class RelationAResource extends JsonResource {
    public function toArray($request): array {
        return [
            'id' => $this->resource->id,
            'name' => $this->resource->name,
        ];
    }
}

为什么资源比普通数组更好:

  • 您将转换移动到另一个类(分隔代码)
  • 您可以在不同的地方使用资源(没有重复)
  • 这是一个相当灵活的解决方案(资源本身)

如果你不想在代码中多次使用map + filter,那么你可以把这个逻辑放到一个独立的方法中:

namespace App\Collections;

class RelationACollection extends Illuminate\Database\Eloquent\Collection {
    public function onlyIdAndNameWithoutLorem(): array {
        return $this
            ->filter(
                fn (RelationA $relationA) => $relationA->name !== 'Lorem Ipsum'
            )
            ->map(
                fn (RelationA $relationA) => $relationA->only('id', 'name')
            );
    }
}

将您的系列与模特联系起来

namespace App\Models;

class RelationA extends Model 
{
    public function newCollection(array $models = []): RelationACollection   
    {
        return new RelationACollection($models);
    }
}

用途:

$filtered = MainModel::with('relationA')
    ->get()
    ->map(
        fn (MainModel $mainModel) => [
            'id' => $mainModel->getRouteKey(),
            'name' => $mainModel->name,
            'relationAFiltered' => $mainModel->relationA->onlyIdAndNameWithoutLorem()
        ]
    );

您自己的收藏有优点和缺点:

  • (+)你可以把一些逻辑移到它们上面
  • (+)你可以在任何地方像使用类型一样使用你的集合
  • (-)需要为每个模型重新定义Model::newCollection

我希望我正确地理解了这个问题

0md85ypi

0md85ypi3#

Laravel的filter()方法中没有内置函数来指定要返回的特定字段。相反,您可以使用map()函数自定义输出并只选择必需的字段。举个例子

$filtered = MainModel::with('relationA')->get()->map(function (MainModel $mainModel) {
    return [
        'id' => $mainModel->getRouteKey(),
        'name' => $mainModel->name,
        'relationAFiltered' => $mainModel->relationA->filter(function (SomeModel $someModel) {
            return $someModel->name !== 'Lorem Ipsum';
        })->map(function ($g) {
            return $g->only(['id', 'name']);
        }),
    ];
});

相关问题