批改状态:合格
老师批语:学得时候 会感觉很多的, 实际工作中用得并不是太多的, 不必太担心
管理员列表
admin 外, 还需要获取用户组表 admin_group 的”角色名称”字段值. 暂时先用循环管理员查询结果的方式, 从 admin_group 表中查询对应的角色名称.新增/修改管理员
layui.open() 弹出iframe层的方式打开新增/修改界面. _token (@csrf). password_hash(待加密数据, 加密方式) 来给管理员密码加密. 如: $admin['password'] = password_hash($admin['password'], PASSWORD_DEFAULT); .jQuery 获取checkbox的选中情况: $('input[name="status"]').prop('checked'); , 返回 true / false ; 设置checkbox的选中情况: $('input[name="status"]').prop('checked', true/false) .弹出iframe层的代码片段:
function add() {// 打开iframe弹出层layer.open({// 弹出层的类型, 2 表示已iframe的方式弹出.type: 2,// 弹出界面标题title: '添加新管理员',// 点击弹出窗口外的阴影区域是否关闭弹出窗口shadeClose: false,// 阴影区域的透明度shade: 0.8,// 弹出界面的大小, 可以设置像素值和百分比.area: ['400px', '55%'],// 弹出界面的iframe区域的url地址, 即iframe中要渲染的页面地址content: '/admin/admin/add' //iframe的url});}
权限中间件业务实现中的一些知识点
Auth::user() 可以从 session 中获取保存在其中的登录用户信息.haldler() 方法中, 使用传入的 $request 参数获取请求的控制器名称和方法名称: $request->route()->action['controller'] . namespace\Controller@action , 可以用字符串函数分离出控制器名和方法名.$request 对象的 ajax() 方法, 返回当前请求是否是ajax请求. 当权限验证没有通过时, 可以利用它判断当前请求类型, ajax请求则返回json格式字符串信息, 普通get/post请求返回原始的response相应信息.$routeMiddleware 属性组.路由中, 使用 namespace() 方法给路由加上命名空间, 简化给每条路由添加验证中间件的步骤:
// 使用namespace()方法给路由添加命名空间Route::namespace('admins')->middleware(['auth', 'right.check'])->group(function() {// 用户管理/* 因为加了命名空间, 所以Admin控制前相对Controllers的命名空间前缀admins就可以不写了. 对比上面的'admins\Home@index'... */Route::get('/admin/admin/index', 'Admin@index');Route::get('/admin/admin/add', 'Admin@add');Route::post('/admin/admin/save', 'Admin@save');// 其他路由...}
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>账号列表</title><link rel="stylesheet" href="/static/plugin/layui/css/layui.css"><script src="/static/plugin/layui/layui.js"></script></head><body><div style="text-align: center; color: #666;"><h2>管理员列表</h2></div><div style="float: right; height: 50px; line-height: 50px; padding: 0 10px;"><button class="layui-btn layui-btn-success layui-btn-sm" onclick="add()">新增</button></div><table class="layui-table"><thead><tr style="text-align: center"><th>ID</th><th>用户名</th><th>分组</th><th>真实姓名</th><th>最后登录时间</th><th>用户状态</th><th>操作</th></tr></thead><tbody>@csrf@foreach($admins as $admin)<tr><td>{{$admin['id']}}</td><td>{{$admin['username']}}</td><!-- 如果后端的keyval()方法没有指定value列名,则使用这个调用取值 --><!-- <td>大括号 大括号 $groups【$admin【'gid'】】【'title'】反大括号 反大括号</td> --><!-- 如果后端的keyval()方法指定了value列名,则使用这个调用取值 --><td>{{$groups[$admin['gid']]}}</td><td>{{$admin['real_name']}}</td><td>{{$admin['lastlogin'] ? date('Y-m-d H:i:s', $admin['lastlogin']) : ''}}</td><td>{{$admin['status'] == 0 ? '正常' : '禁用'}}</td><td><button class="layui-btn layui-btn-xs" onclick="edit({{$admin['id']}})">修改</button>@if($admin['status'] == 0)<button class="layui-btn layui-btn-danger layui-btn-xs" onclick="delOrResume(1, {{$admin['id']}}, '{{$admin['username']}}')">删除</button>@else<button class="layui-btn layui-btn-normal layui-btn-xs" onclick="delOrResume(0, {{$admin['id']}}, '{{$admin['username']}}')">恢复</button>@endif</td></tr>@endforeach</tbody></table></body><script>layui.use(['layer'], function() {layer = layui.layer;$ = layui.jquery;});function edit(id) {layer.open({type: 2,title: '修改管理员信息',shadeClose: false,// 应该是阴影区域的透明度shade: 0.8,// 分别是宽,高area: ['400px', '55%'],content: '/admin/admin/edit?id=' + id});}function add() {layer.open({type: 2,title: '添加新管理员',// 点击弹出窗口外的阴影区域是否关闭弹出窗口shadeClose: false,shade: 0.8,area: ['400px', '55%'],content: '/admin/admin/add' //iframe的url});}function delOrResume(status, id, username) {var msg = status == 1 ? '删除' : '恢复';//询问框layer.confirm('确定要' + msg + username + '吗?', {btn: ['确定','取消'] //按钮}, function(){var _token = $('input[name="_token"]').val();$.post('/admin/admin/del_resume', {id: id, resume: status, _token: _token}, function(res) {if(res.status != undefined && res.status == "0") {layer.msg(res.message, {icon: 1});setTimeout(() => {window.location.reload();}, 1000);} else if(res.status != undefined) {layer.alert(res.message, {icon: 2});} else {layer.alert('操作失败', {icon: 2});}// layer.alert(res);}, 'json');}, function() {});}</script></html>
2-添加管理员视图
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>添加新管理员</title><link rel="stylesheet" href="/static/plugin/layui/css/layui.css"><script src="/static/plugin/layui/layui.js"></script><style>body {padding: 10px;}.cms-label {text-align-last: justify;}</style></head><body><form action="" class="layui-form">@csrf<div class="layui-form-item"><label for="username" class="layui-form-label cms-label">用户名</label><div class="layui-input-inline"><input type="text" class="layui-input" name="username" id="username"></div></div><div class="layui-form-item"><label for="gid" class="layui-form-label cms-label">角色</label><div class="layui-input-inline"><select name="gid" id="gid"><option value=""></option>@foreach($groups as $group)<option value="{{$group['gid']}}">{{$group['title']}}</option>@endforeach</select></div></div><div class="layui-form-item"><label for="password" class="layui-form-label cms-label">密码</label><div class="layui-input-inline"><input type="password" name="password" id="password" class="layui-input"></div></div><div class="layui-form-item"><label for="real_name" class="layui-form-label cms-label">姓名</label><div class="layui-input-inline"><input type="text" name="real_name" id="real_name" class="layui-input"></div></div><div class="layui-form-item"><label for="status" class="layui-form-label cms-label">状态</label><div class="layui-input-inline"><input type="checkbox" name="status" id="status" class="layui-input" title="禁用"></div></div><div class="layui-form-item"><div class="layui-input-block"><!-- 设置form中的button是普通button, 给button加type="button" --><button type="button" class="layui-btn" onclick="save()">保存</button></div></div></form></body><script>layui.use(['layer', 'form'], function() {layer = layui.layer;form = layui.form;$ = layui.jquery;});/* 提交保存 */function save() {var username = $.trim($('input[name="username"]').val());var gid = $.trim($("input[name='gid']").val());var password = $.trim($("input[name='password']").val());var status = $('input[name="status"]').prop('checked') ? 0 : 1;if (username == '') {return layer.alert('用户名不能为空', {icon: 2});}if (isNaN(gid)) {return layer.alert('请选择一个角色', {icon: 2});}if (password == '') {return layer.alert('密码不能为空', {icon: 2});}// 提交数据$.post('/admin/admin/save', $('form').serialize(), function(res) {if (res.status != 'undefined' && res.status == '0') {layer.msg(res.message, {icon: 1});setTimeout(() => {window.parent.location.reload();}, 1000);} else if (res.status != 'undefined') {layer.alert(res.message, {icon: 2});} else {layer.alert('保存出错', {icon: 2});}}, 'json');}</script></html>
3- 修改管理员视图
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>修改管理员</title><link rel="stylesheet" href="/static/plugin/layui/css/layui.css"><script src="/static/plugin/layui/layui.js"></script><style>body {padding: 10px;}.cms-label {text-align-last: justify;}</style></head><body><form action="" class="layui-form">@csrf<input type="hidden" name="id" value="{{$admin['id']}}"><div class="layui-form-item"><label for="username" class="layui-form-label cms-label">用户名</label><div class="layui-input-inline"><input type="text" class="layui-input" name="username" id="username" value="{{$admin['username']}}"></div></div><div class="layui-form-item"><label for="gid" class="layui-form-label cms-label">角色</label><div class="layui-input-inline"><select name="gid" id="gid" value="{{$admin['gid']}}"><option value=""></option>@foreach($groups as $group)<option {{$admin['gid'] == $group['gid'] ? 'selected' : ''}} value="{{$group['gid']}}">{{$group['title']}}</option>@endforeach</select></div></div><div class="layui-form-item"><label for="password" class="layui-form-label cms-label">密码</label><div class="layui-input-inline"><input type="password" name="password" id="password" class="layui-input"></div></div><div class="layui-form-item"><label for="real_name" class="layui-form-label cms-label">姓名</label><div class="layui-input-inline"><input type="text" name="real_name" id="real_name" class="layui-input" value="{{$admin['real_name']}}"></div></div><div class="layui-form-item"><label for="status" class="layui-form-label cms-label">状态</label><div class="layui-input-inline"><input type="checkbox" name="status" id="status" class="layui-input" title="禁用" {{$admin['status'] ? 'checked' : ''}}></div></div><div class="layui-form-item"><div class="layui-input-block"><!-- 设置form中的button是普通button, 给button加type="button" --><button type="button" class="layui-btn" onclick="save()">提交</button></div></div></form></body><script>layui.use(['layer', 'form'], function() {layer = layui.layer;form = layui.form;$ = layui.jquery;});/* 提交修改 */function save() {var username = $.trim($('input[name="username"]').val());var gid = $.trim($("input[name='gid']").val());var password = $.trim($("input[name='password']").val());if(username == '') {return layer.alert('用户名不能为空', {icon: 2});}if(isNaN(gid)) {return layer.alert('请选择一个角色', {icon: 2});}// if(password == '') {// return layer.alert('密码不能为空', {icon: 2});// }// 提交数据$.post('/admin/admin/update', $('form').serialize(), function(res) {if(res.status != 'undefined' && res.status == '0') {layer.msg(res.message, {icon: 1});setTimeout(() => {window.parent.location.reload();}, 1000);} else if(res.status != 'undefined') {layer.alert(res.message, {icon: 2});} else {layer.alert('提交出错', {icon: 2});}}, 'json');}</script></html>
4-管理员控制器
<?phpnamespace App\Http\Controllers\admins;use App\Http\Controllers\Controller;use Illuminate\Http\Request;use Illuminate\Support\Facades\Auth;use Illuminate\Support\Facades\DB;class Admin extends Controller {public function index() {//print_r(DB::table('admin')->lists());die;$data['admins'] = DB::table('admin')->lists();// printf('<pre>%s</pre>', print_r($data, true));die;// 取代关联查询的方法1:遍历表1查询结果集A,通过结果集A中的外键去查询表2对应的记录,返回想要的字段值foreach($data['admins'] as &$admin) {$gid = $admin['gid'];// 在循环中查询数据库,效率不好,$adminGroup = DB::table('admin_group')->select('title')->where('gid', $gid)->first();// printf('<pre>%s</pre>', print_r($gName));$admin['gName'] = $adminGroup->title;}// 传给视图渲染$data['groups'] = $groups;return view('admins/admin/index', $data);}/* 跳转到新增管理员界面 */public function add() {$data['groups'] = DB::table('admin_group')->select(['gid', 'title'])->lists();return view('admins/admin/add', $data);}public function save(Request $req) {$admin['username'] = trim($req->username);$admin['password'] = trim($req->password);$admin['gid'] = trim($req->gid);$admin['real_name'] = trim($req->real_name);$admin['status'] = $req->status == 'on' ? 1 : 0;// 判空if($admin['username'] == '') {return json_encode(['status' => 1, 'message' => '用户名不能为空']);}if($admin['password'] == '') {return json_encode(['status' => 1, 'message' => '密码不能为空']);}// 判断该用户名是否已存在$admin_user = DB::table('admin')->where('username', $admin['username'])->first();if($admin_user) {return json_encode(['status' => 1, 'message' => '该用户名已存在']);}// 执行保存/* php提供的密码加密函数 */$admin['password'] = password_hash($admin['password'], PASSWORD_DEFAULT);$admin['add_time'] = time();// 保存数据$res = DB::table('admin')->insert($admin);if($res) {return json_encode(['status' => 0, 'message' => '用户添加成功']);}}public function delOrResume(Request $req) {$id = $req->id;$status = $req->resume == '' ? 1 : $req->resume;$msg = $status ? '删除' : '恢复';// 一般删除是执行update用户状态, 不要物理删除// $res = DB::table('admin')->where('id', $id)->delete();$res = DB::table('admin')->where('id', $id)->update(['status'=>$status]);if($res) {return json_encode(['status' => 0, 'message' => '用户' . $msg . '成功']);} else {return json_encode(['status' => 1, 'message' => '用户' . $msg . '失败']);}}public function edit(Request $req) {$id = $req->id;// 验证$id是否有效if(!filter_var($id, FILTER_VALIDATE_INT, ['option' => [`min_range` => 1]])) {if($req->ajax())return json_encode(['status' => 1, 'message' => '无效的id值']);elsereturn response('无效的id值', 200);}// 验证$id是否存在$admin = DB::table('admin')->where('id', $id)->getFirst();// printf('<pre>%s</pre>', print_r($admin, true));if(empty($admin)) {if($req->ajax())return json_encode(['status' => 1, 'message' => '该管理员不存在']);elsereturn response('该管理员不存在', 200);}$data['admin'] = $admin;$data['groups'] = DB::table('admin_group')->select(['gid', 'title'])->lists();return view('/admins/admin/edit', $data);}public function update(Request $req) {/* echo '<pre>';dump(isset($req->password)); */// 获取所有参数$admin = $req->all();// token不是更新字段项unset($admin['_token']);// 状态值$admin['status'] = (isset($admin['status']) && $admin['status']) == 'on' ? 1 : 0;// 真实姓名$admin['real_name'] = isset($admin['real_name']) ? $admin['real_name'] : '';// 如果if(isset($admin['password'])) {$admin['password'] = password_hash($admin['password'], PASSWORD_DEFAULT);} else {unset($admin['password']);}$id = $admin['id'];unset($admin['id']);// DB::connection()->enableQueryLog(); // 开启QueryLog$res = DB::table('admin')->where('id', $id)->update($admin);// dump(DB::getQueryLog());die;if($res) {return $this->returns($req, '修改成功!', 0);} else {return $this->returns($req, '修改失败!');}}private function returns($req, $msg, $status = 1) {if($req->ajax())return json_encode(['status' => $status, 'message' => $msg]);elsereturn response($msg, 200);}}
5-权限验证中间件
<?phpnamespace App\Http\Middleware;use Closure;use Illuminate\Support\Facades\Auth;use Illuminate\Support\Facades\DB;/* 权限验证中间件 */class RightCheck {public function handle($request, Closure $next, $guard = null) {$loginAdmin = Auth::user();// 当前用户的角色id$gid = $loginAdmin->gid;// 获取角色信息$group = DB::table('admin_group')->where('gid', $gid)->getFirst();// 角色所拥有的权限(json字符串)$rights = [];// 如果角色的权限字段有值if($group && $group['rights']) {// 把json字符串转为php数组(入参的第二个参数为true, 则转为数组; 为false, 则返回php对象)$rights = json_decode($group['rights'], true);} else {return json_encode(['status' => 1, 'message' => '你无权执行此操作']);}// 获取当前请求的控制器和方法/* $routeController的值: namespace\Controller@action */$routeController = $request->route()->action['controller'];/* 转成数组, 拿到最后一个数组元素值 */$routeController = explode('\\', $routeController);/* 弹出最后一个元素 */$routeController = array_pop($routeController);/* 把Controller@action拆分成两个值 */list($controller, $action) = explode('@', $routeController);// dump($controller);dump($action);die;/* 查询当前请求的控制器和方法对应的权限id */$menu = DB::table('admin_menu')->select('mid', 'status')->where('controller', $controller)->where('action', $action)->getFirst();/* 查不到这个请求权限 */if(!$menu) {// return response('该功能不存在', 200);return $this->noRight($request, '该功能不存在');}// dump($menu['mid']); dump($rights);die;// 没有权限if(!in_array($menu['mid'], $rights)) {// 注意,返回必须是底层 response相应, 否则,VerifyCsrfToken.php会报错。return $this->noRight($request, '权限不足');}// 有该权限, 但是该权限被禁用了if($menu['status'] == 1) {// 注意,返回必须是底层 response相应, 否则,VerifyCsrfToken.php会报错。return $this->noRight($request, '该功能已被禁用');}$loginAdmin->rights = $rights;// 把用户信息存到$request对象中$request->loginInfo = $loginAdmin;// 放行return $next($request);}/*** 判断请求是否是ajax请求,若是,则response封装json格式字符串,若不是,则response封装普通文本字符串。*/private function noRight($request, $msg) {// 注意,返回必须是底层 response相应, 否则,VerifyCsrfToken.php会报错。if($request->ajax()) {return response(json_encode(['status'=>1, 'message'=>$msg]), 200);} else {return response($msg, 200);}}}
7-路由
Route::namespace('admins')->middleware(['auth', 'right.check'])->group(function() {// 用户管理/* 因为加了命名空间, 所以Admin控制前相对Controllers的命名空间前缀admins就可以不写了. 对比上面的'admins\Home@index'... */Route::get('/admin/admin/index', 'Admin@index');Route::get('/admin/admin/add', 'Admin@add');Route::post('/admin/admin/save', 'Admin@save');Route::post('/admin/admin/del_resume', 'Admin@delOrResume');Route::get('/admin/admin/edit', 'Admin@edit');Route::post('/admin/admin/update', 'Admin@update');}
可以使用PHP提供的密码加密函数 password_hash(待加密数据, 加密方式) 给管理员密码加密.
使用namespace()方法给多条路由设置命名空间, 把需要在各条路由指定的中间件改成在命名空间指定, 简化路由指定中间件的写法.
复习中间件的使用: 1.创建中间件; 2.注册中间件; 3.触发中间件.
实战课用到的知识好多, 干货太多, 作业很难总结完.
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号