【问题标题】:Laravel, remove null Eloquent object attributes from JSONLaravel,从 JSON 中删除空的 Eloquent 对象属性
【发布时间】:2014-09-05 17:22:51
【问题描述】:

有没有一种优雅的方法可以从 Eloquent 对象中删除 NULL 值?我的对象嵌套在关系中。这个特定的调用可能有 1000 行长,所以我尝试这样做的主要原因是为用户节省带宽,但服务器性能也是一个考虑因素。

我的代码:

$data['locations'] = Location::with('address')->where('user_id', '1')->get();

return Response::json($data);

我尝试了 Mutators,但除非我弄错了,否则 Mutators 对对象键没有权力,只有值。

我也尝试过使用这样的array_filter,但失败了:

Any PHP function that will strip properties of an object that are null?

How to remove empty associative array entries

按要求编辑,

{
    "status": "ok",
    "locations": [
        {
            "id": "1",
            "latitude": "12.239107980271",
            "longitude": "109.19479025725",
            "user_time": "",
            "transport": "Bus",
            "title1": "",
            "title2": "",
            "address": {
                "town": "Nha Trang",
                "country": "Vietnam",
                "address": "36-44 Hùng Vương, Lộc Thọ, Nha Trang, Khanh Hoa Province, Vietnam"
            },
            "altitude": {
                "altitude": "10.006237983704"
            },
            "timezone": {
                "offset": "25200"
            },
            "forecast": {
                "icon": "",
                "high_temp": "",
                "low_temp": ""
            }
        },
        {
            "id": "2",

期望的响应:

{
    "status": "ok",
    "locations": [
        {
            "id": "1",
            "latitude": "12.239107980271",
            "longitude": "109.19479025725",
            "transport": "Bus",
            "address": {
                "town": "Nha Trang",
                "country": "Vietnam",
                "address": "36-44 Hùng Vương, Lộc Thọ, Nha Trang, Khanh Hoa Province, Vietnam"
            },
            "altitude": {
                "altitude": "10.006237983704"
            },
            "timezone": {
                "offset": "25200"
            }
        },
        {
            "id": "2",

如您所见,我可以简单地遍历整个批次并删除任何没有值的键(或键的键)。我希望 Laravel 可以提供一种简洁/快速的方式来做同样的事情。

我应该补充一点,从技术上讲,只有纬度和经度是必填字段!

【问题讨论】:

  • 发布一个例子,说明你得到了什么以及你想要的结果。

标签: laravel eloquent


【解决方案1】:

3 种可能性:

  1. 编写一个 响应宏 来清理您的 json 数据: http://laravel.com/docs/responses#response-macros
  2. 扩展Response并在那里实现您的清理例程。有关如何执行此操作的详细信息,请参阅这个很棒的教程:http://fideloper.com/extend-request-response-laravel
  3. 在您的模型中实现jsonSerialize 方法,当您的模型转换为 json 并将您的清理例程放在那里时,该方法将被自动调用。您甚至可以更进一步,为您的 Location 模型编写自己的 Collection。根据您的数据结构,这可以使事情变得更容易一些。可以在这里找到一个很好的教程:http://heera.it/extend-laravel-eloquent-collection-object

我个人更喜欢选项 3。)因为数据修改发生在它应该发生的地方 - 在您的模型中。

但归根结底,这实际上取决于哪种解决方案最适合您的项目。

【讨论】:

  • 谢谢,那些文章很有趣。这种对核心功能的覆盖/扩展让我觉得这是一个非常严重的解决方案,并且可能会影响升级路径。我稍后会报告。
  • 别害怕,laravel 就是为此而生的:laravel.com/docs/extendinglaravel.com/docs/ioc。我的建议都不是“肮脏的黑客”,一切都完全按照惯例。
  • 所有这些建议都可以使用。然而,与 opt 3 相反,还有另一种方式,因为模型不是这样做的地方(这不是数据修改,而是表示层)。使用 api 转换器并使其保持稳定。例如。 fractal.thephpleague.com/transformersgithub.com/dingo/api
【解决方案2】:

首先制作一个特征并添加您的自定义验证,然后在您需要的每个资源中使用

trait ResourceHelpers
{
    /**
     * Remove null values from Eloquent api resource
     * @param array $data
     * @return array
     */
    public function removeNullValues(array $data)
    {
        $filtered_data = [];
        foreach ($data as $key => $value) {
            // if resource is empty
            if ($value instanceof JsonResource and $value->resource === null) {
                continue;
            }
            $filtered_data[$key] = $this->when($value !== null, $value);
        }

        return $filtered_data;
    }
}

然后在你的资源中使用它

class UserResource extends JsonResource
{

    use ResourceHelpers;

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array
     */
    public function toArray($request)
    {
        return $this->removeNullValues([
            "id" => $this->id,
            "first_name" => $this->first_name,
            "last_name" => $this->last_name,
            "phone" => $this->phone,
            "email" => $this->email,
            "balance" => $this->balance,
            'address' => $this->address,
            'city' => $this->city,
            'state' => $this->state,
            'zip_code' => $this->zip_code,
            'country' => CountryResource::make($this->whenLoaded('country')),
            "joined_at" => $this->created_at,
            "updated_at" => $this->updated_at,
        ]);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-15
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 2015-03-10
    相关资源
    最近更新 更多