目录
一、内容详细页
项目介绍
本项目分为前台和后台。前台的功能包括用户登录与注册、内容列表、内容详细页、广告展示、评论和热门内容等。后台在未登录的状态下会自动跳转至登录页面。输入用户名“admin”、密码“123456”和验证码后,单击“登录”按钮,即可进行登录。登录后,页面顶部右侧显示了当前登录的用户名“admin”和“退出”按钮,单击“退出”按钮即可退出后台系统。后台页面的左侧有一个菜单栏,用户可以在菜单栏中选择一个菜单项进行操作。项目中需要使用到的技术点包括文件上传、分页和会话技术。整个项目开发基于实现功能的步骤来完成,先实现后台开发,提供数据支持,再完成前台的数据展示。
安装Laravel
首先选择你想在的哪个文件安装Laravel,然后就选择那个文件执行安装Larave命令:composer create-project --prefer-dist laravel/laravel ./ 5.8.*
比如我想在D盘的 phpstudy_pro->WWW 里下载Laravel,则选择到D盘里的 phpstudy_pro->WWW 文件,然后在文件的上面写上cmd按下回车键,就可以进入到该文件的终端,然后执行安装Laravel的命令即可。操作如下图所示。
配置文件
Laravel安装完成后,在Apache的conf\extra\httpd-vhosts.conf配置文件中创建一个虚拟主机。具体配置为:
<VirtualHost *:80>
DocumentRoot "C:/web/apache2.4/htdocs/cms/public"
ServerName cms.com
<VirtualHost>
然后,编辑Apache的hosts文件,添加一条解析记录“127.0.0.1 cms.com”。如下图所示。
登录MySQL服务器,创建数据库cms,将cms作为内容管理系统的数据库。
打开项目,在config\database.php数据库配置文件中,将数据库名称修改为cms。
在.env文件中配置正确的数据库配置信息。全部完成后,即可在项目中访问数据库。
引入需要的静态文件
一、后台用户登录
1.创建用户表
(1)在命令行中执行如下命令创建迁移文件,具体命令如下:
php artisan make:migration create_admin_user_table
(2)执行完上述命令后,会在database\migrations目录下生成文件名称为时间前缀_create_admin_user_table.php的文件 。
(3)在迁移文件的up()方法中添加表结构信息,具体代码如下:
public function up()
{
Schema::create('admin_user', function (Blueprint $table) {
$table->increments('id')->comment('主键');
$table->string('username', 32)->comment('用户名')->unique();
$table->string('password', 32)->comment('密码');
$table->char('salt', 32)->comment('密码salt');
$table->timestamps();
});
}
(4)迁移文件创建完成后,使用如下命令来执行迁移
php artisan migrate
(5)上述命令会执行迁移文件中的up()方法,来完成数据表的创建。
(6)创建填充文件,具体命令如下:
php artisan make:seeder AdminuserTableSeeder
(7)执行完上述命令后,会在database\seeds目录下生成对应的迁移文件,文件名为AdminuserTableSeeder.php。
(8)在填充文件的run()方法中编写填充代码:
public function run()
{
$salt = md5(uniqid(microtime(), true));
$password = md5(md5('123456') . $salt);
DB::table('admin_user')->insert([
[
'id' => 1,
'username' => 'admin',
'password' => $password,
'salt' => $salt
],
]);
}
(9)执行填充文件命令:
php artisan db:seed --class=AdminuserTableSeeder
(10)数据库创建成功后,创建用户模型:
php artisan make:model Admin
(11)打开app\Admin.php,在模型中指定要操作的表名,具体代码如下:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Admin extends Model
{
protected $table = 'admin_user';
public $fillable = ['username', 'password'];
}
2.显示登录页面
(1)创建User控制器,具体代码如下:
php artisan make:controller Admin/UserController
(2)执行完上述命令后,会在app\Http\Controllers\Admin目录下创建UserController.php,命名空间为App\Http\Controllers\Admin。
(3)打开UserController.php,创建login()方法,具体代码如下:
public function login(){
return view('admin/login');
}
(4)在routes\web.php文件中添加路由规则,具体代码如下:
Route::get('/admin/login','Admin\UserController@login');
(5)在resources\views目录下创建admin目录,该目录用于存放后台相关的模板文件。在admin目录中创建login.blade.php文件,具体代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入静态文件 -->
<title>登录</title>
</head>
<body class="login">
<div class="container">
<!-- 登录表单 -->
</div>
</body>
</html>
(6)在上述的第6行引入静态文件,具体代码如下:
<link rel="stylesheet" href="{
{asset('admin')}}/common/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/common/font-awesome-4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/common/toastr.js/2.1.4/toastr.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/css/main.css">
<script src="{
{asset('admin')}}/common/jquery/1.12.4/jquery.min.js"></script>
<script src="{
{asset('admin')}}/common/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script src="{
{asset('admin')}}/common/toastr.js/2.1.4/toastr.min.js"></script>
<script src="{
{asset('admin')}}/js/main.js"></script>
(7)在注释登录表单下面定义登录表单,具体代码如下:
<form action="" method="post" class="j-login">
<h1>后台管理系统</h1>
<div class="form-group">
<input type="text" name="username" class="form-control" placeholder="用户名" required>
</div>
<div class="form-group">
<input type="password" name="password" class="form-control" placeholder="密码" required>
</div>
<div class="form-group">
<input type="text" name="captcha" class="form-control" placeholder="验证码" required>
</div>
<!-- 验证码 -->
<div class="form-group">
{
{csrf_field()}}
<input type="submit" class="btn btn-lg btn-block btn-success" value="登录">
</div>
</form>
(8)使用Composer载入mews/captcha验证码库,具体代码如下:
composer require mews/captcha=3.0
(9)创建验证码的配置文件 ,具体命令如下:
php artisan vendor:publish
(10)执行完上述命令后,在命令行中输入序号“9”并按"Enter"键,就会自动生成config\captcha.php文件。
(11)编辑config\captcha.php文件,将字符个数改为4,具体代码如下:
'default' => [
'length' => 4, //字符个数
'width' => 120, //图片宽度
'height' => 36, //图片高度
'quality' => 90, //图片质量
'math' => false, //数学计算
],
(12)在config\app.php中将验证码服务注册到服务器中,具体代码如下:
'providers' => [
...(原有代码)
Mews\Captcha\CaptchaServiceProvider::class,
...(原有代码)
]
(13)在config\app.php文件中给验证码服务注册别名,具体代码如下:
'aliases' => [
...(原有代码)
'Captcha' =>Mews\Captcha\Facades\Captcha::class,
]
(14)在登录表单中添加验证码,具体代码如下:
<div class="form-group">
<div class="login-captcha"><img src="{
{ captcha_src() }}" alt="captcha"></div>
</div>
(15)通过浏览器访问,其页面效果如下图:
(16)实现单机验证码图片后更换验证码功能,在模板中编写JavaScript代码,具体代码如下:
<script>
$('.login-captcha img').click(function() {
$(this).attr('src', '{
{ captcha_src()}}' + '?_=' + Math.random());
});
</script>
3.Ajax交互
(1)打开public\admin\js\main.js文件,添加如下代码:
(function (window, $, toastr) {
window.main = {
token: '', // 保存令牌
toastr: toastr,
init: function (opt) {
$.extend(this, opt); // 将传入的opt对象合并到自身对象中
toastr.options.positionClass = 'toast-top-center';
return this;
},
ajax: function (opt, success, error) {
opt = (typeof opt === 'string') ? {url: opt} : opt;
var that = this;
var options = {
success: function (data, status, xhr) {
that.hideLoading();
if (!data) {
toastr.error('请求失败,请重试。');
} else if (data.code === 0) {
toastr.error(data.msg);
error && error(data);
} else {
success && success(data);
}
opt.success && opt.success(data, status, xhr);
},
error: function (xhr, status, err) {
that.hideLoading();
toastr.error('请求失败,请重试。');
opt.error && opt.error(xhr, status, err);
}
};
that.showLoading();
$.ajax($.extend({}, opt, options));
},
showLoading: function() {
$('.main-loading').show();
},
hideLoading: function() {
$('.main-loading').hide();
},
};
})(this, jQuery, toastr);
(2)在main对象中编写ajaxPost()方法,具体代码如下:
ajaxPost: function(opt, success, error) {
opt = (typeof opt === 'string') ? {url: opt} : opt;
var that = this;
var callback = opt.success;
opt.type = 'POST';
opt.success = function(data, status, xhr) {
if (data && data.code === 1) {
toastr.success(data.msg);
}
callback && callback(data, status, xhr);
};
that.ajax(opt, success, error);
},
(3)在main.js中编写ajaxForm()方法,用于将表单改为Ajax提交方式,具体代码如下:
ajaxForm: function (selector, success, error) {
var form = $(selector);
var that = this;
form.submit(function (e) {
e.preventDefault();
that.ajaxPost({
url: form.attr('action'),
data: new FormData(form.get(0)),
contentType: false,
processData: false
}, success, error);
});
},
4.验证用户登录
(1)在routes\web.php文件中添加路由规则,具体代码如下:
//登录验证
Route::post('/admin/check','Admin\UserController@check');
(2)在UserController.php中创建check()方法,具体代码如下:
public function check(Request $request)
{
//声明自动验证规则
$rule = [
'username' => 'required',
'password' => 'required|min:6',
'captcha' => 'required|captcha'
];
// 声明自动验证规则对应的提示信息(验证失败返回信息)
$message = [
'username.required' => '用户名不能为空',
'password.required' => '密码不能为空',
'password.min' => '密码最少为6位',
'captcha.required' => '验证码不能为空',
'captcha.captcha' => '验证码有误'
];
//进行自动验证,验证表单提交数据
$validator = Validator::make($request->all(), $rule, $message);
// 输出验证结果并返回给浏览器
if ($validator->fails()) { //验证失败fails()方法
foreach ($validator->getMessageBag()->toArray() as $v) {
$msg = $v[0];
}
return response()->json(['code' => 0, 'msg' => $msg]);
}
// 获取用户输入的用户名、密码信息,以及数据表中用户名、密码信息
$username = $request->get('username');
$password = $request->get('password');
$theUser = Admin::where('username',$username)->first();
// 对用户输入的密码与数据库中的密码进行比较,如果密码正确则登录成功,并将用户信息保存在session中
// 跳转至后台首页,如果登录失败,则显示“登录失败”
if($theUser->password == md5(md5($password). $theUser->salt))
{
Session::put('user', ['id'=>$theUser->id,'name'=>$username]);
return response()->json(['code' => 1, 'msg' => '登录成功']);
}else{
return response()->json(['code' => 0, 'msg' => '登录失败']);
}
}
(3)在上述代码中使用的一些类需要导入命名空间,具体代码如下:
use App\Admin;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
(4)在login.blade.php的<script>标签中添加代码,具体代码如下:
main.ajaxForm('.j-login', function() {
location.href = '/index.php/admin/index';
});
(5)通过浏览器访问,输入小于6位的密码,页面出现“密码最少为6位”的错误提示;输入验证码不正确,页面出现“验证码有误”的错误提示;如果提交正确的用户名(admin)和密码(123456),页面中会出现“登录成功”的提示。
5.用户退出
(1)在User控制器中添加logout()方法,具体代码如下:
public function logout(){
if(request()->session()->has('user')){
request()->session()->pull('user',session('user'));
}
return redirect('/admin/login');
}
(2)在routes\web.php文件中添加路由规则,具体代码如下:
//用户退出
Route::get('/admin/logout','Admin\UserController@logout');
(3)通过浏览器访问,在确保用户已经登录以后,访问http://cms.com/index.php/admin/logout,浏览器会自动跳转到登录页面,说明已经成功退出。
二、后台首页
1.后台页面布局
(1)在layouts目录下创建admin.blade.php文件,具体代码如下 :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--引入静态文件-->
<title>@yield('title')</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light main-navbar">
<a class="navbar-brand" href="#">后台管理系统</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav ml-auto main-nav-right">
<li>
<a href="#" class="j-layout-pwd">
<i class="fa fa-user fa-fw"></i>{
{session()->get('user.name')}}
</a>
</li>
<li>
<a href="{
{url('admin/logout')}}">
<i class="fa fa-power-off fa-fw"></i>退出
</a>
</li>
</ul>
</div>
</nav>
<!-- 后台页面的首页部分 -->
<div class="main-container">
<div class="main-content">
<div>@yield('main')</div>
</div>
</div>
</body>
</html>
(2)在页面引入静态资源,具体代码如下:
<link rel="stylesheet" href="{
{asset('admin')}}/common/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/common/font-awesome-4.2.0/css/font-awesome.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/common/toastr.js/2.1.4/toastr.min.css">
<link rel="stylesheet" href="{
{asset('admin')}}/css/main.css">
<script src="{
{asset('admin')}}/common/jquery/1.12.4/jquery.min.js"></script>
<script src="{
{asset('admin')}}/common/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script src="{
{asset('admin')}}/common/toastr.js/2.1.4/toastr.min.js"></script>
<script src="{
{asset('admin')}}/js/main.js"></script>
(3)在页面中定义左侧导航栏,具体代码如下:
<div class="main-sidebar">
<ul class="nav flex-column main-menu">
</div>
(4)添加首页菜单,具体代码如下:
<li class="">
<a href="{
{url('admin/index')}}" class="active">
<i class="fa fa-home fa-fw"></i>首页
</a>
</li>
(5) 添加栏目菜单,具体代码如下:
<li class="main-sidebar-collapse"> <!-- 被收起的双层项 -->
<a href="#" class="main-sidebar-collapse-btn"> <!-- 链接用于展开或收起子菜单 -->
<i class="fa fa-list-alt fa-fw"></i>栏目
<span class="fa main-sidebar-arrow"></span> <!-- 双层项的右侧小箭头 -->
</a>
<ul class="nav">
<!-- 设置子菜单 -->
<li>
<a href="#" data-name="addcategory">
<i class="fa fa-list fa-fw"></i>添加</a>
</li>
<li>
<a href="#" data-name="category">
<i class="fa fa-table fa-fw"></i>列表</a>
</li>
</ul>
</li>
(6)添加内容表单,具体代码如下:
<li class="main-sidebar-collapse">
<a href="#" class="main-sidebar-collapse-btn">
<i class="fa fa-list-alt fa-fw"></i>内容
<span class="fa main-sidebar-arrow"></span>
</a>
<ul class="nav">
<li>
<a href="#" data-name="addcontent">
<i class="fa fa-list fa-fw"></i>添加</a>
</li>
<li>
<a href="#" data-name="content">
<i class="fa fa-table fa-fw"></i>列表</a>
</li>
</ul>
</li>
(7)添加广告表单,具体代码如下:
<li class="main-sidebar-collapse">
<a href="#" class="main-sidebar-collapse-btn">
<i class="fa fa-cog fa-fw"></i>广告
<span class="fa main-sidebar-arrow"></span>
</a>
<ul class="nav">
<li>
<a href="#" data-name="adv">
<i class="fa fa-list fa-fw"></i>广告位</a>
</li>
<li>
<a href="#" data-name="advcontent">
<i class="fa fa-list-alt fa-fw"></i>广告内容</a>
</li>
</ul>
</li>
(8)添加消息表单,具体代码如下:
@if(!empty(session('message')))
<div class="alert alert-success" role="alert"
style="text-align:center;margin:0 auto;width: 400px">
{
{session('message')}}
</div>
@endif
@if(!empty(session('tip')))
<div class="alert alert-warning" role="alert"
style="text-align:center;margin:0 auto;width: 400px">
{
{session('tip')}}
</div>
@endif
(9)在<body>标签结束前的位置添加<script>标签,控制消息模板的显示时间,具体代码如下:
<script>
// setInterval(myFunction,myTimeLapse),每隔myTimeLapse(毫秒)执行一次myFunction()函数
setInterval(function(){
$('.alert').remove();
},3000);
</script>
(10) 修改public\admin\js\main.js文件,编写layout()方法,具体代码如下:
layout: function() {
$('.main-sidebar-collapse-btn').click(function() {
$(this).parent().find('.nav').slideToggle(200);
$(this).parent().toggleClass('main-sidebar-collapse').siblings().
addClass('main-sidebar-collapse').find('.nav').slideUp(200);
return false;
});
},
(11)在main.js中增加menuActive()方法,用于将指定菜单项设为选中效果,具体代码如下:
menuActive: function(name) {
var menu = $('.main-menu');
menu.find('a').removeClass('active');
menu.find('a[data-name=\'' + name + '\']').addClass('active');
menu.find('a[data-name=\'' + name + '\']').parent().parent().show();
}
(12)在<script>标签中调用layout()方法,具体代码如下:
main.layout();
2.显示后台首页
(1)公共文件创建完成后,接下来创建后台首页admin\index.blade.php,具体代码如下:
@extends('admin/layouts/admin')
@section('title', '后台首页')
@section('main')
<div>
<div class="main-title">
<h2>首页</h2>
</div>
<div class="main-section">
<div class="card">
<div class="card-header">服务器信息</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">系统环境:{
{ $server_version }}</li>
<li class="list-group-item">Laravel版本:{
{ $laravel_version }}</li>
<li class="list-group-item">MySQL版本:{
{ $mysql_version }}</li>
<li class="list-group-item">服务器时间:{
{ $server_time }}</li>
<li class="list-group-item">文件上传限制:{
{ $upload_max_filesize }}</li>
<li class="list-group-item">脚本执行时限:{
{ $max_execution_time }}</li>
</ul>
</div>
</div>
</div>
@endsection
(2)创建Index控制器,具体代码如下:
php artisan make:controller Admin\IndexController
(3) 在Index控制器中添加index()方法,具体代码如下:
public function index(Request $request){
$data = [
'server_version' => $request->server('SERVER_SOFTWARE'),
'laravel_version' => app()::VERSION,
'mysql_version' => $this->getMySQLVer(),
'server_time' => date('Y-m-d H:i:s', time()),
'upload_max_filesize' => ini_get('file_uploads') ?
ini_get('upload_max_filesize') : '已禁用',
'max_execution_time' => ini_get('max_execution_time') . '秒'
];
return view('admin\index', $data);
}
(4)在上述代码中,第六行代码调用getMySQLVer()方法获取MySQL版本,创建getMySQLVer()方法,具体代码如下:
private function getMySQLVer()
{
$res = DB::select('SELECT VERSION() AS ver');
return $res[0]->ver ?? '未知';
}
(5)在getMySQLVer()方法中,使用DB类执行SQL,获取MySQL的版本,导入DB类的命名空间,具体代码如下:
use DB;
(6)在routes\web.php文件中添加路由规则,具体代码如下:
Route::get('/admin/index', 'Admin\IndexController@index');
(7)通过浏览器访问后台首页,其效果如下图: