【问题标题】:Laravel DB : first() method brings the Response content must be a stringLaravel DB:first() 方法带来的响应内容必须是字符串
【发布时间】:2018-01-03 19:20:32
【问题描述】:

我使用 Laravel Illuminate,当我使用 first() 方法获取单个结果时出现此错误:

The Response content must be a string or object implementing __toString(), "object" given.

return DB::table('todos')->where("title","your List")->first();

如果我使用 get() 方法进行选择,它会起作用:

return DB::table('todos')->where("title","your List")->get();

你知道第一句话有什么问题吗?

【问题讨论】:

    标签: php laravel eloquent


    【解决方案1】:

    当您执行->get() 时,您会返回一个Illuminate\Support\Collection 对象。该对象可以由响应返回,因为它实现了__toString() 方法:

    /**
     * Convert the collection to its string representation.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toJson();
    }
    
    /**
     * Get the collection of items as JSON.
     *
     * @param  int  $options
     * @return string
     */
    public function toJson($options = 0)
    {
        return json_encode($this->jsonSerialize(), $options);
    }
    
    /**
     * Convert the object into something JSON serializable.
     *
     * @return array
     */
    public function jsonSerialize()
    {
        return array_map(function ($value) {
            if ($value instanceof JsonSerializable) {
                return $value->jsonSerialize();
            } elseif ($value instanceof Jsonable) {
                return json_decode($value->toJson(), true);
            } elseif ($value instanceof Arrayable) {
                return $value->toArray();
            } else {
                return $value;
            }
        }, $this->items);
    }
    

    如您所见,它所做的就是将整个集合转换为 json。

    但是当您执行->first() 时,幕后发生的事情是 Laravel 执行了->take(1)->get()->first(),因此查询被限制在一行,然后检索包含该行结果的集合,最后您取回一个对象。

    所以 ->first() 调用是在幕后对集合进行的,这意味着您不会得到另一个集合,而是一个数据库对象 - 可能是 Illuminate\Database\Query\Builder 类型,我不太记得了。

    由于该类没有实现__toString() 方法,因此响应不知道如何处理它。相反,您会得到一个错误。

    您可以通过在对象上运行 json_encode() 或返回 json 响应来轻松模拟相同的响应。

    【讨论】:

    • 当使用DB选择单行时,你会得到一个stdClass的对象,它没有实现__toString()
    • 您也可以只使用 JSON 响应。 return response()->json(compact('todo'));
    【解决方案2】:

    @JoelHinz 已经尽可能详细地说明了。但是对这种行为感到好奇,我在 Laravel 文档中发现了一些有趣的东西,位于 Query builder's where clause

    使用DB Facade 并调用get() 返回一个(StdClass)对象的集合。由于它位于 Laravel 的集合中,因此有一些方法可以将其基础属性转换为 String。但是,当您直接从查询构建器访问集合中的某个项目时,您将拥有一个 pure StdClass 对象,该对象未实现 __toString()(非常确定)。

    我认为同样的情况是,如果你有一个集合,并且你检索一个底层数组说$collection[0],你将失去 Laravel 集合的_toString() 的实现,因为你已经解开它并且现在有纯 PHP 数组.

    这种行为正是查询构建器的开发方式。为了让你的查询结果得到很好的处理,你可以return json_encode($query_result)return response()->json($query_result),或者使用Eloquent(如果你已经创建了模型),即return Todo::where("title","your List")->first()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-24
      • 2012-08-20
      • 2019-03-17
      • 2014-11-19
      • 1970-01-01
      • 2018-06-04
      • 2013-07-21
      相关资源
      最近更新 更多