Whip Monstrous Code Into Shape 20-Consider Wrapping it Up

Imagine that you perform an API request to fetch a bit of JSON. That response will become an array of objects, once decoded. Too often, though, I see developers littering their views or creating helper functions, all to add a bit of behavior or formatting to how the data is rendered. There's no need for this. Instead, you might consider wrapping each item within a simple POPO, and then add your behavior and formatting to this class alone.


这是这个系列的最后一节,介绍的是包装一条记录。想象一下开发的时候有些是从外部 api 服务器获取的 JSON 数据,json_decode 之后就变成了一个 stdClass 对象数组。

[
    {
        "id": 4,
        "name": "Prof. Kyleigh Quitzon",
        "power": 77,
        "created_at": "2016-12-12 12:12:40",
        "updated_at": "2016-12-12 12:12:40"
    },
    {
        "id": 5,
        "name": "Dr. Agustin Frami",
        "power": 89,
        "created_at": "2016-12-12 12:12:40",
        "updated_at": "2016-12-12 12:12:40"
    },
    {
        "id": 6,
        "name": "Ms. Carmela Beahan MD",
        "power": 57,
        "created_at": "2016-12-12 12:12:40",
        "updated_at": "2016-12-12 12:12:40"
    },
    ...
]

返回的数据是数组,很多 collection 很好用的方法都没有办法用,另外数据也是标准的 stdClass,如果要格式化某个数据,不得不在视图中写各种逻辑或者编写自己的 helper 方法。

@foreach($heroes as $hero)
    英雄姓名: {{ $hero->name }},
    英雄能力:{{ $hero->power }},
    狂暴能力:{{ $hero->power * 1.3 }}
    创建时间: {{ humanTime($hero->created_at) }}
@endforeach

// humanTime 辅助方法

function humanTime($date){
    $carbon = \Carbon\Carbon::createFromFormat(\Carbon\Carbon::DEFAULT_TO_STRING_FORMAT, $date);

    return $carbon->diffForHumans();
}

这种情况下,可以考虑使用包装类,也就是创建一个类,负责管理一个个数据,并且可以添加自定义的方法。

class HeroWrap
{
    private $item;

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

    public function humanTime()
    {
        $carbon = Carbon::createFromFormat(Carbon::DEFAULT_TO_STRING_FORMAT, $this->item->created_at);

        return $carbon->diffForHumans();
    }

    public function wild()
    {
        return $this->item->power * 1.3;
    }

    public function __get($property)
    {
        if (isset($this->item->$property)){
            return $this->item->$property;
        }

        throw new \Exception("$property doesn't exist!");
    }
}

在从 api 服务器获取到数据后,就创建一个 collect,并调用 map 方法,把所有的数据都包装成 HeroWrap

$heroes = // get heroes from api service;

$heroes= collect($heroes)->map(function ($hero) {
    return new HeroWrap($hero);
});

这样在视图里面就可以很简单的使用了,一方面方便修改,比如要修改狂暴指数,只要改改HeroWrap里面的wild方法就行;另外一方面方便扩展。

@foreach($heroes as $hero)
    英雄姓名: {{ $hero->name }},
    英雄能力:{{ $hero->power }},
    狂暴能力:{{ $hero->wild() }}
    创建时间: {{ $hero->humanTime() }}
@endforeach

以上就是 Whip Monstrous Code Into Shape 这个系列的所有内容了,后面看到有意义的再写吧,写东西对我来说真的太难了,即使是有一个思路,要表达出来也是很困难...

本帖已被设为精华帖!
本帖由 overtrue 于 7年前 加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 2
nickfan
$heroes= collect($heroes)->map(function ($hero) {
    return new HeroWrap($hero);
});

精华所在,转换collection成员偷梁换柱。

7年前 评论
Lonexw

来学习 ~~

7年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!