【问题标题】:Laravel: How to Append Properties to an ArrayLaravel:如何将属性附加到数组
【发布时间】:2015-11-30 07:35:20
【问题描述】:

我有一个从我的show 方法返回的数组。这是show方法:

public function show($id)
{
    $track = Fuelconsumption::where('id', $id)->first();

    return $track;
}

返回这个:

{
    id: 6,
    distance: 178.6,
    volume: 14.31,
    price: 1.45,
    date: "2015-11-08 14:13:56",
    created_at: "2015-11-30 03:29:57",
    updated_at: "2015-11-30 03:29:57"
}

我想根据提供的值进行一些计算(平均值等),并将这些变量附加到上面的 json 数组中。

现在我正在通过在新的KpiController 中创建一个new Kpi 对象来解决这个问题。控制器将上面的array(它是一个燃料消耗对象)传递给我的constructor

这是我KpiControllershow方法:

public function show($id)
{
    $item = Fuelconsumption::where('id', $id)->first();

    $kpi = new Kpi($item);

    return $kpi['list'];
}

Constructor 我的Kpi 班级:

protected $avgFuel;
protected $avgCost;
protected $cost;
protected $list;

/**
 * Creates all necessary KPIs
 * 
 * @param Object $item Fuelconsumption
 */
public function __construct(Fuelconsumption $item)
{
    $this->avgFuel = $this->avgFuelperUnitofDistance($item);
    $this->avgCost = $this->avgCostPerUnitOfDistance($item);
    $this->cost = $this->cost($item);

    $this->list = [
        'avgFuelperUnitOfDistance' => $this->avgFuel, 
        'avgCostperUnitOfDistance' => $this->avgCost,
        'cost' => $this->cost
    ];
}

它会返回一个如下所示的 Json 数组:

{
     avgFuelperUnitOfDistance: 0.08,
     avgCostperUnitOfDistance: 0.116,
     cost: 20.75
}

我现在遇到的问题是,当我访问以下 URI 时,第一个数组被返回:

http://localhost:8000/fuelconsumption/6

当我访问这个 URI 时,第二个数组被返回:

http://localhost:8000/fuelconsumption/6/kpi

问题是我希望将两个 Json 数组合并到一个数组中,但我不知道如何实现。


这是我的想法:

修改油耗等级

将我的 FuelConsumptionController 修改为:

public function show($id)
{
    $item = Fuelconsumption::where('id', $id)->first();

    $kpi = new Fuelconsumption($item);

    dd($kpi);
}

并且在我的Fuelconsumption 类中有一个构造函数:

class Fuelconsumption extends Model
{
    protected $fillable = ['distance', 'volume', 'price', 'date'];

    protected $dates = ['date'];

    protected $cost;

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

    public function cost($item) {
        return round($item->volume * $item->price, 2);
    }
}

不幸的是,这会引发错误:

App\Fuelconsumption::__construct() 缺少参数 1

在我的理解中,因为该类甚至在我第二次在我的控制器中回忆它之前就被调用了。不知道如何解决。

第二个想法:展开 KPI 对象

包含我想要的所有其他变量,然后以某种方式在我的 FuelConsumptionController@show 方法中返回完整的数组。

第三个想法:以某种方式组合这些数组

不确定如何。


现在我相信最简单的解决方案是扩展 KPI 模型(我的第二个想法),但我希望通过以某种方式将 item 传递给我的 FuelConsumption 构造函数来完全摆脱 KPI 类。

【问题讨论】:

  • 检查这个 - laravel.com/docs/5.1/…
  • 谢谢,我为您的建议写了一个解决方案。与 Yorm de Langen 提供的其他解决方案相比,我将不胜感激任何建议

标签: php arrays json laravel


【解决方案1】:

你几乎是对的.. 因为你的类 FuelConsumption 是一个 Eloquent 模型,__construct 已经被 Laravel 设置并且你试图覆盖它。

Eloquent 所做的是在使用 ->first()->find($id) 返回单个模型的情况下(就像您拥有的一样)。当使用 ->all()->get() 时,它返回一个 Eloquent 集合。

建议的方法:

class Fuelconsumption extends Model
{
    protected $fillable = ['distance', 'volume', 'price', 'date'];

    protected $dates = ['date'];

    protected $cost;

    public function cost() {
        return round($this->volume * $this->price, 2);
    }

    public function avgFuelperUnitofDistance() {
        return $this->distance / $volume; // do your thing, dummy calc
    }

    public function avgCostPerUnitOfDistance() {
        return $this->distance / $price;  // do your thing, dummy calc
    }
}

您的 api 控制器方法可能如下所示:

public function show($id)
{
    $item = Fuelconsumption::find($id)->first();
    // if $item == null if it is item was not found
    if (!$item) {
        return response('item was missing', 404);
    }

    // $item will look like:
    // class Fuelconsumption: {
    //    id: 6,
    //    distance: 178.6,
    //    volume: 14.31,
    //    price: 1.45,
    //    date: "2015-11-08 14:13:56",
    //    created_at: "2015-11-30 03:29:57",
    //    updated_at: "2015-11-30 03:29:57"
    // }

    // doing more stuff over here

    // create the json response
    return response()->json([
        'id' => $item->id,
        'distance' => $item->distance,
        'volume' => $item->volume,
        'price' => $item->price,
        'date' => $item->date,
        'cost' => $item->cost(),
        'avg_fuel' => $item->avgFuelperUnitofDistance(),
        'avg_unit' => $item->avgCostperUnitofDistance(),
    ]);
}

或者如果你真的想创建和合并属性:

public function show($id)
{
    $item = Fuelconsumption::find($id)->first();

    .....

    $extra = [
        'cost' => $item->cost(),
        'avg_fuel' => $item->avgFuelperUnitofDistance(),
        'avg_unit' => $item->avgCostperUnitofDistance(),
    ];

    return array_merge($item->getAttributes(), $extra);
}

【讨论】:

  • 感谢您的解决方案。您能否也看看我写的感谢用户 naneri 的解决方案,因为我试图弄清楚 laravel。
【解决方案2】:

解决此问题的另一种方法是用户 naneri 通过此链接提出的建议:

http://laravel.com/docs/5.1/eloquent-serialization#appending-values-to-json

那么我的模型应该是这样的:

class Fuelconsumption extends Model
{
    protected $fillable = ['distance', 'volume', 'price', 'date'];

    protected $dates = ['date'];

    protected $appends = ['cost', 'avg_fuel_per_unit_of_distance', 'avg_cost_per_unit_of_distance'];

    public function getCostAttribute()
    {
        return round($this->attributes['volume'] * $this->attributes['price'], 2);
    }

    public function getAvgFuelPerUnitOfDistanceAttribute()
    {
        return round($this->attributes['volume'] / $this->attributes['distance'], 3 );
    }

    public function getAvgCostPerUnitOfDistanceAttribute()
    {
        return round($this->attributes['volume'] * $this->attributes['price'] / $this->attributes['distance'], 3);
    }

}

当获取 URI http://localhost:8000/fuelconsumption/6 时,我的 show 方法的输出将如下所示

{
    id: 6,
    distance: 178.6,
    volume: 14.31,
    price: 1.45,
    date: "2015-11-08 14:13:56",
    created_at: "2015-11-30 03:29:57",
    updated_at: "2015-11-30 03:29:57",
    cost: 20.75,
    avg_fuel_per_unit_of_distance: 0.08,
    avg_cost_per_unit_of_distance: 0.116
}

【讨论】:

  • 唯一的建议是将名称 date 更改为其他名称...它是什么样的日期(可能类似于:registered_at)? date 是保留字
  • 缩短代码:$this->attributes['...']$this->... 示例:public function getCostAttribute() { return round($this->volume * $this->price, 2); } public function getAvgFuelPerUnitOfDistanceAttribute() { return round($this->volume / $this->distance, 3 ); } public function getAvgCostPerUnitOfDistanceAttribute() { return round($this->volume * $this->price / $this->distance, 3); }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-12
  • 2016-07-31
  • 2023-01-12
  • 1970-01-01
  • 2021-06-14
  • 2010-10-03
  • 1970-01-01
相关资源
最近更新 更多