[PHP从小白到大牛]-025 PHP-商城项目(一)

843 阅读2分钟

实现后台登录前的准备工作

include include_once require require_once

  • 这四个语句都是用来引入文件
  • includerequire的区别在于, 如果找不到需要引入的文件, include以后的代码, 继续执行, require后面的代码无法执行
  • includeinclude_once 的区别在于, 多次引入同一个文件, include会多次引入, include_once只会引入一次, 好处在于, 可以避免函数重复定义的错误

config.php 配置文件

<?php
// 数据库配置
$arr = [
	'db_host'=>'127.0.0.1',
	'db_port'=>'3306',
	'db_user'=>'root',
	'db_password'=>'root',
	'db_name'=>'shop',
	'db_prefix'=>'',
	'db_charset'=>'utf8'
];
return $arr;

db.func.php 数据库的相关函数

<?php
/**
 * connect 连接数据库
 * 
 * @return resource 连接资源, 失败返回错误信息
 */
function connect(){
	$config = require dirname(__FILE__)."/config.php";
	$link = mysqli_connect(
		$config['db_host'].':'.$config['db_port'],
		$config['db_user'],
		$config['db_password'],
		$config['db_name']
	);
	if(!is_null(mysqli_connect_error())){
		die('数据库连接错误: '.mysqli_connect_error());
	}
	return $link;
}
/**
 * queryOne 查询一条数据
 * 
 * @param  string $sql sql语句
 * 
 * @return array      查询到的关联数组, 没有返回空数组
 */
function queryOne($sql){
	$link = connect();
	$result = mysqli_query($link,$sql);
	$data = [];
	if($result && mysqli_num_rows($result)>0){
		$data = mysqli_fetch_assoc($result);
	}
	return $data;
}
/**
 * queryAll 查询所有数据
 * 
 * @param  string $sql sql语句
 * 
 * @return array 二维关联数组, 没有就返回空数组
 */
function queryAll($sql){
	$link = connect();
	$result = mysqli_query($link,$sql);
	$data = [];
	if($result && mysqli_num_rows($result)>0){
		$data = mysqli_fetch_all($result,MYSQLI_ASSOC);
	}
	return $data;
}
/**
 * getDBPrefix 返回前缀
 * 
 * @return string 数据表的前缀
 */
function getDBPrefix(){
	$config = require dirname(__FILE__)."/config.php";
	return $config['db_prefix'];
}
/**
 * execute 增删改操作
 * 
 * @param  string $sql sql语句
 * 
 * @return bool      有影响行数, true, 没有影响行数, false
 */
function execute($sql){
	$link = connect();
	mysqli_query($link,$sql);
	return mysqli_affected_rows($link)>0;
}

toos.func.php 工具函数/公共函数

<?php
/**
 * setSession 设置session
 *
 * @param string $key    session的名字
 * @param string $value  session的值
 * @param string $prefix session前缀, 用来区分, 前台session还是后台session
 *
 * @return void
 */
function setSession($key, $value, $prefix = '') {
    session_id() || session_start();
    if (!empty($prefix)) {
        $_SESSION[$prefix][$key] = $value;
    } else {
        $_SESSION[$key] = $value;
    }
}
/**
 * getSession 获取session
 *
 * @param  string $key    session名字
 * @param  string $prefix session前缀
 *
 * @return string         session的值, 如果获取不到, 返回空字符串
 */
function getSession($key, $prefix = '') {
    session_id() || session_start();
    if (!empty($prefix)) {
        return isset($_SESSION[$prefix][$key]) ? $_SESSION[$prefix][$key] : '';
    } else {
        return isset($_SESSION[$key]) ? $_SESSION[$key] : '';
    }
}
/**
 * deleteSession 清除session
 *
 * @param  string $key    session名字
 * @param  string $prefix session前缀
 *
 * @return void
 */
function deleteSession($key, $prefix = '') {
    session_id() || session_start();
    if (!empty($prefix)) {
        unset($_SESSION[$prefix][$key]);
    } else {
        unset($_SESSION[$key]);
    }
}
/**
 * setInfo 设置系统消息
 *
 * @param string $info 消息的具体内容
 *
 * @return  void
 */
function setInfo($info) {
    setSession('info', $info, 'system');
}
/**
 * getInfo 获取系统消息
 *
 * @return string 系统消息, 有就返回消息, 没有就空字符串
 */
function getInfo() {
    $info = getSession('info', 'system');
    deleteSession('info', 'system');
    return $info;
}
/**
 * hasInfo 是否有消息需要展示
 *
 * @return boolean 有则返回true, 没有返回false
 */
function hasInfo() {
    return !empty(getSession('info', 'system'));
}

后台登录的实现

引入文件

<?php 
require_once '../db.func.php';
require_once '../tools.func.php';

判断是否点击了登录, 如果没有登录, 先不执行php逻辑, 只展示html页面

if(!empty($_POST['adminuser'])){
    // 省略php代码...
}

连接数据库, 获取表前缀, 接受参数, 拼接sql语句

if (!empty($_POST['adminuser'])) {
    $prefix = getDBPrefix();
    $adminuser = $_POST['adminuser'];
    $adminpass = md5('yunhe_' . md5($_POST['adminpass']));
    // 拼接sql语句
    $sql = "select id,adminuser
        from {$prefix}admin
        where
            adminuser = '{$adminuser}'
        and
            adminpass = '{$adminpass}'
        ";
    // 省略php代码...
}

执行sql语句, 判断结果, 如果有则更新状态, 跳转index.php,

如果没有, 则保存并展示错误信息...

  $result = queryOne($sql);
  if ($result) {
    setSession('admin',['adminuser'=>$result['adminuser'],'id'=>$result['id']],'admin');
    // 当前登陆时间
    $login_at = date('Y-m-d H:i:s');
    // 当前登录IP

    $ip = $_SERVER['REMOTE_ADDR'] == "::1"? '127.0.0.1':$_SERVER['REMOTE_ADDR'];

    $login_ip = ip2long($ip); 

    $sql = "update {$prefix}admin 
    set login_at = '{$login_at}',
    login_ip = '{$login_ip}' 
    where id = {$result['id']}";
    execute($sql);
    header('location:index.php');
  }else{
    setInfo('用户名或密码错误');
  }

在html的代码中, 展示错误信息

// 省略代码...

<div class="card-body">
<p>
    <?php if(hasInfo()) echo getInfo(); ?>
</p>
<form method='post'>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label class="bmd-label-floating">用户名</label>

// 省略代码...