批改状态:合格
老师批语:总结的很完整, 不错哟
laravel的查询结果, 是对象数组, 一个对象就是一条表记录. 通过扩展数据库访问类, 把对象数组转换成方便使用的二维数组, 一个数组就是一条表记录.
扩展数据库访问类, 可以找到该类, 在里面增加新方法, 但是这样会破坏框架的源码, 框架升级后, 会被覆盖, 不推荐.
laravel提供了一个叫 Macroable 的 Traits , 凡是使用了 Macroable 的类, 都可以使用其提供的 macro() 方法来扩展类的功能. 而laravel的数据库访问类 \Illuminate\Database\Query\Builder 使用了 Macroable , 所以可以使用 macro() 方法扩展功能.
macro() 方法的调用方式: 调用方法是: [被扩展新方法的laravel内置类]::macro(扩展方法名, 闭包); . 调用 macro() 方法的代码, 应该放在laravel提供的”服务提供者”类中. 具体使用流程:
Macraoable 的 trait , 则这个类就具有了”可宏扩展”性./app/Providers 目录中, 命名方式: XxxServiceProvider.php . 类继承 Illuminate\Support\ServiceProvider 类(好像也可以继承别的类似ServiceProvider类)XxxServiceProvider 中创建 public function boot() {...} 方法, 调用 [被扩展新方法的laravel内置类]::macro(扩展方法名, 闭包); 方法, 在闭包中编写扩展的方法的逻辑./config/app.php 文件中的 providers 数组中注册 XxxServiceProvider 类.代码:
1-服务提供者类 DBServiceProvider.php
<?phpnamespace App\Providers;use Illuminate\Support\ServiceProvider;// 门面类 `Illuminate\Support\Facades\DB` 实际的操作类是 `Illuminate\Database\Query\Builder` 类, 它使用了trait: `Macroable` .use Illuminate\Database\Query\Builder as QueryBuilder;class DBServiceProvider extends ServiceProvider {/*** 必须要有这个方法*/public function boot() {/*** 扩展laravel的DB类,返回二维数组类型的查询结果集*/QueryBuilder::macro('lists', function() {// 这里的$this是指向被扩展类(即, Builder类)$data = $this->get()->toArray();$lists = [];foreach($data as $val) {// 对象强转成数组$lists[] = (array) $val;}return $lists;});/*** 扩展laravel的DB类,获取数组类型的第一条查询结果*/QueryBuilder::macro('getFirst', function() {// 这里的$this是指向被扩展类(即, Builder类)$data = (array) $this->first();return $data;});}}
2-在 /config/app.php 中的 providers 属性中注册内容提供者类(略).
3-在代码中调用扩展的方法( \Illuminate\Support\Facades\DB 是laravel访问数据库的 \Illuminate\Database\Query\Builder 类的门面类)
<?phpnamespace App\Http\Controllers\admins;use App\Http\Controllers\Controller;use Illuminate\Support\Facades\DB;class Admin extends Controller {public function index() {// 像使用DB类默认提供的方法一样使用扩展的方法.$data['admins'] = DB::table('admin')->lists();// 其他业务逻辑略...}}
大部分数据库表之间的关联, 是把一个表A的主键以外键字段的方式放在另一个表B. 若查询A表时, 查询结果能以记录的主键做数组key, 则可在渲染后表数据时, 以外键为key从A表的结果集数组中获取对应的A表记录.
可以使用上一节介绍的扩展数据库访问类的方法, 再扩展一个 keyval(作为key的字段, 作为值的字段[可选]) 方法, 实现上述需求.
1-在服务提供者实现类中( DBServiceProvider )添加 keyval() 方法
/*** 扩展laravel的DB类,把查询结果中的一列作为key,另一列作为value; 若没有指定作为value的列名, 则以整个结果集作为value。*/QueryBuilder::macro('keyval', function($key, $val = null) {// 查询数组$data = $this->lists();// 获取作为key的列$keyColumn = array_column($data, $key);// 判断形参$val的值是否存在if(!empty($val)) {// $val值存在,则把列名为$val的列作为值。$valColumn = array_column($data, $val);if(isset($keyColumn) && isset($valColumn)) {return array_combine($keyColumn, $valColumn);}} else {// $val不存在,则把结果集作为值if(isset($keyColumn)) return array_combine($keyColumn, $data);}// 不能处理的情况,返回空数组return [];});
2-改造查询管理员列表数据控制器方法
<?phpnamespace App\Http\Controllers\admins;use App\Http\Controllers\Controller;use Illuminate\Support\Facades\DB;class Admin extends Controller {public function index() {$data['admins'] = DB::table('admin')->lists();/* 当前业务逻辑值需要查出用户组的组名一个字段,所以并不需要查出所有的字段值 */$groups = DB::table('admin_group')->keyval('gid', 'title');// 传给视图渲染$data['groups'] = $groups;return view('admins/admin/index', $data);}}
3-管理员视图文件中渲染时调用(代码片段)
/* 获取用户所属分组的名称 */<!-- 如果后端的keyval()方法指定了value列名,则使用这个调用取值 --><td>{{$groups[$admin['gid']]}}</td>
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号