Laravel 5.1 从原始数据库(或只是一个数组)创建集合或关联数组

Posted

技术标签:

【中文标题】Laravel 5.1 从原始数据库(或只是一个数组)创建集合或关联数组【英文标题】:Laravel 5.1 create collection or associative array from raw DB (or just an array) 【发布时间】:2015-12-23 21:59:28 【问题描述】:

鉴于以下表结构,我想返回一个 Eloquent 集合,或者至少将原始 DB 结果转换为关联数组以便于迭代。

建筑物

+----+---------------+
| id | building_name |
+----+---------------+
|  1 | Building 1    |
|  2 | Building 2    |
+----+---------------+

房间

+----+-----------+-------------+
| id | room_name | building_id |
+----+-----------+-------------+
|  1 | Room 1    |           1 |
|  2 | Room 2    |           1 |
|  3 | Room 3    |           2 |
+----+-----------+-------------+

维护日志

+----+-------------------+---------+---------------------+
| id | maintenance_value | room_id |      created_at     |
+----+-------------------+---------+---------------------+
|  1 | Cleaned           |       1 | 2015-09-10 00:54:59 |
|  2 | Cleaned           |       1 | 2015-09-13 01:55:59 |
|  3 | Cleaned           |       2 | 2015-09-09 02:56:59 |
|  4 | Cleaned           |       2 | 2015-09-14 03:57:59 |
|  5 | Cleaned           |       3 | 2015-09-08 04:58:59 |
|  6 | Cleaned           |       3 | 2015-09-15 05:59:59 |
+----+-------------------+---------+---------------------+

现在使用以下原始数据库查询..

$results = DB::select('
  select b.building_name,r.room_name,x.maxdate FROM buildings b
  join rooms r on r.building_id = b.id
  join (select room_id,max(created_at) as maxdate from maintenancelog group by room_id) x on x.room_id=room.id
  having x.maxdate < DATE_SUB(NOW(), INTERVAL 10 DAY)');

返回

Array
(
    [0] => stdClass Object
        (
            [building_name] => Building 1
            [room_name] => Room 1
            [maxdate] => 2015-09-13 01:55:59
        )

    [1] => stdClass Object
        (
            [building_name] => Building 1
            [room_name] => Room 2
            [maxdate] => 2015-09-14 03:57:59 
        )

    [2] => stdClass Object
        (
            [building_name] => Building 2
            [room_name] => Room 3
            [maxdate] => 2015-09-15 05:59:59
        )

是否有一个 Laravel 辅助函数给定一个数组,我可以指定键和分组顺序?有点像,按 building_name,room_name 分组,这样它将返回一个集合或关联数组,其中“buildings”和“rooms”作为键,使迭代更容易?我可以建造一个,但这似乎是一项常见的任务。 (我确实搜索过)

我正在使用 Eloquent 并为表格制作了模型,但是查询太复杂了,我无法弄清楚如何将其转换为 Eloquent 语句。那么即使有办法使用现有模型创建集合?

(注意我已经弄清楚如何使用关系和查询范围从维护日志 -> 房间 -> 建筑物向后工作。但它将建筑物置于关系的最低级别,我希望它是第一个)

【问题讨论】:

【参考方案1】:

Laravel 提供了一些收集方法,您可以使用这些方法来获取所需的数组 https://laravel.com/docs/5.1/collections#method-put https://laravel.com/docs/5.1/collections#introduction。

为了从您的 $results 中获取关联数组,例如

array:3 [
       "Building 1" => "Room 1"
       "Building 1" => "Room 2"
       "Building 1" => "Room 3"
] 

为了解决你的问题,创建一个集合对象

$collection_obj = collect();

遍历 $results

foreach ($results as $result) 
            $collection_obj->put($result->building_name, $result->room_name);

然后要将您的集合转换为数组,请使用 toArray()

$result_arr = $collection_obj->toArray();

我希望这可以解决您的问题或至少作为参考。

【讨论】:

【参考方案2】:

在建筑类中:

public function rooms()
    return $this->hasMany('App\Room');

在房间类:

public function maintenanceLog()
    return $this->hasMany('App\MaintenanceLog');

在维护日志类中:

public function scopeLongest($query) //you can name it as you like ofc.
    return $query->orderBy('created_at','desc')->first();

终于可以使用了:

foreach(Building::all() as $building)
    foreach($building->rooms() as $room)
        echo 'building: ' . $building->building_name . ' room: ' . $room->room_name . ' maxdate: ' . $room->maintenanceLog()->longest()->created_at;
    

【讨论】:

以上是关于Laravel 5.1 从原始数据库(或只是一个数组)创建集合或关联数组的主要内容,如果未能解决你的问题,请参考以下文章

laravel 5.1 表单验证如何验证数组里面的

laravel 5.1 中 Eloquent 和 Query Builder 有啥区别?

从原始 SQL 到 Laravel Eloquent 或查询构建器

从 Laravel 输出原始 HTML

Laravel 5.1 创建或更新重复

Laravel 5.1用eloquent删除DB中的重复项