Blogger Information
Blog 64
fans 6
comment 2
visits 83013
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
laravel--通用后台管理系统--分页--图片上传
王娇
Original
1293 people have browsed it

学习总结

1.文章列表的分页,前端使用layui中的laypage进行渲染,后端使用laravel中的paginate(每页显示的记录个数)方法实现文章列表的分页

2.在DBServiceProvider.php中把paginate()进行扩展,扩展后的方法名称为pages()以数组的形式返回所查询到的数据,并且返回数据记录的总数

3.文件上传使用layui的Upload进行文件上传操作,上传的文件通过Upload控制器中的upload_img方法进行存储,并且返回可访问的地址。

5.上传的文件应当存储在storage目录下的public目录下

6.渲染保存在数据库的富文本编辑器中的内容 应该使用{!! $detail['contents'] !!}

1.文章控制器Article.php

  1. <?php
  2. namespace App\Http\Controllers\admins;
  3. use App\Http\Controllers\Controller;
  4. //登录验证
  5. use Illuminate\Support\Facades\Auth;
  6. use Illuminate\Http\Request;
  7. //引入数据库查询构造器,链式调用
  8. use Illuminate\Support\Facades\DB;
  9. //后台文章管理控制器
  10. class Article extends Controller
  11. {
  12. //显示文章列表
  13. public function index(Request $req)
  14. {
  15. $res['page'] =(int)$req->page;//当前显示的是第几页
  16. $limit = 8;//每页显示的记录数
  17. $pageInfo = DB::table('article')->orderby('id','desc')->pages($limit);//pages()方法为自定义的分页方法
  18. $res['articles'] = $pageInfo['data'];//得到分页数据
  19. $res['total'] = $pageInfo['total'];//得到记录总数
  20. $res['limit'] = $limit;//得到每页显示多少条记录
  21. //$res['articles'] = DB::table('article')->paginate(1);
  22. // $res['articles'] = DB::table('article')->lists();
  23. $res['cates'] = DB::table('article_cate')->cate('id');
  24. $res['auths'] = DB::table('admin')->select('id','real_name')->cate('id');
  25. // echo '<pre>';
  26. // print_r($res);
  27. // exit;
  28. return view('/admins/article/index',$res);
  29. }
  30. //添加修改文章
  31. public function add(Request $req)
  32. {
  33. //获取当前登录用户的id
  34. $res['admin_id'] = Auth::user()->id;
  35. //使用aid判断用户是添加文章=0,修改文章aid不为0
  36. $res['aid'] = (int)$req->aid;
  37. $res['article'] = DB::table('article')->where('id',$res['aid'])->item();
  38. //把文章分类数据带入视图中
  39. $res['cates'] = DB::table('article_cate')->lists();
  40. //把文章作者数据带入视图中
  41. $res['auths'] = DB::table('admin')->select('id','real_name')->lists();
  42. //获取文章详情
  43. $res['detail']= DB::table('article_detail')->where('aid',$res['aid'])->item();
  44. // echo '<pre>';
  45. // print_r($res);
  46. // exit;
  47. return view('/admins/article/add',$res);
  48. }
  49. //保存文章
  50. public function save(Request $req)
  51. {
  52. $aid = (int)$req->aid;
  53. $data['title'] = trim($req->title);
  54. if($data['title']==''):
  55. return (json_encode(['status'=>'1','msg'=>'文章标题不能为空']));
  56. endif;
  57. $data['cid'] =(int)$req->cid;
  58. $data['auth_id'] =(int)$req->auth_id;
  59. $data['subtitle'] = trim($req->subtitle);
  60. $data['thumb'] = $req->thumb;
  61. $data['keywords'] = trim($req->keywords);
  62. $data['descs'] = trim($req->descs);
  63. $data['status'] =(int)$req->status;
  64. $content = $req->detail;
  65. // echo '<pre>';
  66. // print_r($data);
  67. // exit;
  68. if($aid==0):
  69. $data['add_time'] =time();
  70. $artIndex = DB::table('article')->insertGetId($data);//插入文章后获取文章id索引
  71. if($artIndex>0):
  72. $res = DB::table('article_detail')->insert(['aid'=>$artIndex,'contents'=>$content]);//把文章详情插入文章内容表中
  73. endif;
  74. else:
  75. $artIndex = DB::table('article')->where('id',$aid)->update($data);//修改文章
  76. $res = DB::table('article_detail')->where('aid',$aid)->update(['contents'=>$content]);//更新文章内容表中的内容
  77. endif;
  78. return json_encode(['status'=>0,'msg'=>'保存成功']);
  79. }
  80. //删除文章
  81. public function del(Request $req)
  82. {
  83. $aid = $req->aid;
  84. $res = DB::table('article')->where('id',$aid)->delete();
  85. $res = DB::table('article_detail')->where('aid',$aid)->delete();
  86. return json_encode(['status'=>0,'msg'=>'删除成功']);
  87. }
  88. public function cates()
  89. {
  90. return view('/admins/article/cates');
  91. }
  92. }

2.显示文章列表,进行分页渲染index.blade.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. <title>文章管理</title>
  9. </head>
  10. <style>
  11. .addBtn {
  12. margin-top: 10px;
  13. width: 120px;
  14. margin-left: auto;
  15. margin-right: 50px;
  16. }
  17. .layui-table {
  18. width: 95%;
  19. margin: 20px;
  20. }
  21. </style>
  22. <body>
  23. <div class="addBtn">
  24. <button class="layui-btn" onclick="add()">添加文章</button>
  25. </div>
  26. <table class="layui-table">
  27. <thead>
  28. <tr>
  29. <th>编号</th>
  30. <th>文章分类</th>
  31. <th>标题</th>
  32. <th>封面图</th>
  33. <th>作者</th>
  34. <th>状态</th>
  35. <th>注册时间</th>
  36. <th>操作</th>
  37. </tr>
  38. </thead>
  39. <tbody>
  40. @foreach($articles as $article)
  41. <tr>
  42. <td>{{$article['id']}}</td>
  43. <td>{{$cates[$article['cid']]['title']}}</td>
  44. <td>{{$article['title']}}</td>
  45. <td><img src="{{$article['thumb']}}" alt="" style="height:30px"></td>
  46. <td>{{$auths[$article['auth_id']]['real_name']}}</td>
  47. <td>{{$article['status']?'已发布':'草稿'}}</td>
  48. <td>{{$article['add_time']?date('Y-m-d',$article['add_time']):''}}</td>
  49. <td>
  50. <button class="layui-btn layui-btn-xs" onclick="add({{$article['id']}})">修改</button>
  51. <button class="layui-btn layui-btn-xs layui-btn-danger"
  52. onclick="del({{$article['id']}})">删除</button>
  53. </td>
  54. </tr>
  55. @endforeach
  56. </tbody>
  57. </table>
  58. <div id="pageList" style="width:500px;margin-left: auto; margin-right:auto;"></div>
  59. </body>
  60. <script>
  61. layui.use(['layer', 'laypage'], function() {
  62. layer = layui.layer;
  63. $ = layui.jquery;
  64. //创建分页
  65. laypage = layui.laypage;
  66. //渲染分页条
  67. laypage.render({
  68. elem: 'pageList',
  69. count:{{$total}}, //数据记录总数
  70. limit: {{$limit}}, //每页显示几条数据
  71. curr:{{ $page }},//当前显示的是第几页的数据
  72. groups: 5, //中间连续显示几个页码
  73. layout:['prev','page','next','skip','count'],
  74. // first: '首页',可以自定义首页,下一页,尾页,上一页的文件显示
  75. // last: '尾页',
  76. // prev: '上一页',
  77. // next: '下一页',
  78. jump: function(obj, first) {
  79. //console.log(obj.curr);当前点击分页条的页码数
  80. if (!first) {
  81. window.location.href="?page="+obj.curr;
  82. }
  83. }
  84. });
  85. });
  86. //添加修改文章
  87. function add(aid) {
  88. //iframe层
  89. layer.open({
  90. type: 2,
  91. title: aid?'修改文章':'添加文章',
  92. shadeClose: true,
  93. shade: 0.8,
  94. area: ['680px', '100%'],
  95. content: '/admins/article/add?aid='+aid, //iframe的url
  96. btn: ['保存'],
  97. yes: function(index, layero) {
  98. //得到iframe页的窗口对象,执行iframe页的方法:iframeWin.子页面的方法名称();
  99. var iframeWin = window[layero.find('iframe')[0]['name']];;
  100. iframeWin.save();
  101. }
  102. });
  103. }
  104. //删除文章
  105. function del(aid) {
  106. layer.confirm('确认要删除文章吗?', function() {
  107. $.get('/admins/article/del?aid=' + aid, function(res) {
  108. if (res.status > 0) {
  109. layer.alert(res.msg, {
  110. icon: 2
  111. });
  112. } else {
  113. layer.msg(res.msg, {
  114. time: 3000
  115. });
  116. window.location.reload();
  117. }
  118. }, 'json');
  119. });
  120. }
  121. </script>
  122. </html>

3.添加或者修改文章add.blade.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. <!-- html文件编辑器配置文件 -->
  9. <script src="/static/plugins/ueditor/ueditor.config.js"></script>
  10. <!-- 编辑器源码文件 -->
  11. <script src="/static/plugins/ueditor/ueditor.all.js"></script>
  12. <title>添加文章</title>
  13. <style>
  14. .layui-form {
  15. margin-top: 20px;
  16. margin-right: 20px;
  17. }
  18. </style>
  19. </head>
  20. <body>
  21. <form action="" class="layui-form">
  22. @csrf
  23. <input type="hidden" name="aid" id="" value="{{ $article['id']?$article['id']:0 }}">
  24. <div class="layui-form-item">
  25. <label for="" class="layui-form-label">标题</label>
  26. <div class="layui-input-block">
  27. <input type="text" class="layui-input" name="title" value="{{ $article['title'] }}">
  28. </div>
  29. </div>
  30. <div class="layui-form-item">
  31. <label for="" class="layui-form-label">作者</label>
  32. <div class="layui-input-block">
  33. <select name="auth_id" id="">
  34. <option value=""></option>
  35. @foreach ($auths as $auth )
  36. @if($aid>0)
  37. {{-- 修改文章时作者id为数据库中保存的作者id --}}
  38. <option value="{{ $auth['id'] }}" {{ $auth['id'] === $article['auth_id']?'selected':'' }}>{{ $auth['real_name'] }}</option>
  39. @else
  40. {{-- 添加文章时作者id为登录用户的id --}}
  41. <option value="{{ $auth['id'] }}" {{ $auth['id'] === $admin_id?'selected':'' }}>{{ $auth['real_name'] }}</option>
  42. @endif
  43. @endforeach
  44. </select>
  45. </div>
  46. </div>
  47. <div class="layui-form-item">
  48. <label for="" class="layui-form-label">文章分类</label>
  49. <div class="layui-input-block">
  50. <select name="cid" id="">
  51. <option value=""></option>
  52. @foreach ($cates as $cate )
  53. <option value="{{ $cate['id'] }}" {{ $cate['id'] === $article['cid']?'selected':'' }}>{{ $cate['title'] }}</option>
  54. @endforeach
  55. </select>
  56. </div>
  57. </div>
  58. <div class="layui-form-item">
  59. <label for="" class="layui-form-label">封面图片</label>
  60. <div class="layui-input-block">
  61. <img src="{{ $article['thumb'] }}" alt="" id="show_thumb" style="height: 30px;">
  62. <button type="button" class="layui-btn" id="thumb">
  63. <i class="layui-icon">&#xe67c;</i>上传图片
  64. </button>
  65. </div>
  66. </div>
  67. <div class="layui-form-item">
  68. <label for="" class="layui-form-label">副标题</label>
  69. <div class="layui-input-block">
  70. <input type="text" class="layui-input" name="subtitle" value="{{ $article['subtitle'] }}">
  71. </div>
  72. </div>
  73. <div class="layui-form-item">
  74. <label for="" class="layui-form-label">关键词</label>
  75. <div class="layui-input-block">
  76. <input type="text" class="layui-input" name="keywords" value="{{ $article['keywords'] }}">
  77. </div>
  78. </div>
  79. <div class="layui-form-item">
  80. <label for="" class="layui-form-label">描述</label>
  81. <div class="layui-input-block">
  82. <textarea class="layui-textarea" name="descs">{{ $article['descs'] }}</textarea>
  83. </div>
  84. </div>
  85. <div class="layui-form-item">
  86. <label for="" class="layui-form-label">是否发布</label>
  87. <div class="layui-input-block">
  88. <input type="checkbox" lay-skin="switch" name="status" lay-text="发布|草稿" {{ $article['status']?'checked':'' }}>
  89. </div>
  90. </div>
  91. <!-- html文本编辑器 -->
  92. <div class="layui-form-item" style="padding-left:10px">
  93. <!-- 加载编辑器的容器 -->
  94. {{-- {!! $detail['contents'] !!} 进行html解析 --}}
  95. <script id="detail" name="detail" type="text/plain">{!! $detail['contents'] !!}</script>
  96. </div>
  97. </form>
  98. </body>
  99. <script>
  100. layui.use(['form', 'layer', 'upload'], function() {
  101. var form = layui.form;
  102. var layer = layui.layer;
  103. $ = layui.jquery;
  104. //<!-- 实例化编辑器 -->
  105. //var ue = UE.getEditor('detail', {
  106. ue = UE.getEditor('detail', {//副文本编辑器去掉var关键字,变成全局变量
  107. initialFrameWidth: '100%', //设定ueditor的宽度
  108. initialFrameHeight: '500' //设定ueditor的高度
  109. });
  110. var upload = layui.upload;
  111. _token = $('input[name="_token"]').val();//_token也去掉var关键字,成为全局变量
  112. //上传封面图片执行实例
  113. var uploadInst = upload.render({
  114. elem: '#thumb' //绑定元素
  115. ,
  116. url: '/admins/upload/upload_img' //上传接口
  117. ,
  118. data: {
  119. _token: _token
  120. },
  121. done: function(res) {
  122. //上传完毕回调
  123. // console.log(res.data.src);
  124. $('#show_thumb').attr('src', res.data.src);
  125. },
  126. error: function() {
  127. //请求异常回调
  128. layer.alert('封面图片上传失败', {
  129. icon: 2
  130. });
  131. }
  132. });
  133. });
  134. //在父窗口中调用了save方法
  135. function save() {
  136. if ($('input[name="title"]').val().trim() === '') {
  137. error('请输入文章标题');
  138. return false;
  139. }
  140. //把form表单中的数据序列化后通过post提交
  141. var data ={
  142. _token:_token,
  143. aid: $('input[name="aid"]').val(),
  144. title: $('input[name="title"]').val(),
  145. auth_id: $('select[name="auth_id"]').val(),
  146. cid: $('select[name="cid"]').val(),
  147. thumb:$('#show_thumb').attr('src'),
  148. subtitle:$('input[name="subtitle"]').val(),
  149. keywords:$('input[name="keywords"]').val(),
  150. descs:$('textarea[name="descs"]').val(),
  151. //获取状态的checed属性值,如果选中保存为1=已发布,否则保存为0=草稿
  152. status:$('input[name="status"]').attr('checked')?1:0,
  153. detail:ue.getContent(),//获取副文本编辑器中的数据
  154. };
  155. //把js对象转换为一个json字符串,然后在网络中传输
  156. JSON.stringify(data);
  157. $.post('/admins/article/save',
  158. data,
  159. function(res) {
  160. if (res.status > 0) {
  161. error(res.msg);
  162. } else {
  163. layer.msg(res.msg);
  164. setTimeout(function() {
  165. //假设这是iframe页
  166. var index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
  167. //关闭当前窗口
  168. parent.layer.close(index); //再执行关闭
  169. //刷新父窗口,重新显示账号管理员列表
  170. parent.window.location.reload();
  171. }, 1000);
  172. }
  173. }, 'json');
  174. function error(msg) {
  175. layer.alert(msg, {
  176. icon: 2
  177. });
  178. }
  179. }
  180. </script>
  181. </html>


4.路由文件web.php

  1. <?php
  2. use Illuminate\Support\Facades\Route;
  3. /*
  4. |--------------------------------------------------------------------------
  5. | Web Routes
  6. |--------------------------------------------------------------------------
  7. |
  8. | Here is where you can register web routes for your application. These
  9. | routes are loaded by the RouteServiceProvider within a group which
  10. | contains the "web" middleware group. Now create something great!
  11. |
  12. */
  13. Route::get('/', function(){
  14. return view('welcome');
  15. });
  16. //登录页面
  17. Route::get('/admins/account/login','admins\Account@login')->name('login');//使用name()方法对路由进行命名
  18. //验证码图片
  19. Route::get('/admins/account/captcha','admins\Account@captcha');
  20. //登录操作
  21. Route::post('/admins/account/dologin','admins\Account@dologin');
  22. //后台首页
  23. //调用框架自带的auth中间件判断是否登录,namespace()方法指定控制器的命令空间,group()方法中是一个回调函数,把一组路由写在这个回调函数中
  24. Route::namespace('admins')->middleware(['auth','rights'])->group(function(){
  25. Route::get('/admins/home/index','Home@index');
  26. Route::get('/admins/home/welcome','Home@welcome');
  27. Route::get('/admins/home/logout','Home@logout');
  28. //账号管理
  29. Route::get('/admins/admin/index','Admin@index');
  30. //添加账号
  31. Route::get('/admins/admin/add','Admin@add');
  32. //修改账号
  33. Route::get('/admins/admin/edit','Admin@edit');
  34. //保存账号
  35. Route::post('/admins/admin/save','Admin@save');
  36. //删除账号
  37. Route::get('/admins/admin/del','Admin@del');
  38. //菜单管理
  39. Route::get('/admins/menus/index','Menus@index');
  40. //添加菜单
  41. Route::get('/admins/menus/add','Menus@add');
  42. //修改菜单
  43. Route::get('/admins/menus/edit','Menus@edit');
  44. //保存菜单
  45. Route::post('/admins/menus/save','Menus@save');
  46. //删除菜单
  47. Route::get('/admins/menus/del','Menus@del');
  48. //角色管理
  49. Route::get('/admins/groups/index','Groups@index');
  50. //添加角色
  51. Route::get('/admins/groups/add','Groups@add');
  52. //修改角色
  53. Route::get('/admins/groups/edit','Groups@edit');
  54. //保存角色
  55. Route::post('/admins/groups/save','Groups@save');
  56. //删除角色
  57. Route::get('/admins/groups/del','Groups@del');
  58. //文章管理
  59. Route::get('/admins/article/index','Article@index');
  60. //添加文章
  61. Route::get('/admins/article/add','Article@add');
  62. //修改文章
  63. Route::get('/admins/article/edit','Article@edit');
  64. //保存文章
  65. Route::post('/admins/article/save','Article@save');
  66. //删除文章
  67. Route::get('/admins/article/del','Article@del');
  68. //文件上传管理
  69. //文章封面上传
  70. Route::post('/admins/upload/upload_img','Upload@upload_img');
  71. });

5.数据库扩展DBserviceProvider.php

  1. <?php
  2. namespace App\Providers;
  3. use Illuminate\Database\Query\Builder as QueryBuilder;
  4. use Illuminate\Support\ServiceProvider;
  5. class DBServiceProvider extends ServiceProvider
  6. {
  7. public function boot()
  8. {
  9. //扩展DB类中的查询结果集的方法,把结果集转换为数组
  10. QueryBuilder::macro('lists',function(){
  11. $res=[];
  12. $data = $this->get()->toArray();
  13. foreach($data as $item):
  14. $res[]=(array)$item;
  15. endforeach;
  16. return $res?$res:false;//判断返回结果是否为空,为空返回false,这样前端渲染数据不容易出错
  17. });
  18. //扩展DB类中的查询结果为一条记录,把结果转换为数组
  19. QueryBuilder::macro('item',function(){
  20. $data=[];
  21. $data = $this->get()->first();
  22. $data = (array)$data;
  23. return $data?$data:false;//判断返回结果是否为空,为空返回false,这样前端渲染数据不容易出错
  24. });
  25. //扩展DB类中的查询结果为数组的索引转换为记录的索引
  26. QueryBuilder::macro('cate',function($index){
  27. $res=[];
  28. $data = $this->lists();
  29. foreach($data as $item):
  30. //把查询结果集中的索引转换为记录中索引号
  31. $res[$item[$index]]=(array)$item;
  32. endforeach;
  33. return $res?$res:false;//判断返回结果是否为空,为空返回false,这样前端渲染数据不容易出错
  34. });
  35. QueryBuilder::macro('pages',function( $perPage = 15,$columns = ['*'],$pageName = 'page',$page = null){
  36. $res= [];
  37. $res['data']=[];
  38. $res['total']=[];
  39. $pageObj = $this->paginate($perPage,$columns,$pageName,$page);
  40. $lists = $pageObj->items();
  41. foreach($lists as $list):
  42. $res['data'][] = (array)$list;
  43. endforeach;
  44. $res['total'] = $pageObj->total();
  45. return $res?$res:false;//判断返回结果是否为空,为空返回false,这样前端渲染数据不容易出错
  46. });
  47. }
  48. }

6.文件上传控制器Upload.php

  1. <?php
  2. namespace App\Http\Controllers\admins;
  3. use App\Http\Controllers\Controller;
  4. //引入storage类,用于文件存储
  5. use Illuminate\Support\Facades\Storage;
  6. use Illuminate\Http\Request;
  7. //引入数据库查询构造器,链式调用
  8. use Illuminate\Support\Facades\DB;
  9. use PhpParser\Node\Expr\FuncCall;
  10. //文件上传控制器
  11. class Upload extends Controller
  12. {
  13. public function upload_img(Request $req)
  14. {
  15. //把上传的文件进行存储,存储在stroage目录中的app目录下的public/thumb
  16. $path = $req->file('file')->store('public/thumb/'.date('Y/m/d'));
  17. //使用
  18. //把存储文件地址转换为能访问的文件地址
  19. $path = Storage::url($path);
  20. // echo '<pre>';
  21. // print_r($path);
  22. // exit;
  23. return json_encode(['status'=>'0','msg'=>'文件上传成功','data'=>['src'=>$path]]);
  24. }
  25. }
Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:坚持 必将 带来收获
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post